places sidebar: Use a popover for the context menu

Use a popover for the context menu, and add a long press gesture
to allow opening it with touch.
This commit is contained in:
Matthias Clasen 2015-07-15 21:25:10 -04:00
parent 186c8f5254
commit e08c5262b7

View File

@ -58,6 +58,9 @@
#include "gtkdnd.h" #include "gtkdnd.h"
#include "gtkseparator.h" #include "gtkseparator.h"
#include "gtkentry.h" #include "gtkentry.h"
#include "gtkgesturelongpress.h"
#include "gtkbox.h"
#include "gtkmodelbutton.h"
/** /**
* SECTION:gtkplacessidebar * SECTION:gtkplacessidebar
@ -135,12 +138,14 @@ struct _GtkPlacesSidebar {
gint drag_root_y; gint drag_root_y;
GtkWidget *row_placeholder; GtkWidget *row_placeholder;
DropState drop_state; DropState drop_state;
GtkGesture *long_press_gesture;
/* volume mounting - delayed open process */ /* volume mounting - delayed open process */
GtkPlacesOpenFlags go_to_after_mount_open_flags; GtkPlacesOpenFlags go_to_after_mount_open_flags;
GCancellable *cancellable; GCancellable *cancellable;
GtkWidget *popup_menu; GtkWidget *popover;
GtkSidebarRow *context_row;
GSList *shortcuts; GSList *shortcuts;
GDBusProxy *hostnamed_proxy; GDBusProxy *hostnamed_proxy;
@ -255,7 +260,11 @@ static gboolean on_button_press_event (GtkWidget *widget,
static gboolean on_button_release_event (GtkWidget *widget, static gboolean on_button_release_event (GtkWidget *widget,
GdkEventButton *event, GdkEventButton *event,
GtkSidebarRow *sidebar); GtkSidebarRow *sidebar);
static void popup_menu_cb (GtkSidebarRow *row); static void popup_menu_cb (GtkSidebarRow *row);
static void long_press_cb (GtkGesture *gesture,
gdouble x,
gdouble y,
GtkPlacesSidebar *sidebar);
static void stop_drop_feedback (GtkPlacesSidebar *sidebar); static void stop_drop_feedback (GtkPlacesSidebar *sidebar);
@ -290,6 +299,7 @@ emit_open_location (GtkPlacesSidebar *sidebar,
location, open_flags); location, open_flags);
} }
#if 0
static void static void
emit_populate_popup (GtkPlacesSidebar *sidebar, emit_populate_popup (GtkPlacesSidebar *sidebar,
GtkMenu *menu, GtkMenu *menu,
@ -299,6 +309,7 @@ emit_populate_popup (GtkPlacesSidebar *sidebar,
g_signal_emit (sidebar, places_sidebar_signals[POPULATE_POPUP], 0, g_signal_emit (sidebar, places_sidebar_signals[POPULATE_POPUP], 0,
menu, selected_item, selected_volume); menu, selected_item, selected_volume);
} }
#endif
static void static void
emit_show_error_message (GtkPlacesSidebar *sidebar, emit_show_error_message (GtkPlacesSidebar *sidebar,
@ -1958,14 +1969,6 @@ drag_drop_callback (GtkWidget *list_box,
return retval; return retval;
} }
/* Callback used when the file list's popup menu is detached */
static void
bookmarks_popup_menu_detach_cb (GtkWidget *attach_widget,
GtkMenu *menu)
{
GTK_PLACES_SIDEBAR (attach_widget)->popup_menu = NULL;
}
static void static void
check_unmount_and_eject (GMount *mount, check_unmount_and_eject (GMount *mount,
GVolume *volume, GVolume *volume,
@ -2039,11 +2042,11 @@ typedef struct {
GtkWidget *rescan_item; GtkWidget *rescan_item;
GtkWidget *start_item; GtkWidget *start_item;
GtkWidget *stop_item; GtkWidget *stop_item;
} PopupMenuData; } PopoverData;
static void static void
check_popup_sensitivity (GtkSidebarRow *row, check_popover_sensitivity (GtkSidebarRow *row,
PopupMenuData *data) PopoverData *data)
{ {
gboolean show_mount; gboolean show_mount;
gboolean show_unmount; gboolean show_unmount;
@ -2055,8 +2058,12 @@ check_popup_sensitivity (GtkSidebarRow *row,
GDrive *drive; GDrive *drive;
GVolume *volume; GVolume *volume;
GMount *mount; GMount *mount;
GtkWidget *sidebar;
GActionGroup *actions;
GAction *action;
g_object_get (row, g_object_get (row,
"sidebar", &sidebar,
"place-type", &type, "place-type", &type,
"drive", &drive, "drive", &drive,
"volume", &volume, "volume", &volume,
@ -2065,9 +2072,12 @@ check_popup_sensitivity (GtkSidebarRow *row,
gtk_widget_set_visible (data->add_shortcut_item, (type == PLACES_MOUNTED_VOLUME)); gtk_widget_set_visible (data->add_shortcut_item, (type == PLACES_MOUNTED_VOLUME));
gtk_widget_set_sensitive (data->remove_item, (type == PLACES_BOOKMARK)); actions = gtk_widget_get_action_group (sidebar, "row");
gtk_widget_set_sensitive (data->rename_item, (type == PLACES_BOOKMARK || action = g_action_map_lookup_action (G_ACTION_MAP (actions), "remove");
type == PLACES_XDG_DIR)); g_simple_action_set_enabled (G_SIMPLE_ACTION (action), (type == PLACES_BOOKMARK));
action = g_action_map_lookup_action (G_ACTION_MAP (actions), "rename");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), (type == PLACES_BOOKMARK ||
type == PLACES_XDG_DIR));
check_visibility (mount, volume, drive, check_visibility (mount, volume, drive,
&show_mount, &show_unmount, &show_eject, &show_rescan, &show_start, &show_stop); &show_mount, &show_unmount, &show_eject, &show_rescan, &show_start, &show_stop);
@ -2081,32 +2091,32 @@ check_popup_sensitivity (GtkSidebarRow *row,
gtk_widget_set_visible (data->stop_item, show_stop); gtk_widget_set_visible (data->stop_item, show_stop);
/* Adjust start/stop items to reflect the type of the drive */ /* Adjust start/stop items to reflect the type of the drive */
gtk_menu_item_set_label (GTK_MENU_ITEM (data->start_item), _("_Start")); g_object_set (data->start_item, "text", _("_Start"), NULL);
gtk_menu_item_set_label (GTK_MENU_ITEM (data->stop_item), _("_Stop")); g_object_set (data->stop_item, "text", _("_Stop"), NULL);
if ((show_start || show_stop) && drive != NULL) if ((show_start || show_stop) && drive != NULL)
{ {
switch (g_drive_get_start_stop_type (drive)) switch (g_drive_get_start_stop_type (drive))
{ {
case G_DRIVE_START_STOP_TYPE_SHUTDOWN: case G_DRIVE_START_STOP_TYPE_SHUTDOWN:
/* start() for type G_DRIVE_START_STOP_TYPE_SHUTDOWN is normally not used */ /* start() for type G_DRIVE_START_STOP_TYPE_SHUTDOWN is normally not used */
gtk_menu_item_set_label (GTK_MENU_ITEM (data->start_item), _("_Power On")); g_object_set (data->start_item, "text", _("_Power On"), NULL);
gtk_menu_item_set_label (GTK_MENU_ITEM (data->stop_item), _("_Safely Remove Drive")); g_object_set (data->stop_item, "text", _("_Safely Remove Drive"), NULL);
break; break;
case G_DRIVE_START_STOP_TYPE_NETWORK: case G_DRIVE_START_STOP_TYPE_NETWORK:
gtk_menu_item_set_label (GTK_MENU_ITEM (data->start_item), _("_Connect Drive")); g_object_set (data->start_item, "text", _("_Connect Drive"), NULL);
gtk_menu_item_set_label (GTK_MENU_ITEM (data->stop_item), _("_Disconnect Drive")); g_object_set (data->stop_item, "text", _("_Disconnect Drive"), NULL);
break; break;
case G_DRIVE_START_STOP_TYPE_MULTIDISK: case G_DRIVE_START_STOP_TYPE_MULTIDISK:
gtk_menu_item_set_label (GTK_MENU_ITEM (data->start_item), _("_Start Multi-disk Device")); g_object_set (data->start_item, "text", _("_Start Multi-disk Device"), NULL);
gtk_menu_item_set_label (GTK_MENU_ITEM (data->stop_item), _("_Stop Multi-disk Device")); g_object_set (data->stop_item, "text", _("_Stop Multi-disk Device"), NULL);
break; break;
case G_DRIVE_START_STOP_TYPE_PASSWORD: case G_DRIVE_START_STOP_TYPE_PASSWORD:
/* stop() for type G_DRIVE_START_STOP_TYPE_PASSWORD is normally not used */ /* stop() for type G_DRIVE_START_STOP_TYPE_PASSWORD is normally not used */
gtk_menu_item_set_label (GTK_MENU_ITEM (data->start_item), _("_Unlock Drive")); g_object_set (data->start_item, "text", _("_Unlock Device"), NULL);
gtk_menu_item_set_label (GTK_MENU_ITEM (data->stop_item), _("_Lock Drive")); g_object_set (data->stop_item, "text", _("_Lock Device"), NULL);
break; break;
default: default:
@ -2122,6 +2132,8 @@ check_popup_sensitivity (GtkSidebarRow *row,
g_object_unref (volume); g_object_unref (volume);
if (mount) if (mount)
g_object_unref (mount); g_object_unref (mount);
g_object_unref (sidebar);
} }
static void static void
@ -2290,42 +2302,31 @@ open_row (GtkSidebarRow *row,
g_free (uri); g_free (uri);
} }
/* Callback used for the "Open" menu item in the context menu */ /* Callback used for the "Open" menu items in the context menu */
static void static void
open_shortcut_cb (GtkMenuItem *item, open_shortcut_cb (GSimpleAction *action,
GtkSidebarRow *row) GVariant *parameter,
gpointer data)
{ {
open_row (row, GTK_PLACES_OPEN_NORMAL); GtkPlacesSidebar *sidebar = data;
} GtkPlacesOpenFlags flags;
/* Callback used for the "Open in new tab" menu item in the context menu */ flags = (GtkPlacesOpenFlags)g_variant_get_int32 (parameter);
static void open_row (sidebar->context_row, flags);
open_shortcut_in_new_tab_cb (GtkMenuItem *item,
GtkSidebarRow *row)
{
open_row (row, GTK_PLACES_OPEN_NEW_TAB);
}
/* Callback used for the "Open in new window" menu item in the context menu */
static void
open_shortcut_in_new_window_cb (GtkMenuItem *item,
GtkSidebarRow *row)
{
open_row (row, GTK_PLACES_OPEN_NEW_WINDOW);
} }
/* Add bookmark for the selected item - just used from mount points */ /* Add bookmark for the selected item - just used from mount points */
static void static void
add_shortcut_cb (GtkMenuItem *item, add_shortcut_cb (GSimpleAction *action,
GtkSidebarRow *row) GVariant *parameter,
gpointer data)
{ {
GtkPlacesSidebar *sidebar = data;
gchar *uri; gchar *uri;
gchar *name; gchar *name;
GFile *location; GFile *location;
GtkPlacesSidebar *sidebar;
g_object_get (row, g_object_get (sidebar->context_row,
"sidebar", &sidebar,
"uri", &uri, "uri", &uri,
"label", &name, "label", &name,
NULL); NULL);
@ -2338,7 +2339,6 @@ add_shortcut_cb (GtkMenuItem *item,
g_object_unref (location); g_object_unref (location);
} }
g_object_unref (sidebar);
g_free (uri); g_free (uri);
g_free (name); g_free (name);
} }
@ -2505,10 +2505,13 @@ rename_bookmark (GtkSidebarRow *row)
} }
static void static void
rename_shortcut_cb (GtkMenuItem *item, rename_shortcut_cb (GSimpleAction *action,
GtkSidebarRow *row) GVariant *parameter,
gpointer data)
{ {
rename_bookmark (row); GtkPlacesSidebar *sidebar = data;
rename_bookmark (sidebar->context_row);
} }
static void static void
@ -2537,29 +2540,31 @@ remove_bookmark (GtkSidebarRow *row)
} }
static void static void
remove_shortcut_cb (GtkMenuItem *item, remove_shortcut_cb (GSimpleAction *action,
GtkSidebarRow *row) GVariant *parameter,
gpointer data)
{ {
remove_bookmark (row); GtkPlacesSidebar *sidebar = data;
remove_bookmark (sidebar->context_row);
} }
static void static void
mount_shortcut_cb (GtkMenuItem *item, mount_shortcut_cb (GSimpleAction *action,
GtkSidebarRow *row) GVariant *parameter,
gpointer data)
{ {
GtkPlacesSidebar *sidebar = data;
GVolume *volume; GVolume *volume;
GtkPlacesSidebar *sidebar;
g_object_get (row, g_object_get (sidebar->context_row,
"volume", &volume, "volume", &volume,
"sidebar", &sidebar,
NULL); NULL);
if (volume != NULL) if (volume != NULL)
mount_volume (sidebar, volume); mount_volume (sidebar, volume);
g_object_unref (volume); g_object_unref (volume);
g_object_unref (sidebar);
} }
/* Callback used from g_mount_unmount_with_operation() */ /* Callback used from g_mount_unmount_with_operation() */
@ -2800,20 +2805,19 @@ do_unmount (GMount *mount,
} }
static void static void
unmount_shortcut_cb (GtkMenuItem *item, unmount_shortcut_cb (GSimpleAction *action,
GtkSidebarRow *row) GVariant *parameter,
gpointer data)
{ {
GtkPlacesSidebar *sidebar; GtkPlacesSidebar *sidebar = data;;
GMount *mount; GMount *mount;
g_object_get (row, g_object_get (sidebar->context_row,
"sidebar", &sidebar,
"mount", &mount, "mount", &mount,
NULL); NULL);
do_unmount (mount, sidebar); do_unmount (mount, sidebar);
g_object_unref (sidebar);
if (mount) if (mount)
g_object_unref (mount); g_object_unref (mount);
} }
@ -2974,16 +2978,16 @@ do_eject (GMount *mount,
} }
static void static void
eject_shortcut_cb (GtkMenuItem *item, eject_shortcut_cb (GSimpleAction *action,
GtkSidebarRow *row) GVariant *parameter,
gpointer data)
{ {
GtkPlacesSidebar *sidebar = data;
GMount *mount; GMount *mount;
GVolume *volume; GVolume *volume;
GDrive *drive; GDrive *drive;
GtkPlacesSidebar *sidebar;
g_object_get (row, g_object_get (sidebar->context_row,
"sidebar", &sidebar,
"mount", &mount, "mount", &mount,
"volume", &volume, "volume", &volume,
"drive", &drive, "drive", &drive,
@ -2991,7 +2995,6 @@ eject_shortcut_cb (GtkMenuItem *item,
do_eject (mount, volume, drive, sidebar); do_eject (mount, volume, drive, sidebar);
g_object_unref (sidebar);
if (mount) if (mount)
g_object_unref (mount); g_object_unref (mount);
if (volume) if (volume)
@ -3084,14 +3087,14 @@ drive_poll_for_media_cb (GObject *source_object,
} }
static void static void
rescan_shortcut_cb (GtkMenuItem *item, rescan_shortcut_cb (GSimpleAction *action,
GtkSidebarRow *row) GVariant *parameter,
gpointer data)
{ {
GtkPlacesSidebar *sidebar; GtkPlacesSidebar *sidebar = data;
GDrive *drive; GDrive *drive;
g_object_get (row, g_object_get (sidebar->context_row,
"sidebar", &sidebar,
"drive", &drive, "drive", &drive,
NULL); NULL);
@ -3100,8 +3103,6 @@ rescan_shortcut_cb (GtkMenuItem *item,
g_drive_poll_for_media (drive, NULL, drive_poll_for_media_cb, g_object_ref (sidebar)); g_drive_poll_for_media (drive, NULL, drive_poll_for_media_cb, g_object_ref (sidebar));
g_object_unref (drive); g_object_unref (drive);
} }
g_object_unref (sidebar);
} }
static void static void
@ -3134,14 +3135,14 @@ drive_start_cb (GObject *source_object,
} }
static void static void
start_shortcut_cb (GtkMenuItem *item, start_shortcut_cb (GSimpleAction *action,
GtkSidebarRow *row) GVariant *parameter,
gpointer data)
{ {
GtkPlacesSidebar *sidebar; GtkPlacesSidebar *sidebar = data;
GDrive *drive; GDrive *drive;
g_object_get (row, g_object_get (sidebar->context_row,
"sidebar", &sidebar,
"drive", &drive, "drive", &drive,
NULL); NULL);
@ -3156,19 +3157,17 @@ start_shortcut_cb (GtkMenuItem *item,
g_object_unref (mount_op); g_object_unref (mount_op);
g_object_unref (drive); g_object_unref (drive);
} }
g_object_unref (sidebar);
} }
static void static void
stop_shortcut_cb (GtkMenuItem *item, stop_shortcut_cb (GSimpleAction *action,
GtkSidebarRow *row) GVariant *parameter,
gpointer data)
{ {
GtkPlacesSidebar *sidebar; GtkPlacesSidebar *sidebar = data;
GDrive *drive; GDrive *drive;
g_object_get (row, g_object_get (sidebar->context_row,
"sidebar", &sidebar,
"drive", &drive, "drive", &drive,
NULL); NULL);
@ -3183,8 +3182,6 @@ stop_shortcut_cb (GtkMenuItem *item,
g_object_unref (mount_op); g_object_unref (mount_op);
g_object_unref (drive); g_object_unref (drive);
} }
g_object_unref (sidebar);
} }
static gboolean static gboolean
@ -3280,195 +3277,142 @@ on_key_press_event (GtkWidget *widget,
return FALSE; return FALSE;
} }
static GtkMenuItem * static GActionEntry entries[] = {
append_menu_separator (GtkMenu *menu) { "open", open_shortcut_cb, "i", NULL, NULL },
{ "bookmark", add_shortcut_cb, NULL, NULL, NULL },
{ "remove", remove_shortcut_cb, NULL, NULL, NULL },
{ "rename", rename_shortcut_cb, NULL, NULL, NULL },
{ "mount", mount_shortcut_cb, NULL, NULL, NULL },
{ "unmount", unmount_shortcut_cb, NULL, NULL, NULL },
{ "eject", eject_shortcut_cb, NULL, NULL, NULL },
{ "rescan", rescan_shortcut_cb, NULL, NULL, NULL },
{ "start", start_shortcut_cb, NULL, NULL, NULL },
{ "stop", stop_shortcut_cb, NULL, NULL, NULL },
};
static void
add_actions (GtkPlacesSidebar *sidebar)
{ {
GtkWidget *menu_item; GActionGroup *actions;
menu_item = gtk_separator_menu_item_new (); actions = G_ACTION_GROUP (g_simple_action_group_new ());
gtk_widget_show (menu_item); g_action_map_add_action_entries (G_ACTION_MAP (actions),
gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menu_item, -1); entries, G_N_ELEMENTS (entries),
sidebar);
return GTK_MENU_ITEM (menu_item); gtk_widget_insert_action_group (GTK_WIDGET (sidebar), "row", actions);
g_object_unref (actions);
} }
/* Constructs the popup menu for the file list if needed */ static GtkWidget *
static void append_separator (GtkWidget *box)
bookmarks_build_popup_menu (GtkSidebarRow *row) {
GtkWidget *separator;
separator = g_object_new (GTK_TYPE_SEPARATOR,
"orientation", GTK_ORIENTATION_HORIZONTAL,
"visible", TRUE,
"margin-start", 12,
"margin-end", 12,
"margin-top", 6,
"margin-bottom", 6,
NULL);
gtk_container_add (GTK_CONTAINER (box), separator);
return separator;
}
static GtkWidget *
add_button (GtkWidget *box,
const gchar *label,
const gchar *action)
{ {
PopupMenuData menu_data;
GtkWidget *item; GtkWidget *item;
GFile *file;
gchar *uri;
GVolume *volume;
GtkPlacesSidebar *sidebar;
g_object_get (row, item = g_object_new (GTK_TYPE_MODEL_BUTTON,
"sidebar", &sidebar, "visible", TRUE,
"uri", &uri, "action-name", action,
"volume", &volume, "text", label,
NULL); NULL);
gtk_container_add (GTK_CONTAINER (box), item);
sidebar->popup_menu = gtk_menu_new (); return item;
gtk_style_context_add_class (gtk_widget_get_style_context (sidebar->popup_menu), }
GTK_STYLE_CLASS_CONTEXT_MENU);
gtk_menu_attach_to_widget (GTK_MENU (sidebar->popup_menu), static GtkWidget *
GTK_WIDGET (sidebar), add_open_button (GtkWidget *box,
bookmarks_popup_menu_detach_cb); const gchar *label,
GtkPlacesOpenFlags flags)
{
GtkWidget *item;
item = gtk_menu_item_new_with_mnemonic (_("_Open")); item = g_object_new (GTK_TYPE_MODEL_BUTTON,
g_signal_connect (item, "activate", "visible", TRUE,
G_CALLBACK (open_shortcut_cb), row); "action-name", "row.open",
gtk_widget_show (item); "action-target", g_variant_new_int32 (flags),
gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item); "text", label,
NULL);
gtk_container_add (GTK_CONTAINER (box), item);
return item;
}
/* Constructs the popover for the sidebar row if needed */
static void
create_row_popover (GtkPlacesSidebar *sidebar,
GtkSidebarRow *row)
{
PopoverData data;
GtkWidget *box;
sidebar->popover = gtk_popover_new (GTK_WIDGET (sidebar));
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
g_object_set (box, "margin", 10, NULL);
gtk_widget_show (box);
gtk_container_add (GTK_CONTAINER (sidebar->popover), box);
add_open_button (box, _("_Open"), GTK_PLACES_OPEN_NORMAL);
if (sidebar->open_flags & GTK_PLACES_OPEN_NEW_TAB) if (sidebar->open_flags & GTK_PLACES_OPEN_NEW_TAB)
{ add_open_button (box, _("Open in New _Tab"), GTK_PLACES_OPEN_NEW_TAB);
item = gtk_menu_item_new_with_mnemonic (_("Open in New _Tab"));
g_signal_connect (item, "activate",
G_CALLBACK (open_shortcut_in_new_tab_cb), row);
gtk_widget_show (item);
gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
}
if (sidebar->open_flags & GTK_PLACES_OPEN_NEW_WINDOW) if (sidebar->open_flags & GTK_PLACES_OPEN_NEW_WINDOW)
{ add_open_button (box, _("Open in New _Window"), GTK_PLACES_OPEN_NEW_WINDOW);
item = gtk_menu_item_new_with_mnemonic (_("Open in New _Window"));
g_signal_connect (item, "activate",
G_CALLBACK (open_shortcut_in_new_window_cb), row);
gtk_widget_show (item);
gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
}
append_menu_separator (GTK_MENU (sidebar->popup_menu)); append_separator (box);
item = gtk_menu_item_new_with_mnemonic (_("_Add Bookmark")); data.add_shortcut_item = add_button (box, _("_Add Bookmark"), "row.bookmark");
menu_data.add_shortcut_item = item; data.remove_item = add_button (box, _("_Remove"), "row.remove");
g_signal_connect (item, "activate", data.rename_item = add_button (box, _("Rename…"), "row.rename");
G_CALLBACK (add_shortcut_cb), row);
gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
item = gtk_menu_item_new_with_label (_("Remove")); data.separator_item = append_separator (box);
menu_data.remove_item = item;
g_signal_connect (item, "activate",
G_CALLBACK (remove_shortcut_cb), row);
gtk_widget_show (item);
gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
item = gtk_menu_item_new_with_label (_("Rename…")); data.mount_item = add_button (box, _("_Mount"), "row.mount");
menu_data.rename_item = item; data.unmount_item = add_button (box, _("_Unmount"), "row.unmount");
g_signal_connect (item, "activate", data.eject_item = add_button (box, _("_Eject"), "row.eject");
G_CALLBACK (rename_shortcut_cb), row); data.rescan_item = add_button (box, _("_Detect Media"), "row.rescan");
gtk_widget_show (item); data.start_item = add_button (box, _("_Start"), "row.start");
gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item); data.stop_item = add_button (box, _("_Stop"), "row.stop");
/* Mount/Unmount/Eject menu items */
menu_data.separator_item = GTK_WIDGET (append_menu_separator (GTK_MENU (sidebar->popup_menu)));
item = gtk_menu_item_new_with_mnemonic (_("_Mount"));
menu_data.mount_item = item;
g_signal_connect (item, "activate",
G_CALLBACK (mount_shortcut_cb), row);
gtk_widget_show (item);
gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
item = gtk_menu_item_new_with_mnemonic (_("_Unmount"));
menu_data.unmount_item = item;
g_signal_connect (item, "activate",
G_CALLBACK (unmount_shortcut_cb), row);
gtk_widget_show (item);
gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
item = gtk_menu_item_new_with_mnemonic (_("_Eject"));
menu_data.eject_item = item;
g_signal_connect (item, "activate",
G_CALLBACK (eject_shortcut_cb), row);
gtk_widget_show (item);
gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
item = gtk_menu_item_new_with_mnemonic (_("_Detect Media"));
menu_data.rescan_item = item;
g_signal_connect (item, "activate",
G_CALLBACK (rescan_shortcut_cb), row);
gtk_widget_show (item);
gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
item = gtk_menu_item_new_with_mnemonic (_("_Start"));
menu_data.start_item = item;
g_signal_connect (item, "activate",
G_CALLBACK (start_shortcut_cb), row);
gtk_widget_show (item);
gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
item = gtk_menu_item_new_with_mnemonic (_("_Stop"));
menu_data.stop_item = item;
g_signal_connect (item, "activate",
G_CALLBACK (stop_shortcut_cb), row);
gtk_widget_show (item);
gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
/* Update everything! */ /* Update everything! */
check_popover_sensitivity (row, &data);
check_popup_sensitivity (row, &menu_data);
/* And let the caller spice things up */
if (uri)
file = g_file_new_for_uri (uri);
else
file = NULL;
emit_populate_popup (sidebar, GTK_MENU (sidebar->popup_menu), file, volume);
if (file)
g_object_unref (file);
g_free (uri);
if (volume)
g_object_unref (volume);
g_object_unref (sidebar);
} }
static void static void
bookmarks_popup_menu (GtkSidebarRow *row, show_row_popover (GtkSidebarRow *row)
GdkEventButton *event)
{ {
gint button;
GtkPlacesSidebar *sidebar; GtkPlacesSidebar *sidebar;
g_object_get (row, "sidebar", &sidebar, NULL); g_object_get (row, "sidebar", &sidebar, NULL);
if (sidebar->popup_menu) if (sidebar->popover)
gtk_widget_destroy (sidebar->popup_menu); gtk_widget_destroy (sidebar->popover);
bookmarks_build_popup_menu (row); create_row_popover (sidebar, row);
/* The event button needs to be 0 if we're popping up this menu from gtk_popover_set_relative_to (GTK_POPOVER (sidebar->popover), GTK_WIDGET (row));
* a button release, else a 2nd click outside the menu with any button
* other than the one that invoked the menu will be ignored (instead
* of dismissing the menu). This is a subtle fragility of the GTK menu code.
*/
if (event)
{
if (event->type == GDK_BUTTON_RELEASE)
button = 0;
else
button = event->button;
}
else
{
button = 0;
}
gtk_menu_popup (GTK_MENU (sidebar->popup_menu), sidebar->context_row = row;
NULL, gtk_widget_show (sidebar->popover);
NULL,
NULL,
NULL,
button,
event ? event->time : gtk_get_current_event_time ());
g_object_unref (sidebar); g_object_unref (sidebar);
} }
@ -3547,7 +3491,7 @@ on_button_release_event (GtkWidget *widget,
else if (event->button == 3) else if (event->button == 3)
{ {
if (row_type != PLACES_CONNECT_TO_SERVER) if (row_type != PLACES_CONNECT_TO_SERVER)
bookmarks_popup_menu (GTK_SIDEBAR_ROW (row), event); show_row_popover (GTK_SIDEBAR_ROW (row));
} }
} }
@ -3562,7 +3506,20 @@ popup_menu_cb (GtkSidebarRow *row)
g_object_get (row, "place-type", &row_type, NULL); g_object_get (row, "place-type", &row_type, NULL);
if (row_type != PLACES_CONNECT_TO_SERVER) if (row_type != PLACES_CONNECT_TO_SERVER)
bookmarks_popup_menu (row, NULL); show_row_popover (row);
}
static void
long_press_cb (GtkGesture *gesture,
gdouble x,
gdouble y,
GtkPlacesSidebar *sidebar)
{
GtkWidget *row;
row = GTK_WIDGET (gtk_list_box_get_row_at_y (GTK_LIST_BOX (sidebar->list_box), y));
if (GTK_IS_SIDEBAR_ROW (row))
popup_menu_cb (GTK_SIDEBAR_ROW (row));
} }
static gint static gint
@ -3821,6 +3778,11 @@ gtk_places_sidebar_init (GtkPlacesSidebar *sidebar)
G_CALLBACK (on_key_press_event), G_CALLBACK (on_key_press_event),
sidebar); sidebar);
sidebar->long_press_gesture = gtk_gesture_long_press_new (GTK_WIDGET (sidebar));
gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (sidebar->long_press_gesture), TRUE);
g_signal_connect (sidebar->long_press_gesture, "pressed",
G_CALLBACK (long_press_cb), sidebar);
/* DND support */ /* DND support */
gtk_drag_dest_set (sidebar->list_box, gtk_drag_dest_set (sidebar->list_box,
0, 0,
@ -3879,6 +3841,8 @@ gtk_places_sidebar_init (GtkPlacesSidebar *sidebar)
/* populate the sidebar */ /* populate the sidebar */
update_places (sidebar); update_places (sidebar);
add_actions (sidebar);
} }
static void static void
@ -4011,10 +3975,10 @@ gtk_places_sidebar_dispose (GObject *object)
sidebar->bookmarks_manager = NULL; sidebar->bookmarks_manager = NULL;
} }
if (sidebar->popup_menu) if (sidebar->popover)
{ {
gtk_widget_destroy (sidebar->popup_menu); gtk_widget_destroy (sidebar->popover);
sidebar->popup_menu = NULL; sidebar->popover = NULL;
} }
if (sidebar->rename_popover) if (sidebar->rename_popover)
@ -4059,6 +4023,8 @@ gtk_places_sidebar_dispose (GObject *object)
g_clear_object (&sidebar->current_location); g_clear_object (&sidebar->current_location);
g_clear_pointer (&sidebar->rename_uri, g_free); g_clear_pointer (&sidebar->rename_uri, g_free);
g_clear_object (&sidebar->long_press_gesture);
G_OBJECT_CLASS (gtk_places_sidebar_parent_class)->dispose (object); G_OBJECT_CLASS (gtk_places_sidebar_parent_class)->dispose (object);
} }