filechooserwidget: Make context menus mostly work

Move the gestures to the individual cells, and
make them trigger the context menu via an action
that takes item position and coordinates.

The semantics are changed slightly: the menu actions
now operate on the clicked item, not on the selection.

Still to do: Fix up keyboard activation.
This commit is contained in:
Matthias Clasen 2022-10-14 00:01:02 -04:00
parent e5be9e1035
commit 44b5076cf2
5 changed files with 405 additions and 281 deletions

179
gtk/gtkfilechoosercell.c Normal file
View File

@ -0,0 +1,179 @@
/*
* Copyright © 2022 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen <mclasen@redhat.com>
*/
#include "config.h"
#include "gtkfilechoosercellprivate.h"
#include "gtkprivate.h"
#include "gtkbinlayout.h"
#include "gtkgestureclick.h"
#include "gtkgesturelongpress.h"
#include "gtkfilechooserwidget.h"
struct _GtkFileChooserCell
{
GtkWidget parent_instance;
guint position;
};
struct _GtkFileChooserCellClass
{
GtkWidgetClass parent_class;
};
G_DEFINE_TYPE (GtkFileChooserCell, gtk_file_chooser_cell, GTK_TYPE_WIDGET)
enum
{
PROP_POSITION = 1,
};
static void
popup_menu (GtkFileChooserCell *self,
double x,
double y)
{
GtkWidget *widget = GTK_WIDGET (self);
GtkWidget *impl;
double xx, yy;
impl = gtk_widget_get_ancestor (widget, GTK_TYPE_FILE_CHOOSER_WIDGET);
gtk_widget_translate_coordinates (widget, GTK_WIDGET (impl),
x, y, &xx, &yy);
gtk_widget_activate_action (widget, "item.popup-file-list-menu",
"(udd)", self->position, xx, yy);
}
static void
file_chooser_cell_clicked (GtkEventController *controller,
int n_press,
double x,
double y)
{
GtkWidget *widget = gtk_event_controller_get_widget (controller);
GtkFileChooserCell *self = GTK_FILE_CHOOSER_CELL (widget);
popup_menu (self, x, y);
}
static void
file_chooser_cell_long_pressed (GtkEventController *controller,
double x,
double y)
{
GtkWidget *widget = gtk_event_controller_get_widget (controller);
GtkFileChooserCell *self = GTK_FILE_CHOOSER_CELL (widget);
popup_menu (self, x, y);
}
static void
gtk_file_chooser_cell_init (GtkFileChooserCell *self)
{
GtkGesture *gesture;
gesture = gtk_gesture_click_new ();
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_SECONDARY);
g_signal_connect (gesture, "pressed", G_CALLBACK (file_chooser_cell_clicked), NULL);
gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (gesture));
gesture = gtk_gesture_long_press_new ();
g_signal_connect (gesture, "pressed", G_CALLBACK (file_chooser_cell_long_pressed), NULL);
}
static void
gtk_file_chooser_cell_dispose (GObject *object)
{
GtkWidget *child;
while ((child = gtk_widget_get_first_child (GTK_WIDGET (object))))
gtk_widget_unparent (child);
G_OBJECT_CLASS (gtk_file_chooser_cell_parent_class)->dispose (object);
}
static void
gtk_file_chooser_cell_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkFileChooserCell *self = GTK_FILE_CHOOSER_CELL (object);
switch (prop_id)
{
case PROP_POSITION:
self->position = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_file_chooser_cell_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkFileChooserCell *self = GTK_FILE_CHOOSER_CELL (object);
switch (prop_id)
{
case PROP_POSITION:
g_value_set_uint (value, self->position);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_file_chooser_cell_class_init (GtkFileChooserCellClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gtk_file_chooser_cell_dispose;
object_class->set_property = gtk_file_chooser_cell_set_property;
object_class->get_property = gtk_file_chooser_cell_get_property;
g_object_class_install_property (object_class, PROP_POSITION,
g_param_spec_uint ("position", NULL, NULL,
0, G_MAXUINT, 0,
GTK_PARAM_READWRITE));
gtk_widget_class_set_css_name (widget_class, I_("filelistcell"));
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
}
GtkFileChooserCell *
gtk_file_chooser_cell_new (void)
{
return g_object_new (GTK_TYPE_FILE_CHOOSER_CELL, NULL);
}

View File

@ -0,0 +1,37 @@
/*
* Copyright © 2022 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Matthias Clasen
*/
#ifndef __GTK_FILE_CHOOSER_CELL_PRIVATE_H__
#define __GTK_FILE_CHOOSER_CELL_PRIVATE_H__
#include <gtk/gtkwidget.h>
#include <gtk/gtkexpression.h>
G_BEGIN_DECLS
#define GTK_TYPE_FILE_CHOOSER_CELL (gtk_file_chooser_cell_get_type ())
GDK_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (GtkFileChooserCell, gtk_file_chooser_cell, GTK, FILE_CHOOSER_CELL, GtkWidget)
GtkFileChooserCell * gtk_file_chooser_cell_new (void);
G_END_DECLS
#endif /* __GTK_FILE_CHOOSER_CELL_PRIVATE_H__ */

View File

@ -72,8 +72,6 @@
#include "gtkspinner.h" #include "gtkspinner.h"
#include "gtkseparator.h" #include "gtkseparator.h"
#include "gtkmodelbuttonprivate.h" #include "gtkmodelbuttonprivate.h"
#include "gtkgesturelongpress.h"
#include "gtkgestureclick.h"
#include "gtkeventcontrollerkey.h" #include "gtkeventcontrollerkey.h"
#include "gtkdebug.h" #include "gtkdebug.h"
#include "gtkfilechoosererrorstackprivate.h" #include "gtkfilechoosererrorstackprivate.h"
@ -212,6 +210,7 @@ struct _GtkFileChooserWidget
GtkWidget *remote_warning_bar; GtkWidget *remote_warning_bar;
GtkWidget *browse_files_popover; GtkWidget *browse_files_popover;
guint browse_files_popover_item;
GtkWidget *browse_new_folder_button; GtkWidget *browse_new_folder_button;
GtkSizeGroup *browse_path_bar_size_group; GtkSizeGroup *browse_path_bar_size_group;
@ -476,7 +475,6 @@ static void stop_loading_and_clear_list_model (GtkFileChooserWidget *impl,
gboolean remove_from_treeview); gboolean remove_from_treeview);
static GSList *get_selected_files (GtkFileChooserWidget *impl); static GSList *get_selected_files (GtkFileChooserWidget *impl);
static GSList *get_selected_infos (GtkFileChooserWidget *impl);
static void search_setup_widgets (GtkFileChooserWidget *impl); static void search_setup_widgets (GtkFileChooserWidget *impl);
static void search_stop_searching (GtkFileChooserWidget *impl, static void search_stop_searching (GtkFileChooserWidget *impl,
@ -1362,18 +1360,18 @@ copy_file_location_cb (GSimpleAction *action,
gpointer data) gpointer data)
{ {
GtkFileChooserWidget *impl = data; GtkFileChooserWidget *impl = data;
GSList *selected_files = NULL; GFileInfo *info;
GFile *file;
GdkClipboard *clipboard;
selected_files = get_selected_files (impl); info = g_list_model_get_item (G_LIST_MODEL (impl->selection_model), impl->browse_files_popover_item);
file = _gtk_file_info_get_file (info);
if (selected_files) clipboard = gtk_widget_get_clipboard (GTK_WIDGET (impl));
{
GdkClipboard *clipboard;
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (impl)); gdk_clipboard_set (clipboard, G_TYPE_FILE, file);
gdk_clipboard_set (clipboard, GDK_TYPE_FILE_LIST, selected_files);
g_slist_free_full (selected_files, g_object_unref); g_clear_object (&info);
}
} }
/* Callback used when the "Visit this file" menu item is activated */ /* Callback used when the "Visit this file" menu item is activated */
@ -1383,19 +1381,15 @@ visit_file_cb (GSimpleAction *action,
gpointer data) gpointer data)
{ {
GtkFileChooserWidget *impl = data; GtkFileChooserWidget *impl = data;
GSList *files; GFileInfo *info;
GFile *file;
files = get_selected_files (impl); info = g_list_model_get_item (G_LIST_MODEL (impl->selection_model), impl->browse_files_popover_item);
file = _gtk_file_info_get_file (info);
/* Sigh, just use the first one */ gtk_file_chooser_widget_select_file (GTK_FILE_CHOOSER (impl), file, NULL); /* NULL-GError */
if (files)
{
GFile *file = files->data;
gtk_file_chooser_widget_select_file (GTK_FILE_CHOOSER (impl), file, NULL); /* NULL-GError */ g_clear_object (&info);
}
g_slist_free_full (files, g_object_unref);
} }
#define FILE_MANAGER_DBUS_NAME "org.freedesktop.FileManager1" #define FILE_MANAGER_DBUS_NAME "org.freedesktop.FileManager1"
@ -1411,17 +1405,12 @@ open_folder_cb (GSimpleAction *action,
GtkFileChooserWidget *impl = data; GtkFileChooserWidget *impl = data;
GtkRoot *root = gtk_widget_get_root (GTK_WIDGET (impl)); GtkRoot *root = gtk_widget_get_root (GTK_WIDGET (impl));
GtkWindow *toplevel = GTK_IS_WINDOW (root) ? GTK_WINDOW (root) : NULL; GtkWindow *toplevel = GTK_IS_WINDOW (root) ? GTK_WINDOW (root) : NULL;
GSList *files; GFileInfo *info;
GFile *file; GFile *file;
char *uri; char *uri;
files = get_selected_files (impl); info = g_list_model_get_item (G_LIST_MODEL (impl->selection_model), impl->browse_files_popover_item);
file = _gtk_file_info_get_file (info);
if (!files)
return;
/* Sigh, just use the first one */
file = files->data;
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
@ -1481,7 +1470,7 @@ open_folder_cb (GSimpleAction *action,
#endif #endif
g_slist_free_full (files, g_object_unref); g_clear_object (&info);
} }
/* callback used when the "Show Hidden Files" menu item is toggled */ /* callback used when the "Show Hidden Files" menu item is toggled */
@ -1677,89 +1666,77 @@ file_list_drag_drop_cb (GtkDropTarget *dest,
return TRUE; return TRUE;
} }
/* Sensitizes the "Copy files location" and other context menu items if there is actually
* a selection active.
*/
static void static void
check_file_list_popover_sensitivity (GtkFileChooserWidget *impl) check_file_list_popover_sensitivity (GtkFileChooserWidget *impl)
{ {
int num_selected; GAction *action;
gboolean all_files; GFileInfo *info;
gboolean all_folders; gboolean is_folder;
gboolean active; GSimpleAction *delete_action, *trash_action;
GAction *action, *action2;
selection_check (impl, &num_selected, &all_files, &all_folders); info = g_list_model_get_item (G_LIST_MODEL (impl->selection_model), impl->browse_files_popover_item);
is_folder = _gtk_file_info_consider_as_directory (info);
active = (num_selected != 0);
action = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "copy-location"); action = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "copy-location");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), active); g_simple_action_set_enabled (G_SIMPLE_ACTION (action), TRUE);
action = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "add-shortcut"); action = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "add-shortcut");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), active && all_folders); g_simple_action_set_enabled (G_SIMPLE_ACTION (action), is_folder);
action = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "visit"); action = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "visit");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), active); g_simple_action_set_enabled (G_SIMPLE_ACTION (action), TRUE);
action = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "open"); action = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "open");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), (num_selected == 1) && all_folders); g_simple_action_set_enabled (G_SIMPLE_ACTION (action), is_folder);
action = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "rename"); action = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "rename");
if (num_selected == 1) g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
{ g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME));
GSList *infos;
GFileInfo *info;
infos = get_selected_infos (impl);
info = G_FILE_INFO (infos->data);
g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME));
g_slist_free_full (infos, g_object_unref);
}
else
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE);
action = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "delete"); action = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "delete");
action2 = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "trash"); delete_action = G_SIMPLE_ACTION (action);
if (num_selected == 1) action = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "trash");
trash_action = G_SIMPLE_ACTION (action);
if (g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH))
{ {
GSimpleAction *delete_action = G_SIMPLE_ACTION (action); g_simple_action_set_enabled (trash_action, TRUE);
GSimpleAction *trash_action = G_SIMPLE_ACTION (action2); g_simple_action_set_enabled (delete_action, FALSE);
GSList *infos; }
GFileInfo *info; else if (g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE))
{
infos = get_selected_infos (impl); g_simple_action_set_enabled (delete_action, TRUE);
info = G_FILE_INFO (infos->data); g_simple_action_set_enabled (trash_action, FALSE);
if (g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH))
{
g_simple_action_set_enabled (trash_action, TRUE);
g_simple_action_set_enabled (delete_action, FALSE);
}
else if (g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE))
{
g_simple_action_set_enabled (delete_action, TRUE);
g_simple_action_set_enabled (trash_action, FALSE);
}
else
{
g_simple_action_set_enabled (trash_action, FALSE);
g_simple_action_set_enabled (delete_action, FALSE);
}
g_slist_free_full (infos, g_object_unref);
} }
else else
{ {
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), FALSE); g_simple_action_set_enabled (trash_action, FALSE);
g_simple_action_set_enabled (G_SIMPLE_ACTION (action2), FALSE); g_simple_action_set_enabled (delete_action, FALSE);
} }
} }
static void
file_list_show_popover (GtkFileChooserWidget *impl,
double x,
double y);
static void
popup_file_list_menu (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
GtkFileChooserWidget *impl = user_data;
guint position;
double x, y;
g_variant_get (parameter, "(udd)", &position, &x, &y);
impl->browse_files_popover_item = position;
file_list_show_popover (impl, x, y);
}
static GActionEntry entries[] = { static GActionEntry entries[] = {
{ "visit", visit_file_cb, NULL, NULL, NULL }, { "visit", visit_file_cb, NULL, NULL, NULL },
{ "open", open_folder_cb, NULL, NULL, NULL }, { "open", open_folder_cb, NULL, NULL, NULL },
@ -1768,6 +1745,7 @@ static GActionEntry entries[] = {
{ "rename", rename_file_cb, NULL, NULL, NULL }, { "rename", rename_file_cb, NULL, NULL, NULL },
{ "delete", delete_file_cb, NULL, NULL, NULL }, { "delete", delete_file_cb, NULL, NULL, NULL },
{ "trash", trash_file_cb, NULL, NULL, NULL }, { "trash", trash_file_cb, NULL, NULL, NULL },
{ "popup-file-list-menu", popup_file_list_menu, "(udd)", NULL, NULL },
{ "toggle-show-hidden", NULL, NULL, "false", change_show_hidden_state }, { "toggle-show-hidden", NULL, NULL, "false", change_show_hidden_state },
{ "toggle-show-size", NULL, NULL, "false", change_show_size_state }, { "toggle-show-size", NULL, NULL, "false", change_show_size_state },
{ "toggle-show-type", NULL, NULL, "false", change_show_type_state }, { "toggle-show-type", NULL, NULL, "false", change_show_type_state },
@ -1860,18 +1838,17 @@ file_list_update_popover (GtkFileChooserWidget *impl)
/* The sensitivity of the Add to Bookmarks item is set in /* The sensitivity of the Add to Bookmarks item is set in
* bookmarks_check_add_sensitivity() * bookmarks_check_add_sensitivity()
*/ */
state = impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || state = impl->action == GTK_FILE_CHOOSER_ACTION_SAVE &&
impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER || impl->operation_mode == OPERATION_MODE_BROWSE;
impl->operation_mode != OPERATION_MODE_BROWSE;
action = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "rename"); action = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "rename");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), !state); g_simple_action_set_enabled (G_SIMPLE_ACTION (action), state);
action = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "delete"); action = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "delete");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), !state); g_simple_action_set_enabled (G_SIMPLE_ACTION (action), state);
action = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "trash"); action = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "trash");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), !state); g_simple_action_set_enabled (G_SIMPLE_ACTION (action), state);
action = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "visit"); action = g_action_map_lookup_action (G_ACTION_MAP (impl->item_actions), "visit");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), (impl->operation_mode != OPERATION_MODE_BROWSE)); g_simple_action_set_enabled (G_SIMPLE_ACTION (action), (impl->operation_mode != OPERATION_MODE_BROWSE));
@ -1928,27 +1905,6 @@ list_popup_menu_cb (GtkWidget *widget,
return TRUE; return TRUE;
} }
static void
files_list_clicked (GtkGesture *gesture,
int n_press,
double x,
double y,
GtkFileChooserWidget *impl)
{
list_popup_menu_cb (NULL, NULL, impl);
}
static void
files_list_restrict_clicking (GtkGestureClick *gesture,
int n_press,
double x,
double y,
GtkFileChooserWidget *impl)
{
if (impl->browse_files_interaction_frozen)
gtk_event_controller_reset (GTK_EVENT_CONTROLLER (gesture));
}
static gboolean static gboolean
files_list_restrict_key_presses (GtkEventControllerKey *controller, files_list_restrict_key_presses (GtkEventControllerKey *controller,
guint keyval, guint keyval,
@ -1986,35 +1942,6 @@ file_list_show_popover_in_idle (gpointer data)
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
static void
click_cb (GtkGesture *gesture,
int n_press,
double x,
double y,
GtkFileChooserWidget *impl)
{
PopoverData *pd;
pd = g_new (PopoverData, 1);
pd->impl = impl;
gtk_widget_translate_coordinates (impl->browse_files_column_view,
GTK_WIDGET (impl),
x, y, &x, &y);
pd->x = x;
pd->y = y;
g_idle_add (file_list_show_popover_in_idle, pd);
}
static void
long_press_cb (GtkGesture *gesture,
double x,
double y,
GtkFileChooserWidget *impl)
{
file_list_show_popover (impl, x, y);
}
static char * static char *
column_view_get_file_date (GtkListItem *item, column_view_get_file_date (GtkListItem *item,
GFileInfo *info) GFileInfo *info)
@ -5765,31 +5692,6 @@ get_selected_files (GtkFileChooserWidget *impl)
return result; return result;
} }
static GSList *
get_selected_infos (GtkFileChooserWidget *impl)
{
GtkBitsetIter iter;
GtkBitset *bitset;
GSList *result = NULL;
guint i;
bitset = gtk_selection_model_get_selection (impl->selection_model);
for (gtk_bitset_iter_init_first (&iter, bitset, &i);
gtk_bitset_iter_is_valid (&iter);
gtk_bitset_iter_next (&iter, &i))
{
GFileInfo *info;
info = g_list_model_get_item (G_LIST_MODEL (impl->selection_model), i);
result = g_slist_prepend (result, g_object_ref (info));
g_clear_object (&info);
}
return result;
}
/* Callback used from GtkSearchEngine when we get new hits */ /* Callback used from GtkSearchEngine when we get new hits */
static void static void
search_engine_hits_added_cb (GtkSearchEngine *engine, search_engine_hits_added_cb (GtkSearchEngine *engine,
@ -6899,8 +6801,6 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
gtk_widget_class_bind_template_callback (widget_class, rename_file_name_changed); gtk_widget_class_bind_template_callback (widget_class, rename_file_name_changed);
gtk_widget_class_bind_template_callback (widget_class, rename_file_rename_clicked); gtk_widget_class_bind_template_callback (widget_class, rename_file_rename_clicked);
gtk_widget_class_bind_template_callback (widget_class, rename_file_end); gtk_widget_class_bind_template_callback (widget_class, rename_file_end);
gtk_widget_class_bind_template_callback (widget_class, click_cb);
gtk_widget_class_bind_template_callback (widget_class, long_press_cb);
gtk_widget_class_bind_template_callback (widget_class, column_view_get_file_date); gtk_widget_class_bind_template_callback (widget_class, column_view_get_file_date);
gtk_widget_class_bind_template_callback (widget_class, column_view_get_file_display_name); gtk_widget_class_bind_template_callback (widget_class, column_view_get_file_display_name);
gtk_widget_class_bind_template_callback (widget_class, column_view_get_file_time); gtk_widget_class_bind_template_callback (widget_class, column_view_get_file_time);
@ -6955,7 +6855,6 @@ post_process_ui (GtkFileChooserWidget *impl)
{ {
GFile *file; GFile *file;
GtkDropTarget *target; GtkDropTarget *target;
GtkGesture *gesture;
GtkEventController *controller; GtkEventController *controller;
GtkShortcutTrigger *trigger; GtkShortcutTrigger *trigger;
GtkShortcutAction *action; GtkShortcutAction *action;
@ -6990,11 +6889,6 @@ post_process_ui (GtkFileChooserWidget *impl)
gtk_widget_set_parent (impl->rename_file_popover, GTK_WIDGET (impl)); gtk_widget_set_parent (impl->rename_file_popover, GTK_WIDGET (impl));
gesture = gtk_gesture_click_new ();
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_SECONDARY);
g_signal_connect (gesture, "pressed", G_CALLBACK (files_list_clicked), impl);
gtk_widget_add_controller (GTK_WIDGET (impl->browse_files_column_view), GTK_EVENT_CONTROLLER (gesture));
controller = gtk_shortcut_controller_new (); controller = gtk_shortcut_controller_new ();
trigger = gtk_alternative_trigger_new (gtk_keyval_trigger_new (GDK_KEY_F10, GDK_SHIFT_MASK), trigger = gtk_alternative_trigger_new (gtk_keyval_trigger_new (GDK_KEY_F10, GDK_SHIFT_MASK),
gtk_keyval_trigger_new (GDK_KEY_Menu, 0)); gtk_keyval_trigger_new (GDK_KEY_Menu, 0));
@ -7003,15 +6897,6 @@ post_process_ui (GtkFileChooserWidget *impl)
gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut); gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut);
gtk_widget_add_controller (GTK_WIDGET (impl->browse_files_column_view), controller); gtk_widget_add_controller (GTK_WIDGET (impl->browse_files_column_view), controller);
/* Add ability to restrict interaction on file list (click and key_press events),
* needed to prevent data loss bug #2288 */
gesture = gtk_gesture_click_new ();
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), 0);
gtk_gesture_single_set_exclusive (GTK_GESTURE_SINGLE (gesture), TRUE);
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture), GTK_PHASE_CAPTURE);
g_signal_connect (gesture, "pressed", G_CALLBACK (files_list_restrict_clicking), impl);
gtk_widget_add_controller (impl->browse_files_column_view, GTK_EVENT_CONTROLLER (gesture));
controller = gtk_event_controller_key_new (); controller = gtk_event_controller_key_new ();
gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_CAPTURE); gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_CAPTURE);
g_signal_connect (controller, "key-pressed", G_CALLBACK (files_list_restrict_key_presses), impl); g_signal_connect (controller, "key-pressed", G_CALLBACK (files_list_restrict_key_presses), impl);

