gtkplacessidebar: implement libcloudproviders support

Add integration of the libcloudproviders DBus API to the
GtkPlacesSidebar by showing name and sync status of the cloud providers.
The exported menu is rendered as a GtkPopover.

The sidebar will be updated if the list of cloudproviders changes e.g.
by adding or removing an account. If any cloud provider changes detailed
information like sync status only the individual sidebar row gets
updated.

Co-authored-by: Carlos Soriano <csoriano@gnome.org>
Co-authored-by: Daniel Boles <dboles@src.gnome.org>

https://bugzilla.gnome.org/show_bug.cgi?id=786123
This commit is contained in:
Julius Härtl 2017-08-10 22:30:36 +02:00 committed by Matthias Clasen
parent 9514ef0d03
commit a1635b6188
9 changed files with 501 additions and 151 deletions

View File

@ -15,6 +15,9 @@
/* Define to 1 if you have the `bind_textdomain_codeset' function. */
#mesondefine HAVE_BIND_TEXTDOMAIN_CODESET
/* Have the cloudproviders library */
#mesondefine HAVE_CLOUDPROVIDERS
/* define if we have colord */
#mesondefine HAVE_COLORD

View File

@ -24,6 +24,10 @@
#include "config.h"
#include <gio/gio.h>
#ifdef HAVE_CLOUDPROVIDERS
#include <cloudproviders/cloudproviders.h>
#include <cloudproviders/cloudprovideraccount.h>
#endif
#include "gtkplacessidebarprivate.h"
#include "gtksidebarrowprivate.h"
@ -121,6 +125,9 @@ struct _GtkPlacesSidebar {
GtkWidget *new_bookmark_row;
GtkBookmarksManager *bookmarks_manager;
#ifdef HAVE_CLOUDPROVIDERS
CloudProviders *cloud_manager;
#endif
GVolumeMonitor *volume_monitor;
GtkTrashMonitor *trash_monitor;
GtkSettings *gtk_settings;
@ -150,6 +157,8 @@ struct _GtkPlacesSidebar {
DropState drop_state;
GtkGesture *long_press_gesture;
GList *cloud_rows;
/* volume mounting - delayed open process */
GtkPlacesOpenFlags go_to_after_mount_open_flags;
GCancellable *cancellable;
@ -164,6 +173,8 @@ struct _GtkPlacesSidebar {
GtkPlacesOpenFlags open_flags;
GActionGroup *action_group;
guint mounting : 1;
guint drag_data_received : 1;
guint drop_occurred : 1;
@ -425,11 +436,17 @@ add_place (GtkPlacesSidebar *sidebar,
GtkPlacesSidebarPlaceType place_type,
GtkPlacesSidebarSectionType section_type,
const gchar *name,
GIcon *icon,
GIcon *start_icon,
GIcon *end_icon,
const gchar *uri,
GDrive *drive,
GVolume *volume,
GMount *mount,
#ifdef HAVE_CLOUDPROVIDERS
CloudProviderAccount *cloud_provider_account,
#else
gpointer *cloud_provider_account,
#endif
const gint index,
const gchar *tooltip)
{
@ -448,7 +465,8 @@ add_place (GtkPlacesSidebar *sidebar,
row = g_object_new (GTK_TYPE_SIDEBAR_ROW,
"sidebar", sidebar,
"icon", icon,
"start-icon", start_icon,
"end-icon", end_icon,
"label", name,
"tooltip", tooltip,
"ejectable", show_eject_button,
@ -459,6 +477,9 @@ add_place (GtkPlacesSidebar *sidebar,
"drive", drive,
"volume", volume,
"mount", mount,
#ifdef HAVE_CLOUDPROVIDERS
"cloud-provider", cloud_provider_account,
#endif
NULL);
eject_button = gtk_sidebar_row_get_eject_button (GTK_SIDEBAR_ROW (row));
@ -582,7 +603,7 @@ add_special_dirs (GtkPlacesSidebar *sidebar)
{
const gchar *path;
GFile *root;
GIcon *icon;
GIcon *start_icon;
gchar *name;
gchar *mount_uri;
gchar *tooltip;
@ -607,18 +628,18 @@ add_special_dirs (GtkPlacesSidebar *sidebar)
if (!name)
name = g_file_get_basename (root);
icon = special_directory_get_gicon (index);
start_icon = special_directory_get_gicon (index);
mount_uri = g_file_get_uri (root);
tooltip = g_file_get_parse_name (root);
add_place (sidebar, PLACES_XDG_DIR,
SECTION_COMPUTER,
name, icon, mount_uri,
NULL, NULL, NULL, 0,
name, start_icon, NULL, mount_uri,
NULL, NULL, NULL, NULL, 0,
tooltip);
g_free (name);
g_object_unref (root);
g_object_unref (icon);
g_object_unref (start_icon);
g_free (mount_uri);
g_free (tooltip);
@ -721,11 +742,11 @@ on_app_shortcuts_query_complete (GObject *source,
gchar *uri;
gchar *tooltip;
const gchar *name;
GIcon *icon;
GIcon *start_icon;
int pos = 0;
name = g_file_info_get_display_name (info);
icon = g_file_info_get_symbolic_icon (info);
start_icon = g_file_info_get_symbolic_icon (info);
uri = g_file_get_uri (file);
tooltip = g_file_get_parse_name (file);
@ -738,8 +759,8 @@ on_app_shortcuts_query_complete (GObject *source,
add_place (sidebar, PLACES_BUILT_IN,
SECTION_COMPUTER,
name, icon, uri,
NULL, NULL, NULL,
name, start_icon, NULL, uri,
NULL, NULL, NULL, NULL,
pos,
tooltip);
@ -794,7 +815,7 @@ on_bookmark_query_info_complete (GObject *source,
gchar *bookmark_name;
gchar *mount_uri;
gchar *tooltip;
GIcon *icon;
GIcon *start_icon;
info = g_file_query_info_finish (root, result, &error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
@ -815,23 +836,23 @@ on_bookmark_query_info_complete (GObject *source,
}
if (info)
icon = g_object_ref (g_file_info_get_symbolic_icon (info));
start_icon = g_object_ref (g_file_info_get_symbolic_icon (info));
else
icon = g_themed_icon_new_with_default_fallbacks (clos->is_native ? ICON_NAME_FOLDER : ICON_NAME_FOLDER_NETWORK);
start_icon = g_themed_icon_new_with_default_fallbacks (clos->is_native ? ICON_NAME_FOLDER : ICON_NAME_FOLDER_NETWORK);
mount_uri = g_file_get_uri (root);
tooltip = g_file_get_parse_name (root);
add_place (sidebar, PLACES_BOOKMARK,
SECTION_BOOKMARKS,
bookmark_name, icon, mount_uri,
NULL, NULL, NULL, clos->index,
bookmark_name, start_icon, NULL, mount_uri,
NULL, NULL, NULL, NULL, clos->index,
tooltip);
g_free (mount_uri);
g_free (tooltip);
g_free (bookmark_name);
g_object_unref (icon);
g_object_unref (start_icon);
out:
g_clear_object (&info);
@ -871,11 +892,69 @@ update_trash_icon (GtkPlacesSidebar *sidebar)
GIcon *icon;
icon = _gtk_trash_monitor_get_icon (sidebar->trash_monitor);
gtk_sidebar_row_set_icon (GTK_SIDEBAR_ROW (sidebar->trash_row), icon);
gtk_sidebar_row_set_start_icon (GTK_SIDEBAR_ROW (sidebar->trash_row), icon);
g_object_unref (icon);
}
}
#ifdef HAVE_CLOUDPROVIDERS
static void
cloud_row_update (CloudProviderAccount *cloud_provider_account,
GtkWidget *cloud_row)
{
GIcon *end_icon;
gint provider_status;
provider_status = cloud_provider_account_get_status (cloud_provider_account);
switch (provider_status)
{
case CLOUD_PROVIDER_STATUS_IDLE:
end_icon = NULL;
break;
case CLOUD_PROVIDER_STATUS_SYNCING:
end_icon = g_themed_icon_new ("emblem-synchronizing-symbolic");
break;
case CLOUD_PROVIDER_STATUS_ERROR:
end_icon = g_themed_icon_new ("dialog-warning-symbolic");
break;
default:
return;
}
gtk_sidebar_row_set_end_icon (GTK_SIDEBAR_ROW (cloud_row), end_icon);
if (end_icon != NULL)
g_object_unref (end_icon);
g_object_set (cloud_row,
"label", cloud_provider_account_get_name (cloud_provider_account),
NULL);
g_object_set (cloud_row,
"tooltip", cloud_provider_account_get_status_details (cloud_provider_account),
NULL);
}
void
cloud_row_destroy (GtkWidget *object,
gpointer user_data)
{
GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (user_data);
CloudProviderAccount *cloud_provider_account = NULL;
g_object_get (GTK_SIDEBAR_ROW (object), "cloud-provider", &cloud_provider_account, NULL);
if (cloud_provider_account != NULL)
{
g_signal_handlers_disconnect_matched (cloud_provider_account,
G_SIGNAL_MATCH_DATA,
0, 0, 0, cloud_row_update, object);
g_object_unref (object);
g_object_unref (cloud_provider_account);
}
sidebar->cloud_rows = g_list_remove (sidebar->cloud_rows, object);
}
#endif
static void
update_places (GtkPlacesSidebar *sidebar)
{
@ -890,11 +969,17 @@ update_places (GtkPlacesSidebar *sidebar)
gchar *original_uri, *name, *identifier;
GtkListBoxRow *selected;
gchar *home_uri;
GIcon *icon;
GIcon *start_icon;
GFile *root;
gchar *tooltip;
GList *network_mounts, *network_volumes;
GIcon *new_bookmark_icon;
#ifdef HAVE_CLOUDPROVIDERS
GIcon *end_icon;
GList *cloud_provider_proxies;
guint provider_status;
gchar *cloudprovider_path;
#endif
GtkStyleContext *context;
/* save original selection */
@ -921,24 +1006,24 @@ update_places (GtkPlacesSidebar *sidebar)
/* add built-in places */
if (should_show_recent (sidebar))
{
icon = g_themed_icon_new_with_default_fallbacks ("document-open-recent-symbolic");
start_icon = g_themed_icon_new_with_default_fallbacks ("document-open-recent-symbolic");
add_place (sidebar, PLACES_BUILT_IN,
SECTION_COMPUTER,
_("Recent"), icon, "recent:///",
NULL, NULL, NULL, 0,
_("Recent"), start_icon, NULL, "recent:///",
NULL, NULL, NULL, NULL, 0,
_("Recent files"));
g_object_unref (icon);
g_object_unref (start_icon);
}
/* home folder */
home_uri = get_home_directory_uri ();
icon = g_themed_icon_new_with_default_fallbacks (ICON_NAME_HOME);
start_icon = g_themed_icon_new_with_default_fallbacks (ICON_NAME_HOME);
add_place (sidebar, PLACES_BUILT_IN,
SECTION_COMPUTER,
_("Home"), icon, home_uri,
NULL, NULL, NULL, 0,
_("Home"), start_icon, NULL, home_uri,
NULL, NULL, NULL, NULL, 0,
_("Open your personal folder"));
g_object_unref (icon);
g_object_unref (start_icon);
g_free (home_uri);
/* desktop */
@ -947,13 +1032,13 @@ update_places (GtkPlacesSidebar *sidebar)
char *mount_uri = get_desktop_directory_uri ();
if (mount_uri)
{
icon = g_themed_icon_new_with_default_fallbacks (ICON_NAME_DESKTOP);
start_icon = g_themed_icon_new_with_default_fallbacks (ICON_NAME_DESKTOP);
add_place (sidebar, PLACES_BUILT_IN,
SECTION_COMPUTER,
_("Desktop"), icon, mount_uri,
NULL, NULL, NULL, 0,
_("Desktop"), start_icon, NULL, mount_uri,
NULL, NULL, NULL, NULL, 0,
_("Open the contents of your desktop in a folder"));
g_object_unref (icon);
g_object_unref (start_icon);
g_free (mount_uri);
}
}
@ -963,32 +1048,83 @@ update_places (GtkPlacesSidebar *sidebar)
if (sidebar->show_enter_location)
{
icon = g_themed_icon_new_with_default_fallbacks (ICON_NAME_NETWORK_SERVER);
start_icon = g_themed_icon_new_with_default_fallbacks (ICON_NAME_NETWORK_SERVER);
add_place (sidebar, PLACES_ENTER_LOCATION,
SECTION_COMPUTER,
_("Enter Location"), icon, NULL,
NULL, NULL, NULL, 0,
_("Enter Location"), start_icon, NULL, NULL,
NULL, NULL, NULL, NULL, 0,
_("Manually enter a location"));
g_object_unref (icon);
g_object_unref (start_icon);
}
/* Trash */
if (!sidebar->local_only && sidebar->show_trash)
{
icon = _gtk_trash_monitor_get_icon (sidebar->trash_monitor);
start_icon = _gtk_trash_monitor_get_icon (sidebar->trash_monitor);
sidebar->trash_row = add_place (sidebar, PLACES_BUILT_IN,
SECTION_COMPUTER,
_("Trash"), icon, "trash:///",
NULL, NULL, NULL, 0,
_("Trash"), start_icon, NULL, "trash:///",
NULL, NULL, NULL, NULL, 0,
_("Open the trash"));
g_object_add_weak_pointer (G_OBJECT (sidebar->trash_row),
(gpointer *) &sidebar->trash_row);
g_object_unref (icon);
g_object_unref (start_icon);
}
/* Application-side shortcuts */
add_application_shortcuts (sidebar);
/* Cloud providers */
#ifdef HAVE_CLOUDPROVIDERS
cloud_provider_proxies = cloud_providers_get_providers (sidebar->cloud_manager);
for (l = cloud_provider_proxies; l != NULL; l = l->next)
{
start_icon = cloud_provider_account_get_icon (l->data);
name = cloud_provider_account_get_name (l->data);
provider_status = cloud_provider_account_get_status (l->data);
cloudprovider_path = cloud_provider_account_get_path (l->data);
if (start_icon == NULL
|| name == NULL
|| provider_status == CLOUD_PROVIDER_STATUS_INVALID
|| cloudprovider_path == NULL)
continue;
cloudprovider_path = g_strconcat ("file://", cloud_provider_account_get_path (l->data), NULL);
switch (provider_status)
{
case CLOUD_PROVIDER_STATUS_IDLE:
end_icon = NULL;
break;
case CLOUD_PROVIDER_STATUS_SYNCING:
end_icon = g_themed_icon_new ("emblem-synchronizing-symbolic");
break;
case CLOUD_PROVIDER_STATUS_ERROR:
end_icon = g_themed_icon_new ("dialog-warning-symbolic");
break;
default:
continue;
}
/* translators: %s is the name of a cloud provider for files */
tooltip = g_strdup_printf (_("Open %s"), name);
GtkWidget *cloud_row = NULL;
cloud_row = add_place (sidebar, PLACES_BUILT_IN,
SECTION_CLOUD,
name, start_icon, end_icon, cloudprovider_path,
NULL, NULL, NULL, l->data, 0,
tooltip);
g_signal_connect (l->data, "changed", G_CALLBACK (cloud_row_update), cloud_row);
g_signal_connect (cloud_row, "destroy", G_CALLBACK (cloud_row_destroy), sidebar);
g_object_ref (cloud_row);
g_object_ref (l->data);
sidebar->cloud_rows = g_list_append (sidebar->cloud_rows, cloud_row);
}
#endif
/* go through all connected drives */
drives = g_volume_monitor_get_connected_drives (sidebar->volume_monitor);
@ -1024,7 +1160,7 @@ update_places (GtkPlacesSidebar *sidebar)
char *mount_uri;
/* Show mounted volume in the sidebar */
icon = g_mount_get_symbolic_icon (mount);
start_icon = g_mount_get_symbolic_icon (mount);
root = g_mount_get_default_location (mount);
mount_uri = g_file_get_uri (root);
name = g_mount_get_name (mount);
@ -1032,11 +1168,11 @@ update_places (GtkPlacesSidebar *sidebar)
add_place (sidebar, PLACES_MOUNTED_VOLUME,
SECTION_MOUNTS,
name, icon, mount_uri,
drive, volume, mount, 0, tooltip);
name, start_icon, NULL, mount_uri,
drive, volume, mount, NULL, 0, tooltip);
g_object_unref (root);
g_object_unref (mount);
g_object_unref (icon);
g_object_unref (start_icon);
g_free (tooltip);
g_free (name);
g_free (mount_uri);
@ -1051,15 +1187,15 @@ update_places (GtkPlacesSidebar *sidebar)
* cue that the user should remember to yank out the media if
* he just unmounted it.
*/
icon = g_volume_get_symbolic_icon (volume);
start_icon = g_volume_get_symbolic_icon (volume);
name = g_volume_get_name (volume);
tooltip = g_strdup_printf (_("Mount and open “%s”"), name);
add_place (sidebar, PLACES_MOUNTED_VOLUME,
SECTION_MOUNTS,
name, icon, NULL,
drive, volume, NULL, 0, tooltip);
g_object_unref (icon);
name, start_icon, NULL, NULL,
drive, volume, NULL, NULL, 0, tooltip);
g_object_unref (start_icon);
g_free (name);
g_free (tooltip);
}
@ -1079,15 +1215,15 @@ update_places (GtkPlacesSidebar *sidebar)
* work.. but it's also for human beings who like to turn off media detection
* in the OS to save battery juice.
*/
icon = g_drive_get_symbolic_icon (drive);
start_icon = g_drive_get_symbolic_icon (drive);
name = g_drive_get_name (drive);
tooltip = g_strdup_printf (_("Mount and open “%s”"), name);
add_place (sidebar, PLACES_BUILT_IN,
SECTION_MOUNTS,
name, icon, NULL,
drive, NULL, NULL, 0, tooltip);
g_object_unref (icon);
name, start_icon, NULL, NULL,
drive, NULL, NULL, NULL, 0, tooltip);
g_object_unref (start_icon);
g_free (tooltip);
g_free (name);
}
@ -1129,18 +1265,18 @@ update_places (GtkPlacesSidebar *sidebar)
{
char *mount_uri;
icon = g_mount_get_symbolic_icon (mount);
start_icon = g_mount_get_symbolic_icon (mount);
root = g_mount_get_default_location (mount);
mount_uri = g_file_get_uri (root);
tooltip = g_file_get_parse_name (root);
name = g_mount_get_name (mount);
add_place (sidebar, PLACES_MOUNTED_VOLUME,
SECTION_MOUNTS,
name, icon, mount_uri,
NULL, volume, mount, 0, tooltip);
name, start_icon, NULL, mount_uri,
NULL, volume, mount, NULL, 0, tooltip);
g_object_unref (mount);
g_object_unref (root);
g_object_unref (icon);
g_object_unref (start_icon);
g_free (name);
g_free (tooltip);
g_free (mount_uri);
@ -1148,13 +1284,13 @@ update_places (GtkPlacesSidebar *sidebar)
else
{
/* see comment above in why we add an icon for an unmounted mountable volume */
icon = g_volume_get_symbolic_icon (volume);
start_icon = g_volume_get_symbolic_icon (volume);
name = g_volume_get_name (volume);
add_place (sidebar, PLACES_MOUNTED_VOLUME,
SECTION_MOUNTS,
name, icon, NULL,
NULL, volume, NULL, 0, name);
g_object_unref (icon);
name, start_icon, NULL, NULL,
NULL, volume, NULL, NULL, 0, name);
g_object_unref (start_icon);
g_free (name);
}
g_object_unref (volume);
@ -1164,13 +1300,13 @@ update_places (GtkPlacesSidebar *sidebar)
/* file system root */
if (!sidebar->show_other_locations)
{
icon = g_themed_icon_new_with_default_fallbacks (ICON_NAME_FILESYSTEM);
start_icon = g_themed_icon_new_with_default_fallbacks (ICON_NAME_FILESYSTEM);
add_place (sidebar, PLACES_BUILT_IN,
SECTION_MOUNTS,
sidebar->hostname, icon, "file:///",
NULL, NULL, NULL, 0,
sidebar->hostname, start_icon, NULL, "file:///",
NULL, NULL, NULL, NULL, 0,
_("Open the contents of the file system"));
g_object_unref (icon);
g_object_unref (start_icon);
}
/* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
@ -1202,17 +1338,17 @@ update_places (GtkPlacesSidebar *sidebar)
continue;
}
icon = g_mount_get_symbolic_icon (mount);
start_icon = g_mount_get_symbolic_icon (mount);
mount_uri = g_file_get_uri (root);
name = g_mount_get_name (mount);
tooltip = g_file_get_parse_name (root);
add_place (sidebar, PLACES_MOUNTED_VOLUME,
SECTION_COMPUTER,
name, icon, mount_uri,
NULL, NULL, mount, 0, tooltip);
name, start_icon, NULL, mount_uri,
NULL, NULL, mount, NULL, 0, tooltip);
g_object_unref (root);
g_object_unref (mount);
g_object_unref (icon);
g_object_unref (start_icon);
g_free (name);
g_free (mount_uri);
g_free (tooltip);
@ -1255,8 +1391,8 @@ update_places (GtkPlacesSidebar *sidebar)
new_bookmark_icon = g_themed_icon_new ("bookmark-new-symbolic");
sidebar->new_bookmark_row = add_place (sidebar, PLACES_DROP_FEEDBACK,
SECTION_BOOKMARKS,
_("New bookmark"), new_bookmark_icon, NULL,
NULL, NULL, NULL, 0,
_("New bookmark"), new_bookmark_icon, NULL, NULL,
NULL, NULL, NULL, NULL, 0,
_("Add a new bookmark"));
context = gtk_widget_get_style_context (sidebar->new_bookmark_row);
gtk_style_context_add_class (context, "sidebar-new-bookmark-row");
@ -1278,15 +1414,15 @@ update_places (GtkPlacesSidebar *sidebar)
}
else
{
icon = g_volume_get_symbolic_icon (volume);
start_icon = g_volume_get_symbolic_icon (volume);
name = g_volume_get_name (volume);
tooltip = g_strdup_printf (_("Mount and open “%s”"), name);
add_place (sidebar, PLACES_MOUNTED_VOLUME,
SECTION_MOUNTS,
name, icon, NULL,
NULL, volume, NULL, 0, tooltip);
g_object_unref (icon);
name, start_icon, NULL, NULL,
NULL, volume, NULL, NULL, 0, tooltip);
g_object_unref (start_icon);
g_free (name);
g_free (tooltip);
}
@ -1299,16 +1435,16 @@ update_places (GtkPlacesSidebar *sidebar)
mount = l->data;
root = g_mount_get_default_location (mount);
icon = g_mount_get_symbolic_icon (mount);
start_icon = g_mount_get_symbolic_icon (mount);
mount_uri = g_file_get_uri (root);
name = g_mount_get_name (mount);
tooltip = g_file_get_parse_name (root);
add_place (sidebar, PLACES_MOUNTED_VOLUME,
SECTION_MOUNTS,
name, icon, mount_uri,
NULL, NULL, mount, 0, tooltip);
name, start_icon, NULL, mount_uri,
NULL, NULL, mount, NULL, 0, tooltip);
g_object_unref (root);
g_object_unref (icon);
g_object_unref (start_icon);
g_free (name);
g_free (mount_uri);
g_free (tooltip);
@ -1321,14 +1457,14 @@ update_places (GtkPlacesSidebar *sidebar)
/* Other locations */
if (sidebar->show_other_locations)
{
icon = g_themed_icon_new_with_default_fallbacks (ICON_NAME_OTHER_LOCATIONS);
start_icon = g_themed_icon_new_with_default_fallbacks (ICON_NAME_OTHER_LOCATIONS);
add_place (sidebar, PLACES_OTHER_LOCATIONS,
SECTION_OTHER_LOCATIONS,
_("Other Locations"), icon, "other-locations:///",
NULL, NULL, NULL, 0, _("Show other locations"));
_("Other Locations"), start_icon, NULL, "other-locations:///",
NULL, NULL, NULL, NULL, 0, _("Show other locations"));
g_object_unref (icon);
g_object_unref (start_icon);
}
gtk_widget_show (GTK_WIDGET (sidebar));
@ -3357,6 +3493,56 @@ on_row_popover_destroy (GtkWidget *row_popover,
sidebar->popover = NULL;
}
#ifdef HAVE_CLOUDPROVIDERS
static void
build_popup_menu_using_gmenu (GtkSidebarRow *row)
{
CloudProviderAccount *cloud_provider_account;
GtkPlacesSidebar *sidebar;
GMenuModel *cloud_provider_menu;
GActionGroup *cloud_provider_action_group;
g_object_get (row,
"sidebar", &sidebar,
"cloud-provider", &cloud_provider_account,
NULL);
/* Cloud provider */
if (cloud_provider_account)
{
GMenu *menu = g_menu_new ();
GMenuItem *item;
item = g_menu_item_new (_("_Open"), "row.open");
g_menu_item_set_action_and_target_value (item, "row.open",
g_variant_new_int32 (GTK_PLACES_OPEN_NORMAL));
g_menu_append_item (menu, item);
item = g_menu_item_new (_("Open in New _Tab"), "row.open-other");
g_menu_item_set_action_and_target_value (item, "row.open-other",
g_variant_new_int32 (GTK_PLACES_OPEN_NEW_TAB));
g_menu_append_item (menu, item);
item = g_menu_item_new (_("Open in New _Window"), "row.open-other");
g_menu_item_set_action_and_target_value (item, "row.open-other",
g_variant_new_int32 (GTK_PLACES_OPEN_NEW_WINDOW));
g_menu_append_item (menu, item);
cloud_provider_menu = cloud_provider_account_get_menu_model (cloud_provider_account);
g_menu_append_section (menu, NULL, cloud_provider_menu);
cloud_provider_action_group = cloud_provider_account_get_action_group (cloud_provider_account);
gtk_widget_insert_action_group (GTK_WIDGET (sidebar),
"cloudprovider",
G_ACTION_GROUP (cloud_provider_action_group));
add_actions (sidebar);
if (sidebar->popover)
gtk_widget_destroy (sidebar->popover);
sidebar->popover = gtk_popover_new_from_model (GTK_WIDGET (sidebar),
G_MENU_MODEL (menu));
g_signal_connect (sidebar->popover, "destroy", G_CALLBACK (on_row_popover_destroy), sidebar);
g_object_unref (sidebar);
g_object_unref (cloud_provider_account);
}
}
#endif
/* Constructs the popover for the sidebar row if needed */
static void
create_row_popover (GtkPlacesSidebar *sidebar,
@ -3365,6 +3551,18 @@ create_row_popover (GtkPlacesSidebar *sidebar,
PopoverData data;
GtkWidget *box;
#ifdef HAVE_CLOUDPROVIDERS
CloudProviderAccount *cloud_provider_account;
g_object_get (row, "cloud-provider", &cloud_provider_account, NULL);
if (cloud_provider_account)
{
build_popup_menu_using_gmenu (row);
return;
}
#endif
sidebar->popover = gtk_popover_new (GTK_WIDGET (sidebar));
/* Clean sidebar pointer when its destroyed, most of the times due to its
* relative_to associated row being destroyed */
@ -3860,6 +4058,17 @@ gtk_places_sidebar_init (GtkPlacesSidebar *sidebar)
g_object_get (sidebar->gtk_settings, "gtk-shell-shows-desktop", &show_desktop, NULL);
sidebar->show_desktop = show_desktop;
/* Cloud providers */
#ifdef HAVE_CLOUDPROVIDERS
sidebar->cloud_rows = NULL;
sidebar->cloud_manager = cloud_providers_dup_singleton ();
g_signal_connect_swapped (sidebar->cloud_manager,
"owners-changed",
G_CALLBACK (update_places),
sidebar);
cloud_providers_update (sidebar->cloud_manager);
#endif
/* populate the sidebar */
update_places (sidebar);

View File

@ -31,6 +31,7 @@ typedef enum {
SECTION_INVALID,
SECTION_COMPUTER,
SECTION_MOUNTS,
SECTION_CLOUD,
SECTION_BOOKMARKS,
SECTION_OTHER_LOCATIONS,
N_SECTIONS

View File

@ -16,6 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gtksidebarrowprivate.h"
/* For section and place type enums */
#include "gtkplacessidebarprivate.h"
@ -27,11 +29,17 @@
#include "gtkrevealer.h"
#include "gtkselection.h"
#ifdef HAVE_CLOUDPROVIDERS
#include <cloudproviders/cloudprovideraccount.h>
#endif
struct _GtkSidebarRow
{
GtkListBoxRow parent_instance;
GIcon *icon;
GtkWidget *icon_widget;
GIcon *start_icon;
GIcon *end_icon;
GtkWidget *start_icon_widget;
GtkWidget *end_icon_widget;
gchar *label;
gchar *tooltip;
GtkWidget *label_widget;
@ -44,6 +52,7 @@ struct _GtkSidebarRow
GDrive *drive;
GVolume *volume;
GMount *mount;
GObject *cloud_provider;
gboolean placeholder;
GtkPlacesSidebar *sidebar;
GtkWidget *revealer;
@ -54,7 +63,8 @@ G_DEFINE_TYPE (GtkSidebarRow, gtk_sidebar_row, GTK_TYPE_LIST_BOX_ROW)
enum
{
PROP_0,
PROP_ICON,
PROP_START_ICON,
PROP_END_ICON,
PROP_LABEL,
PROP_TOOLTIP,
PROP_EJECTABLE,
@ -66,6 +76,7 @@ enum
PROP_DRIVE,
PROP_VOLUME,
PROP_MOUNT,
PROP_CLOUD_PROVIDER,
PROP_PLACEHOLDER,
LAST_PROP
};
@ -86,8 +97,12 @@ gtk_sidebar_row_get_property (GObject *object,
g_value_set_object (value, self->sidebar);
break;
case PROP_ICON:
g_value_set_object (value, self->icon);
case PROP_START_ICON:
g_value_set_object (value, self->start_icon);
break;
case PROP_END_ICON:
g_value_set_object (value, self->end_icon);
break;
case PROP_LABEL:
@ -130,6 +145,10 @@ gtk_sidebar_row_get_property (GObject *object,
g_value_set_object (value, self->mount);
break;
case PROP_CLOUD_PROVIDER:
g_value_set_object (value, self->cloud_provider);
break;
case PROP_PLACEHOLDER:
g_value_set_boolean (value, self->placeholder);
break;
@ -154,9 +173,43 @@ gtk_sidebar_row_set_property (GObject *object,
self->sidebar = g_value_get_object (value);
break;
case PROP_ICON:
gtk_sidebar_row_set_icon (self, g_value_get_object (value));
break;
case PROP_START_ICON:
{
g_clear_object (&self->start_icon);
object = g_value_get_object (value);
if (object != NULL)
{
self->start_icon = g_object_ref (object);
gtk_image_set_from_gicon (GTK_IMAGE (self->start_icon_widget),
self->start_icon,
GTK_ICON_SIZE_MENU);
}
else
{
gtk_image_clear (GTK_IMAGE (self->start_icon_widget));
}
break;
}
case PROP_END_ICON:
{
g_clear_object (&self->end_icon);
object = g_value_get_object (value);
if (object != NULL)
{
self->end_icon = g_object_ref (object);
gtk_image_set_from_gicon (GTK_IMAGE (self->end_icon_widget),
self->end_icon,
GTK_ICON_SIZE_MENU);
gtk_widget_show (self->end_icon_widget);
}
else
{
gtk_image_clear (GTK_IMAGE (self->end_icon_widget));
gtk_widget_hide (self->end_icon_widget);
}
break;
}
case PROP_LABEL:
g_free (self->label);
@ -212,33 +265,48 @@ gtk_sidebar_row_set_property (GObject *object,
g_set_object (&self->mount, g_value_get_object (value));
break;
case PROP_CLOUD_PROVIDER:
{
#ifdef HAVE_CLOUDPROVIDERS
gpointer *object;
object = g_value_get_object (value);
if (IS_CLOUD_PROVIDER_ACCOUNT(object))
self->cloud_provider = g_object_ref (object);
#endif
break;
}
case PROP_PLACEHOLDER:
self->placeholder = g_value_get_boolean (value);
if (self->placeholder)
{
g_clear_object (&self->icon);
g_free (self->label);
self->label = NULL;
g_free (self->tooltip);
self->tooltip = NULL;
gtk_widget_set_tooltip_text (GTK_WIDGET (self), NULL);
self->ejectable = FALSE;
self->section_type = SECTION_BOOKMARKS;
self->place_type = PLACES_BOOKMARK_PLACEHOLDER;
g_free (self->uri);
self->uri = NULL;
g_clear_object (&self->drive);
g_clear_object (&self->volume);
g_clear_object (&self->mount);
{
self->placeholder = g_value_get_boolean (value);
if (self->placeholder)
{
g_clear_object (&self->start_icon);
g_clear_object (&self->end_icon);
g_free (self->label);
self->label = NULL;
g_free (self->tooltip);
self->tooltip = NULL;
gtk_widget_set_tooltip_text (GTK_WIDGET (self), NULL);
self->ejectable = FALSE;
self->section_type = SECTION_BOOKMARKS;
self->place_type = PLACES_BOOKMARK_PLACEHOLDER;
g_free (self->uri);
self->uri = NULL;
g_clear_object (&self->drive);
g_clear_object (&self->volume);
g_clear_object (&self->mount);
gtk_container_foreach (GTK_CONTAINER (self),
(GtkCallback) gtk_widget_destroy,
NULL);
gtk_container_foreach (GTK_CONTAINER (self),
(GtkCallback) gtk_widget_destroy,
NULL);
context = gtk_widget_get_style_context (GTK_WIDGET (self));
gtk_style_context_add_class (context, "sidebar-placeholder-row");
}
break;
context = gtk_widget_get_style_context (GTK_WIDGET (self));
gtk_style_context_add_class (context, "sidebar-placeholder-row");
}
break;
}
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -280,21 +348,41 @@ gtk_sidebar_row_hide (GtkSidebarRow *self,
}
void
gtk_sidebar_row_set_icon (GtkSidebarRow *self,
GIcon *icon)
gtk_sidebar_row_set_start_icon (GtkSidebarRow *self,
GIcon *icon)
{
g_return_if_fail (GTK_IS_SIDEBAR_ROW (self));
if (self->icon != icon)
if (self->start_icon != icon)
{
g_set_object (&self->icon, icon);
if (self->icon != NULL)
gtk_image_set_from_gicon (GTK_IMAGE (self->icon_widget), self->icon,
g_set_object (&self->start_icon, icon);
if (self->start_icon != NULL)
gtk_image_set_from_gicon (GTK_IMAGE (self->start_icon_widget), self->start_icon,
GTK_ICON_SIZE_MENU);
else
gtk_image_clear (GTK_IMAGE (self->icon_widget));
gtk_image_clear (GTK_IMAGE (self->start_icon_widget));
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ICON]);
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_START_ICON]);
}
}
void
gtk_sidebar_row_set_end_icon (GtkSidebarRow *self,
GIcon *icon)
{
g_return_if_fail (GTK_IS_SIDEBAR_ROW (self));
if (self->end_icon != icon)
{
g_set_object (&self->end_icon, icon);
if (self->end_icon != NULL)
gtk_image_set_from_gicon (GTK_IMAGE (self->end_icon_widget), self->end_icon,
GTK_ICON_SIZE_MENU);
else
if (self->end_icon_widget != NULL)
gtk_image_clear (GTK_IMAGE (self->end_icon_widget));
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_END_ICON]);
}
}
@ -303,7 +391,8 @@ gtk_sidebar_row_finalize (GObject *object)
{
GtkSidebarRow *self = GTK_SIDEBAR_ROW (object);
g_clear_object (&self->icon);
g_clear_object (&self->start_icon);
g_clear_object (&self->end_icon);
g_free (self->label);
self->label = NULL;
g_free (self->tooltip);
@ -342,10 +431,18 @@ gtk_sidebar_row_class_init (GtkSidebarRowClass *klass)
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
properties [PROP_ICON] =
g_param_spec_object ("icon",
"icon",
"The place icon.",
properties [PROP_START_ICON] =
g_param_spec_object ("start-icon",
"start-icon",
"The start icon.",
G_TYPE_ICON,
(G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
properties [PROP_END_ICON] =
g_param_spec_object ("end-icon",
"end-icon",
"The end icon.",
G_TYPE_ICON,
(G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
@ -436,6 +533,14 @@ gtk_sidebar_row_class_init (GtkSidebarRowClass *klass)
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
properties [PROP_CLOUD_PROVIDER] =
g_param_spec_object ("cloud-provider",
"CloudProviderAccount",
"CloudProviderAccount",
G_TYPE_OBJECT,
(G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
properties [PROP_PLACEHOLDER] =
g_param_spec_boolean ("placeholder",
"Placeholder",
@ -450,7 +555,8 @@ gtk_sidebar_row_class_init (GtkSidebarRowClass *klass)
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gtk/libgtk/ui/gtksidebarrow.ui");
gtk_widget_class_bind_template_child (widget_class, GtkSidebarRow, icon_widget);
gtk_widget_class_bind_template_child (widget_class, GtkSidebarRow, start_icon_widget);
gtk_widget_class_bind_template_child (widget_class, GtkSidebarRow, end_icon_widget);
gtk_widget_class_bind_template_child (widget_class, GtkSidebarRow, label_widget);
gtk_widget_class_bind_template_child (widget_class, GtkSidebarRow, eject_button);
gtk_widget_class_bind_template_child (widget_class, GtkSidebarRow, revealer);
@ -459,13 +565,13 @@ gtk_sidebar_row_class_init (GtkSidebarRowClass *klass)
gtk_widget_class_set_css_name (widget_class, "row");
}
GtkSidebarRow*
gtk_sidebar_row_clone (GtkSidebarRow *self)
{
return g_object_new (GTK_TYPE_SIDEBAR_ROW,
"sidebar", self->sidebar,
"icon", self->icon,
"start-icon", self->start_icon,
"end-icon", self->end_icon,
"label", self->label,
"tooltip", self->tooltip,
"ejectable", self->ejectable,
@ -476,10 +582,11 @@ gtk_sidebar_row_clone (GtkSidebarRow *self)
"drive", self->drive,
"volume", self->volume,
"mount", self->mount,
"cloud-provider", self->cloud_provider,
NULL);
}
GtkWidget *
GtkWidget*
gtk_sidebar_row_get_eject_button (GtkSidebarRow *self)
{
return self->eject_button;

View File

@ -49,7 +49,9 @@ void gtk_sidebar_row_hide (GtkSidebarRow *self,
void gtk_sidebar_row_reveal (GtkSidebarRow *self);
GtkWidget *gtk_sidebar_row_get_eject_button (GtkSidebarRow *self);
void gtk_sidebar_row_set_icon (GtkSidebarRow *self,
void gtk_sidebar_row_set_start_icon (GtkSidebarRow *self,
GIcon *icon);
void gtk_sidebar_row_set_end_icon (GtkSidebarRow *self,
GIcon *icon);
G_END_DECLS

View File

@ -845,6 +845,10 @@ if x11_enabled or wayland_enabled
gtk_deps += pangoft_dep
endif
if cloudproviders_enabled
gtk_deps += cloudproviders_dep
endif
gtk_settings_schemas = [
'org.gtk.Settings.FileChooser.gschema.xml',
'org.gtk.Settings.ColorChooser.gschema.xml',

View File

@ -16,7 +16,7 @@
<child>
<object class="GtkBox">
<child>
<object class="GtkImage" id="icon_widget">
<object class="GtkImage" id="start_icon_widget">
<style>
<class name="sidebar-icon"/>
</style>
@ -31,6 +31,17 @@
</style>
</object>
</child>
<child>
<object class="GtkImage" id="end_icon_widget">
<property name="visible">False</property>
<property name="hexpand">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
<style>
<class name="sidebar-icon"/>
</style>
</object>
</child>
<child>
<object class="GtkButton" id="eject_button">
<property name="halign">center</property>

View File

@ -24,19 +24,20 @@ else
glib_max_allowed = 'GLIB_VERSION_@0@_@1@'.format(glib_major_req, glib_minor_req)
endif
glib_req = '>= @0@.@1@.@2@'.format(glib_major_req, glib_minor_req, glib_micro_req)
pango_req = '>= 1.37.3'
atk_req = '>= 2.15.1'
cairo_req = '>= 1.14.0'
gdk_pixbuf_req = '>= 2.30.0'
introspection_req = '>= 1.39.0'
wayland_proto_req = '>= 1.7'
wayland_req = '>= 1.9.91'
mirclient_req = '>= 0.22.0'
mircookie_req = '>= 0.17.0'
graphene_req = '>= 1.5.1'
epoxy_req = '>= 1.0'
xkbcommon_req = '>= 0.2.0'
glib_req = '>= @0@.@1@.@2@'.format(glib_major_req, glib_minor_req, glib_micro_req)
pango_req = '>= 1.37.3'
atk_req = '>= 2.15.1'
cairo_req = '>= 1.14.0'
gdk_pixbuf_req = '>= 2.30.0'
introspection_req = '>= 1.39.0'
wayland_proto_req = '>= 1.7'
wayland_req = '>= 1.9.91'
mirclient_req = '>= 0.22.0'
mircookie_req = '>= 0.17.0'
graphene_req = '>= 1.5.1'
epoxy_req = '>= 1.0'
cloudproviders_req = '>= 0.2.0'
xkbcommon_req = '>= 0.2.0'
gnome = import('gnome')
@ -86,12 +87,13 @@ gtk_soversion = '0.@0@.@1@'.format(gtk_binary_age - gtk_interface_age, gtk_inter
gtk_api_version = '4.0'
x11_enabled = get_option('enable-x11-backend')
wayland_enabled = get_option('enable-wayland-backend')
broadway_enabled = get_option('enable-broadway-backend')
mir_enabled = get_option('enable-mir-backend')
quartz_enabled = get_option('enable-quartz-backend')
win32_enabled = get_option('enable-win32-backend')
x11_enabled = get_option('enable-x11-backend')
wayland_enabled = get_option('enable-wayland-backend')
broadway_enabled = get_option('enable-broadway-backend')
mir_enabled = get_option('enable-mir-backend')
quartz_enabled = get_option('enable-quartz-backend')
win32_enabled = get_option('enable-win32-backend')
cloudproviders_enabled = get_option('enable-cloudproviders')
os_unix = false
os_linux = false
@ -505,6 +507,15 @@ else
message('Vulkan support explicitly disabled')
endif
if cloudproviders_enabled
cloudproviders_dep = dependency('cloudproviders', required: true)
if cloudproviders_dep.found()
cdata.set('HAVE_CLOUDPROVIDERS', cloudproviders_dep.found())
else
error('Cloudproviders support not found, but was explicitly requested.')
endif
endif
subdir('modules/input')
subdir('gdk')
subdir('gsk')

View File

@ -22,6 +22,8 @@ option('enable-papi-print-backend', type: 'combo', choices : ['yes', 'no', 'auto
description : 'Enable the papi print backend')
option('enable-cloudprint-print-backend', type: 'combo', choices : ['yes', 'no', 'auto'], value : 'auto',
description : 'Enable the cloudprint print backend')
option('enable-cloudproviders', type: 'boolean', value: false,
description : 'Enable the cloudproviders support')
option('enable-xinerama', type: 'combo', choices : ['yes', 'no', 'auto'], value : 'auto',
description : 'Enable support for the Xinerama extension')
option('disable-modules', type: 'boolean', value : 'false',