toolbar: Use list box for operations list

Using a GtkBox to display a dynamic list requires us to manually add
and remove children, relying on the GtkContainer API, gone in GTK4.

Instead, we can use GtkListBox, which we can pass a model and let
it take care of creating and disposing of children for us.

After the GTK4 switch, we should probably replace it with GtkListView
to avoid the default behaviors of GtkListBox which we are adding
workarounds for.
This commit is contained in:
António Fernandes 2021-11-25 16:42:07 +00:00
parent 57e3910e5e
commit cfdee53695
4 changed files with 46 additions and 29 deletions

View file

@ -90,7 +90,8 @@ struct _NautilusToolbar
GtkWidget *app_menu;
GtkWidget *operations_popover;
GtkWidget *operations_container;
GtkWidget *operations_list;
GListStore *progress_infos_model;
GtkWidget *operations_revealer;
GtkWidget *operations_icon;
@ -516,14 +517,10 @@ update_operations (NautilusToolbar *self)
{
GList *progress_infos;
GList *l;
GtkWidget *progress;
gboolean should_show_progress_button = FALSE;
gtk_container_foreach (GTK_CONTAINER (self->operations_container),
(GtkCallback) gtk_widget_destroy,
NULL);
disconnect_progress_infos (self);
g_list_store_remove_all (self->progress_infos_model);
progress_infos = get_filtered_progress_infos (self);
for (l = progress_infos; l != NULL; l = l->next)
@ -537,10 +534,7 @@ update_operations (NautilusToolbar *self)
G_CALLBACK (on_progress_info_cancelled), self);
g_signal_connect_swapped (l->data, "progress-changed",
G_CALLBACK (on_progress_info_progress_changed), self);
progress = nautilus_progress_info_widget_new (l->data);
gtk_box_pack_start (GTK_BOX (self->operations_container),
progress,
FALSE, FALSE, 0);
g_list_store_append (self->progress_infos_model, l->data);
}
g_list_free (progress_infos);
@ -887,6 +881,19 @@ on_location_entry_focus_changed (GObject *object,
}
}
static GtkWidget *
operations_list_create_widget (GObject *item,
gpointer user_data)
{
NautilusProgressInfo *info = NAUTILUS_PROGRESS_INFO (item);
GtkWidget *widget;
widget = nautilus_progress_info_widget_new (info);
gtk_widget_show_all (widget);
return widget;
}
static void
nautilus_toolbar_constructed (GObject *object)
{
@ -912,6 +919,12 @@ nautilus_toolbar_constructed (GObject *object)
g_signal_connect (self->progress_manager, "has-viewers-changed",
G_CALLBACK (on_progress_has_viewers_changed), self);
self->progress_infos_model = g_list_store_new (NAUTILUS_TYPE_PROGRESS_INFO);
gtk_list_box_bind_model (GTK_LIST_BOX (self->operations_list),
G_LIST_MODEL (self->progress_infos_model),
(GtkListBoxCreateWidgetFunc) operations_list_create_widget,
NULL,
NULL);
update_operations (self);
self->back_button_longpress_gesture = gtk_gesture_long_press_new (self->back_button);
@ -1149,6 +1162,7 @@ nautilus_toolbar_finalize (GObject *obj)
unschedule_operations_start (self);
unschedule_operations_button_attention_style (self);
g_clear_object (&self->progress_infos_model);
g_signal_handlers_disconnect_by_data (self->progress_manager, self);
g_clear_object (&self->progress_manager);
@ -1212,7 +1226,7 @@ nautilus_toolbar_class_init (NautilusToolbarClass *klass)
gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, operations_button);
gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, operations_icon);
gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, operations_popover);
gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, operations_container);
gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, operations_list);
gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, operations_revealer);
gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, view_button);
gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, view_toggle_button);

View file

@ -42,6 +42,13 @@
animation-iteration-count: 3;
}
/* Remove white background and highlight on hover which GTK adds by default
* to GtkListBox. TODO: Switch to GtkListView and drop this CSS hack. */
.operations-list,
.operations-list > :hover {
background: none;
}
.disclosure-button {
padding-left: 4px;
padding-right: 4px;

View file

@ -10,8 +10,10 @@
<template class="NautilusProgressInfoWidget" parent="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_start">5</property>
<property name="margin_end">5</property>
<property name="margin_start">6</property>
<property name="margin_end">6</property>
<property name="margin_top">6</property>
<property name="margin_bottom">6</property>
<child>
<object class="GtkLabel" id="status">
<property name="width_request">300</property>

View file

@ -405,24 +405,18 @@
<property name="max_content_height">270</property>
<property name="propagate_natural_height">True</property>
<child>
<object class="GtkViewport">
<object class="GtkListBox" id="operations_list">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkBox" id="operations_container">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_start">12</property>
<property name="margin_end">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="orientation">vertical</property>
<property name="spacing">10</property>
<child>
<placeholder/>
</child>
</object>
</child>
<property name="margin_start">6</property>
<property name="margin_end">6</property>
<property name="margin_top">6</property>
<property name="margin_bottom">6</property>
<property name="selection-mode">none</property>
<property name="activate-on-single-click">False</property>
<style>
<class name="operations-list"/>
</style>
</object>
</child>
</object>