diff options
author | Matthias Clasen <mclasen@redhat.com> | 2022-10-04 21:24:16 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2022-10-04 21:26:07 -0400 |
commit | 5d5de9f75934c05a1162bc93a2112db548814d78 (patch) | |
tree | 428e3d6fc5bdd95bfcd97097322f1e48ccb0b2be /gtk/gtkmountoperation.c | |
parent | e1f69ea278b8fa48d0963d9bcd29559fc9206d5e (diff) | |
download | gtk+-5d5de9f75934c05a1162bc93a2112db548814d78.tar.gz |
mountoperation: Don't use a treeview
Port the process list from GtkTreeView
to GtkListView, and fix a number of broken
things along the way.
Diffstat (limited to 'gtk/gtkmountoperation.c')
-rw-r--r-- | gtk/gtkmountoperation.c | 370 |
1 files changed, 156 insertions, 214 deletions
diff --git a/gtk/gtkmountoperation.c b/gtk/gtkmountoperation.c index 22b4af7bbe..8c56917bfc 100644 --- a/gtk/gtkmountoperation.c +++ b/gtk/gtkmountoperation.c @@ -41,26 +41,22 @@ #include "gtkcheckbutton.h" #include "gtkgrid.h" #include "gtkwindow.h" -#include "gtktreeview.h" -#include "gtktreeselection.h" -#include "gtkcellrenderertext.h" -#include "gtkcellrendererpixbuf.h" #include "gtkscrolledwindow.h" #include "gtkicontheme.h" #include "gtkmain.h" #include "gtksettings.h" #include "gtkdialogprivate.h" -#include "gtkgestureclick.h" -#include "gtkmodelbuttonprivate.h" #include "gtkpopover.h" #include "gtksnapshot.h" #include "gdktextureprivate.h" -#include "gtkshortcutcontroller.h" -#include "gtkshortcuttrigger.h" -#include "gtkshortcutaction.h" -#include "gtkshortcut.h" #include "gtkliststore.h" #include <glib/gprintf.h> +#include "gtklistview.h" +#include "gtksignallistitemfactory.h" +#include "gtklistitem.h" +#include "gtksingleselection.h" +#include "gtkpicture.h" + /** * GtkMountOperation: @@ -133,8 +129,8 @@ struct _GtkMountOperationPrivate { gboolean anonymous; /* for the show-processes dialog */ - GtkWidget *process_tree_view; - GtkListStore *process_list_store; + GtkWidget *process_list_view; + GListStore *process_list_store; }; enum { @@ -1064,12 +1060,17 @@ gtk_mount_operation_ask_question (GMountOperation *op, } static void -show_processes_button_clicked (GtkDialog *dialog, - int button_number, +show_processes_button_clicked (GtkWidget *button, GMountOperation *op) { GtkMountOperationPrivate *priv; GtkMountOperation *operation; + int button_number; + GtkDialog *dialog; + + button_number = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "choice")); + dialog = GTK_DIALOG (gtk_widget_get_ancestor (button, GTK_TYPE_DIALOG)); + operation = GTK_MOUNT_OPERATION (op); priv = operation->priv; @@ -1180,17 +1181,70 @@ render_paintable_to_texture (GdkPaintable *paintable) return texture; } +typedef struct _ProcessData ProcessData; + +G_DECLARE_FINAL_TYPE (ProcessData, process_data, PROCESS, DATA, GObject); + +struct _ProcessData +{ + GObject parent; + + GdkTexture *texture; + char *name; + GPid pid; +}; + +G_DEFINE_TYPE (ProcessData, process_data, G_TYPE_OBJECT); + +static void +process_data_init (ProcessData *self) +{ +} + +static void +process_data_finalize (GObject *object) +{ + ProcessData *pd = PROCESS_DATA (object); + + g_free (pd->name); + g_object_unref (pd->texture); + + G_OBJECT_CLASS (process_data_parent_class)->finalize (object); +} + +static void +process_data_class_init (ProcessDataClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->finalize = process_data_finalize; +} + +static ProcessData * +process_data_new (const char *name, + GPid pid, + GdkTexture *texture) +{ + ProcessData *self; + + self = g_object_new (process_data_get_type (), NULL); + self->name = g_strdup (name); + self->pid = pid; + g_set_object (&self->texture, texture); + + return self; +} + static void add_pid_to_process_list_store (GtkMountOperation *mount_operation, GtkMountOperationLookupContext *lookup_context, - GtkListStore *list_store, + GListStore *list_store, GPid pid) { char *command_line; char *name; GdkTexture *texture; char *markup; - GtkTreeIter iter; name = NULL; texture = NULL; @@ -1229,12 +1283,7 @@ add_pid_to_process_list_store (GtkMountOperation *mount_operation, name, command_line); - gtk_list_store_append (list_store, &iter); - gtk_list_store_set (list_store, &iter, - 0, texture, - 1, markup, - 2, pid, - -1); + g_list_store_append (list_store, process_data_new (markup, pid, texture)); if (texture != NULL) g_object_unref (texture); @@ -1245,35 +1294,27 @@ add_pid_to_process_list_store (GtkMountOperation *mount_operation, static void remove_pid_from_process_list_store (GtkMountOperation *mount_operation, - GtkListStore *list_store, + GListStore *list_store, GPid pid) { - GtkTreeIter iter; - GPid pid_of_item; - - if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list_store), &iter)) + for (guint i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (list_store)); i++) { - do - { - gtk_tree_model_get (GTK_TREE_MODEL (list_store), - &iter, - 2, &pid_of_item, - -1); + ProcessData *data = g_list_model_get_item (G_LIST_MODEL (list_store), i); - if (pid_of_item == pid) - { - gtk_list_store_remove (list_store, &iter); - break; - } + g_object_unref (data); + + if (data->pid == pid) + { + g_list_store_remove (list_store, i); + break; } - while (gtk_tree_model_iter_next (GTK_TREE_MODEL (list_store), &iter)); } } static void update_process_list_store (GtkMountOperation *mount_operation, - GtkListStore *list_store, + GListStore *list_store, GArray *processes) { guint n; @@ -1281,7 +1322,6 @@ update_process_list_store (GtkMountOperation *mount_operation, GArray *current_pids; GArray *pid_indices_to_add; GArray *pid_indices_to_remove; - GtkTreeIter iter; GPid pid; /* Just removing all items and adding new ones will screw up the @@ -1292,18 +1332,13 @@ update_process_list_store (GtkMountOperation *mount_operation, pid_indices_to_add = g_array_new (FALSE, FALSE, sizeof (int)); pid_indices_to_remove = g_array_new (FALSE, FALSE, sizeof (int)); - if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list_store), &iter)) + for (guint i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (list_store)); i++) { - do - { - gtk_tree_model_get (GTK_TREE_MODEL (list_store), - &iter, - 2, &pid, - -1); + ProcessData *data = g_list_model_get_item (G_LIST_MODEL (list_store), i); - g_array_append_val (current_pids, pid); - } - while (gtk_tree_model_iter_next (GTK_TREE_MODEL (list_store), &iter)); + g_array_append_val (current_pids, data->pid); + + g_object_unref (data); } g_array_sort (current_pids, pid_equal); @@ -1319,7 +1354,7 @@ update_process_list_store (GtkMountOperation *mount_operation, if (pid_indices_to_add->len > 0) { - lookup_context = _gtk_mount_operation_lookup_context_get (gtk_widget_get_display (mount_operation->priv->process_tree_view)); + lookup_context = _gtk_mount_operation_lookup_context_get (gtk_widget_get_display (mount_operation->priv->process_list_view)); for (n = 0; n < pid_indices_to_add->len; n++) { pid = g_array_index (processes, GPid, n); @@ -1328,17 +1363,6 @@ update_process_list_store (GtkMountOperation *mount_operation, _gtk_mount_operation_lookup_context_free (lookup_context); } - /* select the first item, if we went from a zero to a non-zero amount of processes */ - if (current_pids->len == 0 && pid_indices_to_add->len > 0) - { - if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list_store), &iter)) - { - GtkTreeSelection *tree_selection; - tree_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (mount_operation->priv->process_tree_view)); - gtk_tree_selection_select_iter (tree_selection, &iter); - } - } - g_array_unref (current_pids); g_array_unref (pid_indices_to_add); g_array_unref (pid_indices_to_remove); @@ -1357,26 +1381,18 @@ on_dialog_response (GtkDialog *dialog, } static void -on_end_process_activated (GtkModelButton *button, - gpointer user_data) +on_end_process_activated (GtkButton *button, + GtkMountOperation *op) { - GtkMountOperation *op = GTK_MOUNT_OPERATION (user_data); - GtkTreeSelection *selection; - GtkTreeIter iter; - GPid pid_to_kill; + GtkSelectionModel *selection; + ProcessData *data; GError *error; - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (op->priv->process_tree_view)); - - if (!gtk_tree_selection_get_selected (selection, - NULL, - &iter)) + selection = gtk_list_view_get_model (GTK_LIST_VIEW (op->priv->process_list_view)); + if (gtk_single_selection_get_selected (GTK_SINGLE_SELECTION (selection)) == GTK_INVALID_LIST_POSITION) goto out; - gtk_tree_model_get (GTK_TREE_MODEL (op->priv->process_list_store), - &iter, - 2, &pid_to_kill, - -1); + data = gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (selection)); /* TODO: We might want to either * @@ -1389,7 +1405,7 @@ on_end_process_activated (GtkModelButton *button, * But that's not how things work right now.... */ error = NULL; - if (!_gtk_mount_operation_kill_process (pid_to_kill, &error)) + if (!_gtk_mount_operation_kill_process (data->pid, &error)) { GtkWidget *dialog; @@ -1418,82 +1434,38 @@ on_end_process_activated (GtkModelButton *button, ; } -static gboolean -do_popup_menu_for_process_tree_view (GtkWidget *widget, - GdkEvent *event, - GtkMountOperation *op) +static void +setup_process_row (GtkListItemFactory *factory, + GtkListItem *item) { - GtkWidget *menu; - GtkWidget *item; - double x, y; - - menu = gtk_popover_new (); - gtk_widget_set_parent (menu, widget); - gtk_widget_add_css_class (menu, "context-menu"); - - item = gtk_model_button_new (); - g_object_set (item, "text", _("_End Process"), NULL); - g_signal_connect (item, "clicked", - G_CALLBACK (on_end_process_activated), - op); - gtk_box_append (GTK_BOX (menu), item); - - if (event && gdk_event_triggers_context_menu (event)) - { - GtkTreePath *path; - GtkTreeSelection *selection; - - gdk_event_get_position (event, &x, &y); - if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (op->priv->process_tree_view), - (int) x, - (int) y, - &path, - NULL, - NULL, - NULL)) - { - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (op->priv->process_tree_view)); - gtk_tree_selection_select_path (selection, path); - gtk_tree_path_free (path); - } - else - { - /* don't popup a menu if the user right-clicked in an area with no rows */ - return FALSE; - } + GtkWidget *box, *picture, *label; - gtk_popover_set_pointing_to (GTK_POPOVER (menu), &(GdkRectangle){ x, y, 1, 1}); - } + picture = gtk_picture_new (); + label = gtk_label_new (NULL); + gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_MIDDLE); - gtk_popover_popup (GTK_POPOVER (menu)); - return TRUE; -} + box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10); + gtk_box_append (GTK_BOX (box), picture); + gtk_box_append (GTK_BOX (box), label); -static gboolean -on_popup_menu_for_process_tree_view (GtkWidget *widget, - GVariant *args, - gpointer user_data) -{ - GtkMountOperation *op = GTK_MOUNT_OPERATION (user_data); - return do_popup_menu_for_process_tree_view (widget, NULL, op); + gtk_list_item_set_child (item, box); } static void -click_cb (GtkGesture *gesture, - int n_press, - double x, - double y, - gpointer user_data) +bind_process_row (GtkListItemFactory *factory, + GtkListItem *item) { - GtkMountOperation *op = GTK_MOUNT_OPERATION (user_data); - GdkEvent *event; - GdkEventSequence *sequence; - GtkWidget *widget; + GtkWidget *box, *picture, *label; + ProcessData *data; + + data = gtk_list_item_get_item (item); - sequence = gtk_gesture_get_last_updated_sequence (gesture); - event = gtk_gesture_get_last_event (gesture, sequence); - widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture)); - do_popup_menu_for_process_tree_view (widget, event, op); + box = gtk_list_item_get_child (item); + picture = gtk_widget_get_first_child (box); + label = gtk_widget_get_next_sibling (picture); + + gtk_picture_set_paintable (GTK_PICTURE (picture), GDK_PAINTABLE (data->texture)); + gtk_label_set_markup (GTK_LABEL (label), data->name); } static GtkWidget * @@ -1507,20 +1479,15 @@ create_show_processes_dialog (GtkMountOperation *op, char *primary; int count, len = 0; GtkWidget *label; - GtkWidget *tree_view; + GtkWidget *list_view; GtkWidget *scrolled_window; GtkWidget *vbox; + GtkWidget *hbox; GtkWidget *content_area; - GtkTreeViewColumn *column; - GtkCellRenderer *renderer; - GtkListStore *list_store; char *s; - gboolean use_header; - GtkGesture *gesture; - GtkEventController *controller; - GtkShortcutTrigger *trigger; - GtkShortcutAction *action; - GtkShortcut *shortcut; + GListStore *store; + GtkListItemFactory *factory; + GtkWidget *button; priv = op->priv; @@ -1531,12 +1498,7 @@ create_show_processes_dialog (GtkMountOperation *op, primary = g_strndup (message, primary - message); } - g_object_get (gtk_settings_get_default (), - "gtk-dialogs-use-header", &use_header, - NULL); - dialog = g_object_new (GTK_TYPE_DIALOG, - "use-header-bar", use_header, - NULL); + dialog = gtk_dialog_new (); if (priv->parent_window != NULL) gtk_window_set_transient_for (GTK_WINDOW (dialog), priv->parent_window); @@ -1544,6 +1506,10 @@ create_show_processes_dialog (GtkMountOperation *op, content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_widget_set_margin_top (vbox, 12); + gtk_widget_set_margin_bottom (vbox, 12); + gtk_widget_set_margin_start (vbox, 12); + gtk_widget_set_margin_end (vbox, 12); gtk_box_append (GTK_BOX (content_area), vbox); if (secondary != NULL) @@ -1564,11 +1530,16 @@ create_show_processes_dialog (GtkMountOperation *op, while (choices[len] != NULL) len++; + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); for (count = len - 1; count >= 0; count--) - gtk_dialog_add_button (GTK_DIALOG (dialog), choices[count], count); - - g_signal_connect (G_OBJECT (dialog), "response", - G_CALLBACK (show_processes_button_clicked), op); + { + button = gtk_button_new_with_label (choices[count]); + g_object_set_data (G_OBJECT (button), "choice", GINT_TO_POINTER (count)); + g_signal_connect (button, "clicked", G_CALLBACK (show_processes_button_clicked), op); + gtk_box_append (GTK_BOX (hbox), button); + } + gtk_widget_set_halign (hbox, GTK_ALIGN_END); + gtk_box_append (GTK_BOX (vbox), hbox); priv->dialog = GTK_DIALOG (dialog); g_object_notify (G_OBJECT (op), "is-showing"); @@ -1576,67 +1547,38 @@ create_show_processes_dialog (GtkMountOperation *op, if (priv->parent_window == NULL && priv->display) gtk_window_set_display (GTK_WINDOW (dialog), priv->display); - tree_view = gtk_tree_view_new (); - gtk_widget_set_size_request (tree_view, 300, 120); - - column = gtk_tree_view_column_new (); - renderer = gtk_cell_renderer_pixbuf_new (); - gtk_tree_view_column_pack_start (column, renderer, FALSE); - gtk_tree_view_column_set_attributes (column, renderer, - "texture", 0, - NULL); - renderer = gtk_cell_renderer_text_new (); - g_object_set (renderer, - "ellipsize", PANGO_ELLIPSIZE_MIDDLE, - "ellipsize-set", TRUE, - NULL); - gtk_tree_view_column_pack_start (column, renderer, TRUE); - gtk_tree_view_column_set_attributes (column, renderer, - "markup", 1, - NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column); - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree_view), FALSE); + store = g_list_store_new (process_data_get_type ()); + factory = gtk_signal_list_item_factory_new (); + + g_signal_connect (factory, "setup", G_CALLBACK (setup_process_row), op); + g_signal_connect (factory, "bind", G_CALLBACK (bind_process_row), op); + list_view = gtk_list_view_new (GTK_SELECTION_MODEL (gtk_single_selection_new (G_LIST_MODEL (store))), factory); + + gtk_widget_set_size_request (list_view, 300, 120); scrolled_window = gtk_scrolled_window_new (); + gtk_widget_set_vexpand (scrolled_window, TRUE); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_propagate_natural_height (GTK_SCROLLED_WINDOW (scrolled_window), TRUE); gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (scrolled_window), TRUE); - gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled_window), tree_view); + gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled_window), list_view); gtk_box_append (GTK_BOX (vbox), scrolled_window); - controller = gtk_shortcut_controller_new (); - trigger = gtk_alternative_trigger_new (gtk_keyval_trigger_new (GDK_KEY_F10, GDK_SHIFT_MASK), - gtk_keyval_trigger_new (GDK_KEY_Menu, 0)); - action = gtk_callback_action_new (on_popup_menu_for_process_tree_view, - op, - NULL); - shortcut = gtk_shortcut_new_with_arguments (trigger, action, "s", "sv"); - gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut); - gtk_widget_add_controller (GTK_WIDGET (tree_view), controller); - - gesture = gtk_gesture_click_new (); - gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_SECONDARY); - g_signal_connect (gesture, "pressed", - G_CALLBACK (click_cb), op); - gtk_widget_add_controller (tree_view, GTK_EVENT_CONTROLLER (gesture)); - - list_store = gtk_list_store_new (3, - GDK_TYPE_TEXTURE, - G_TYPE_STRING, - G_TYPE_INT); - - gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), GTK_TREE_MODEL (list_store)); - - priv->process_list_store = list_store; - priv->process_tree_view = tree_view; + button = gtk_button_new_with_mnemonic (_("End Process")); + gtk_widget_set_halign (button, GTK_ALIGN_END); + g_signal_connect (button, "clicked", G_CALLBACK (on_end_process_activated), op); + gtk_box_append (GTK_BOX (vbox), button); + + priv->process_list_store = store; + priv->process_list_view = list_view; /* set pointers to NULL when dialog goes away */ g_object_add_weak_pointer (G_OBJECT (priv->process_list_store), (gpointer *) &priv->process_list_store); - g_object_add_weak_pointer (G_OBJECT (priv->process_tree_view), (gpointer *) &priv->process_tree_view); + g_object_add_weak_pointer (G_OBJECT (priv->process_list_view), (gpointer *) &priv->process_list_view); - g_object_unref (list_store); g_object_ref (op); return dialog; |