View File

@ -108,6 +108,7 @@ gtk_private_sources = files([
'gtkfilechoosererrorstack.c', 'gtkfilechoosererrorstack.c',
'gtkfilechoosernativeportal.c', 'gtkfilechoosernativeportal.c',
'gtkfilechooserutils.c', 'gtkfilechooserutils.c',
'gtkfilechoosercell.c',
'gtkfilesystemmodel.c', 'gtkfilesystemmodel.c',
'gtkfilethumbnail.c', 'gtkfilethumbnail.c',
'gtkgizmo.c', 'gtkgizmo.c',

View File

@ -143,19 +143,6 @@
<object class="GtkColumnView" id="browse_files_column_view"> <object class="GtkColumnView" id="browse_files_column_view">
<signal name="activate" handler="column_view_row_activated_cb" swapped="no"/> <signal name="activate" handler="column_view_row_activated_cb" swapped="no"/>
<signal name="keynav-failed" handler="browse_files_column_view_keynav_failed_cb"/> <signal name="keynav-failed" handler="browse_files_column_view_keynav_failed_cb"/>
<child>
<object class="GtkGestureLongPress">
<property name="touch-only">1</property>
<signal name="pressed" handler="long_press_cb" swapped="no"/>
</object>
</child>
<child>
<object class="GtkGestureClick">
<property name="button">3</property>
<signal name="pressed" handler="click_cb" swapped="no"/>
</object>
</child>
<child> <child>
<object class="GtkColumnViewColumn" id="column_view_name_column"> <object class="GtkColumnViewColumn" id="column_view_name_column">
<property name="title" translatable="yes">Name</property> <property name="title" translatable="yes">Name</property>
@ -168,31 +155,38 @@
<interface> <interface>
<template class="GtkListItem"> <template class="GtkListItem">
<property name="child"> <property name="child">
<object class="GtkBox"> <object class="GtkFileChooserCell">
<binding name="tooltip-text"> <binding name="position">
<closure type="gchararray" function="column_view_get_tooltip_text"> <lookup name="position">GtkListItem</lookup>
<lookup name="item">GtkListItem</lookup>
</closure>
</binding> </binding>
<child> <child>
<object class="GtkFileThumbnail"> <object class="GtkBox">
<property name="margin-start">6</property> <binding name="tooltip-text">
<property name="margin-end">6</property> <closure type="gchararray" function="column_view_get_tooltip_text">
<binding name="file-info">
<lookup name="item">GtkListItem</lookup>
</binding>
</object>
</child>
<child>
<object class="GtkInscription">
<property name="hexpand">1</property>
<property name="xalign">0</property>
<property name="min-chars">10</property>
<binding name="text">
<closure type="gchararray" function="column_view_get_file_display_name">
<lookup name="item">GtkListItem</lookup> <lookup name="item">GtkListItem</lookup>
</closure> </closure>
</binding> </binding>
<child>
<object class="GtkFileThumbnail">
<property name="margin-start">6</property>
<property name="margin-end">6</property>
<binding name="file-info">
<lookup name="item">GtkListItem</lookup>
</binding>
</object>
</child>
<child>
<object class="GtkInscription">
<property name="hexpand">1</property>
<property name="xalign">0</property>
<property name="min-chars">10</property>
<binding name="text">
<closure type="gchararray" function="column_view_get_file_display_name">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding>
</object>
</child>
</object> </object>
</child> </child>
</object> </object>
@ -218,22 +212,29 @@
<interface> <interface>
<template class="GtkListItem"> <template class="GtkListItem">
<property name="child"> <property name="child">
<object class="GtkInscription"> <object class="GtkFileChooserCell">
<property name="hexpand">1</property> <binding name="position">
<property name="xalign">0</property> <lookup name="position">GtkListItem</lookup>
<property name="min-chars">10</property>
<property name="margin-start">6</property>
<property name="margin-end">6</property>
<binding name="text">
<closure type="gchararray" function="column_view_get_location">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding>
<binding name="tooltip-text">
<closure type="gchararray" function="column_view_get_tooltip_text">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding> </binding>
<child>
<object class="GtkInscription">
<property name="hexpand">1</property>
<property name="xalign">0</property>
<property name="min-chars">10</property>
<property name="margin-start">6</property>
<property name="margin-end">6</property>
<binding name="text">
<closure type="gchararray" function="column_view_get_location">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding>
<binding name="tooltip-text">
<closure type="gchararray" function="column_view_get_tooltip_text">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding>
</object>
</child>
</object> </object>
</property> </property>
</template> </template>
@ -254,19 +255,26 @@
<interface> <interface>
<template class="GtkListItem"> <template class="GtkListItem">
<property name="child"> <property name="child">
<object class="GtkLabel"> <object class="GtkFileChooserCell">
<property name="hexpand">1</property> <binding name="position">
<property name="xalign">0</property> <lookup name="position">GtkListItem</lookup>
<binding name="label">
<closure type="gchararray" function="column_view_get_size">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding>
<binding name="tooltip-text">
<closure type="gchararray" function="column_view_get_tooltip_text">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding> </binding>
<child>
<object class="GtkLabel">
<property name="hexpand">1</property>
<property name="xalign">0</property>
<binding name="label">
<closure type="gchararray" function="column_view_get_size">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding>
<binding name="tooltip-text">
<closure type="gchararray" function="column_view_get_tooltip_text">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding>
</object>
</child>
</object> </object>
</property> </property>
</template> </template>
@ -288,19 +296,26 @@
<interface> <interface>
<template class="GtkListItem"> <template class="GtkListItem">
<property name="child"> <property name="child">
<object class="GtkLabel"> <object class="GtkFileChooserCell">
<property name="hexpand">1</property> <binding name="position">
<property name="xalign">0</property> <lookup name="position">GtkListItem</lookup>
<binding name="label">
<closure type="gchararray" function="column_view_get_file_type">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding>
<binding name="tooltip-text">
<closure type="gchararray" function="column_view_get_tooltip_text">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding> </binding>
<child>
<object class="GtkLabel">
<property name="hexpand">1</property>
<property name="xalign">0</property>
<binding name="label">
<closure type="gchararray" function="column_view_get_file_type">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding>
<binding name="tooltip-text">
<closure type="gchararray" function="column_view_get_tooltip_text">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding>
</object>
</child>
</object> </object>
</property> </property>
</template> </template>
@ -321,32 +336,39 @@
<interface> <interface>
<template class="GtkListItem"> <template class="GtkListItem">
<property name="child"> <property name="child">
<object class="GtkBox"> <object class="GtkFileChooserCell">
<property name="spacing">6</property> <binding name="position">
<binding name="tooltip-text"> <lookup name="position">GtkListItem</lookup>
<closure type="gchararray" function="column_view_get_tooltip_text">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding> </binding>
<child> <child>
<object class="GtkLabel"> <object class="GtkBox">
<binding name="label"> <property name="spacing">6</property>
<closure type="gchararray" function="column_view_get_file_date"> <binding name="tooltip-text">
<lookup name="item">GtkListItem</lookup> <closure type="gchararray" function="column_view_get_tooltip_text">
</closure>
</binding>
</object>
</child>
<child>
<object class="GtkLabel">
<binding name="visible">
<closure type="gboolean" function="column_view_get_time_visible" />
</binding>
<binding name="label">
<closure type="gchararray" function="column_view_get_file_time">
<lookup name="item">GtkListItem</lookup> <lookup name="item">GtkListItem</lookup>
</closure> </closure>
</binding> </binding>
<child>
<object class="GtkLabel">
<binding name="label">
<closure type="gchararray" function="column_view_get_file_date">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding>
</object>
</child>
<child>
<object class="GtkLabel">
<binding name="visible">
<closure type="gboolean" function="column_view_get_time_visible" />
</binding>
<binding name="label">
<closure type="gchararray" function="column_view_get_file_time">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding>
</object>
</child>
</object> </object>
</child> </child>
</object> </object>