[nautilus] nautilus-view-icon: Rework selection and loading



commit 1a1e367fd0a098e97f542b63e7361ba68a9166da
Author: Carlos Soriano <csoriano gnome org>
Date:   Fri Mar 10 14:10:45 2017 +0100

    nautilus-view-icon: Rework selection and loading
    
    Better performance, code design and fixes some issues.

 src/nautilus-view-icon-controller.c |   64 +++++++++++++++++++++--------
 src/nautilus-view-icon-ui.c         |   61 +++++++++++----------------
 src/nautilus-view-icon-ui.h         |    4 ++
 src/nautilus-view-item-model.c      |   42 -------------------
 src/nautilus-view-item-model.h      |    5 --
 src/nautilus-view-model.c           |   76 +++++++++++++++--------------------
 src/nautilus-view-model.h           |    8 ++-
 7 files changed, 114 insertions(+), 146 deletions(-)
---
diff --git a/src/nautilus-view-icon-controller.c b/src/nautilus-view-icon-controller.c
index 507eb94..9c32a18 100644
--- a/src/nautilus-view-icon-controller.c
+++ b/src/nautilus-view-icon-controller.c
@@ -250,7 +250,7 @@ real_clear (NautilusFilesView *files_view)
 {
     NautilusViewIconController *self = NAUTILUS_VIEW_ICON_CONTROLLER (files_view);
 
-    g_list_store_remove_all (nautilus_view_model_get_g_model (self->model));
+    nautilus_view_model_remove_all_items (self->model);
 }
 
 
@@ -279,13 +279,17 @@ real_get_selection (NautilusFilesView *files_view)
     NautilusViewIconController *self;
     GList *selected_files = NULL;
     GList *l;
-    g_autoptr (GQueue) selected_items = NULL;
+    g_autoptr (GList) selected_items = NULL;
 
     self = NAUTILUS_VIEW_ICON_CONTROLLER (files_view);
-    selected_items = nautilus_view_model_get_selected (self->model);
-    for (l = g_queue_peek_head_link (selected_items); l != NULL; l = l->next)
+    selected_items = gtk_flow_box_get_selected_children (GTK_FLOW_BOX (self->view_ui));
+    for (l = selected_items; l != NULL; l = l->next)
     {
-        selected_files = g_list_prepend (selected_files, l->data);
+        NautilusViewItemModel *item_model;
+
+        item_model = nautilus_view_icon_item_ui_get_model (NAUTILUS_VIEW_ICON_ITEM_UI (l->data));
+        selected_files = g_list_prepend (selected_files,
+                                         g_object_ref (nautilus_view_item_model_get_file (item_model)));
     }
 
     return selected_files;
@@ -378,7 +382,7 @@ real_set_selection (NautilusFilesView *files_view,
 
     selection_files = convert_glist_to_queue (selection);
     selection_item_models = nautilus_view_model_get_items_from_files (self->model, selection_files);
-    nautilus_view_model_set_selected (self->model, selection_item_models);
+    nautilus_view_icon_ui_set_selection (self->view_ui, selection_item_models);
     nautilus_files_view_notify_selection_changed (files_view);
 }
 
@@ -603,27 +607,53 @@ on_button_press_event (GtkWidget *widget,
                        gpointer   user_data)
 {
     NautilusViewIconController *self;
-    GList *selection;
+    g_autoptr (GList) selection = NULL;
     GtkWidget *child_at_pos;
-    NautilusViewItemModel *item_model;
     GdkEventButton *event_button;
 
     self = NAUTILUS_VIEW_ICON_CONTROLLER (user_data);
     event_button = (GdkEventButton *) event;
 
-    if ((event_button->button == GDK_BUTTON_SECONDARY))
+    /* Need to update the selection so the popup has the right actions enabled */
+    selection = nautilus_view_get_selection (NAUTILUS_VIEW (self));
+    child_at_pos = GTK_WIDGET (gtk_flow_box_get_child_at_pos (GTK_FLOW_BOX (self->view_ui),
+                                                              event_button->x, event_button->y));
+    if (child_at_pos != NULL)
     {
-        /* Need to update the selection so the popup has the right actions enabled */
-        selection = nautilus_view_get_selection (NAUTILUS_VIEW (self));
-        child_at_pos = GTK_WIDGET (gtk_flow_box_get_child_at_pos (GTK_FLOW_BOX (self->view_ui),
-                                                                  event_button->x, event_button->y));
+        NautilusFile *selected_file;
+        NautilusViewItemModel *item_model;
+
         item_model = nautilus_view_icon_item_ui_get_model (NAUTILUS_VIEW_ICON_ITEM_UI (child_at_pos));
-        selection = g_list_prepend (selection, nautilus_view_item_model_get_file (item_model));
+        selected_file = nautilus_view_item_model_get_file (item_model);
+        if (g_list_find (selection, selected_file) == NULL)
+        {
+            g_list_foreach (selection, (GFunc) g_object_unref, NULL);
+            selection = g_list_append (NULL, selected_file);
+        }
+        else
+        {
+            selection = g_list_prepend (selection, g_object_ref (selected_file));
+        }
+
         nautilus_view_set_selection (NAUTILUS_VIEW (self), selection);
 
-        nautilus_files_view_pop_up_selection_context_menu (NAUTILUS_FILES_VIEW (self),
-                                                           event_button);
+        if (event_button->button == GDK_BUTTON_SECONDARY)
+        {
+            nautilus_files_view_pop_up_selection_context_menu (NAUTILUS_FILES_VIEW (self),
+                                                               event_button);
+        }
     }
+    else
+    {
+        nautilus_view_set_selection (NAUTILUS_VIEW (self), NULL);
+        if (event_button->button == GDK_BUTTON_SECONDARY)
+        {
+            nautilus_files_view_pop_up_background_context_menu (NAUTILUS_FILES_VIEW (self),
+                                                                event_button);
+        }
+    }
+
+    g_list_foreach (selection, (GFunc) g_object_unref, NULL);
 
     return GDK_EVENT_STOP;
 }
@@ -727,7 +757,7 @@ real_add_files (NautilusFilesView *files_view,
 
     files_queue = convert_glist_to_queue (files);
     item_models = convert_files_to_item_models (self, files_queue);
-    nautilus_view_model_set_items (self->model, item_models);
+    nautilus_view_model_add_items (self->model, item_models);
 }
 
 
diff --git a/src/nautilus-view-icon-ui.c b/src/nautilus-view-icon-ui.c
index 6df82a7..1f2639f 100644
--- a/src/nautilus-view-icon-ui.c
+++ b/src/nautilus-view-icon-ui.c
@@ -98,25 +98,34 @@ set_property (GObject      *object,
     }
 }
 
-static void
-on_view_item_model_selected_changed (GObject    *object,
-                                     GParamSpec *pspec,
-                                     gpointer    user_data)
+void
+nautilus_view_icon_ui_set_selection (NautilusViewIconUi *self,
+                                     GQueue             *selection)
 {
-    NautilusViewIconUi *self;
     NautilusViewItemModel *item_model;
-    GtkFlowBoxChild *item_ui;
+    NautilusViewModel *model;
+    GListStore *gmodel;
+    gint i = 0;
 
-    self = NAUTILUS_VIEW_ICON_UI (user_data);
-    item_model = NAUTILUS_VIEW_ITEM_MODEL (object);
-    item_ui = GTK_FLOW_BOX_CHILD (nautilus_view_item_model_get_item_ui (item_model));
-    if (nautilus_view_item_model_get_is_selected (item_model) && !gtk_flow_box_child_is_selected (item_ui))
-    {
-        gtk_flow_box_select_child (GTK_FLOW_BOX (self), item_ui);
-    }
-    else if (!nautilus_view_item_model_get_is_selected (item_model) && gtk_flow_box_child_is_selected 
(item_ui))
+    model = nautilus_view_icon_controller_get_model (self->controller);
+    gmodel = nautilus_view_model_get_g_model (model);
+    while ((item_model = NAUTILUS_VIEW_ITEM_MODEL (g_list_model_get_item (G_LIST_MODEL (gmodel), i))))
     {
-        gtk_flow_box_unselect_child (GTK_FLOW_BOX (self), item_ui);
+        GtkWidget *item_ui;
+
+        item_ui = nautilus_view_item_model_get_item_ui (item_model);
+        if (g_queue_find (selection, item_model) != NULL)
+        {
+            gtk_flow_box_select_child (GTK_FLOW_BOX (self),
+                                       GTK_FLOW_BOX_CHILD (item_ui));
+        }
+        else
+        {
+            gtk_flow_box_unselect_child (GTK_FLOW_BOX (self),
+                                         GTK_FLOW_BOX_CHILD (item_ui));
+        }
+
+        i++;
     }
 }
 
@@ -125,7 +134,6 @@ static GtkWidget *
 create_widget_func (gpointer item,
                     gpointer user_data)
 {
-    NautilusViewIconUi *self = NAUTILUS_VIEW_ICON_UI (user_data);
     NautilusViewItemModel *item_model = NAUTILUS_VIEW_ITEM_MODEL (item);
     NautilusViewIconItemUi *child;
 
@@ -133,9 +141,6 @@ create_widget_func (gpointer item,
     nautilus_view_item_model_set_item_ui (item_model, GTK_WIDGET (child));
     gtk_widget_show (GTK_WIDGET (child));
 
-    g_signal_connect (item_model, "notify::selected",
-                      (GCallback) on_view_item_model_selected_changed, self);
-
     return GTK_WIDGET (child);
 }
 
@@ -161,25 +166,9 @@ on_ui_selected_children_changed (GtkFlowBox *box,
                                  gpointer    user_data)
 {
     NautilusViewIconUi *self;
-    GList *selected_children_ui;
-    GList *l;
-    GList *files_selection;
 
     self = NAUTILUS_VIEW_ICON_UI (user_data);
-    files_selection = NULL;
-
-    selected_children_ui = gtk_flow_box_get_selected_children (GTK_FLOW_BOX (self));
-    for (l = selected_children_ui; l != NULL; l = l->next)
-    {
-        NautilusViewItemModel *item_model;
-        NautilusFile *file;
-
-        item_model = nautilus_view_icon_item_ui_get_model (NAUTILUS_VIEW_ICON_ITEM_UI (l->data));
-        file = nautilus_view_item_model_get_file (item_model);
-        files_selection = g_list_prepend (files_selection, file);
-    }
-
-    nautilus_view_set_selection (NAUTILUS_VIEW (self->controller), files_selection);
+    nautilus_files_view_notify_selection_changed (NAUTILUS_FILES_VIEW (self->controller));
 }
 
 static void
diff --git a/src/nautilus-view-icon-ui.h b/src/nautilus-view-icon-ui.h
index 5361acc..e883275 100644
--- a/src/nautilus-view-icon-ui.h
+++ b/src/nautilus-view-icon-ui.h
@@ -30,6 +30,10 @@ G_BEGIN_DECLS
 G_DECLARE_FINAL_TYPE (NautilusViewIconUi, nautilus_view_icon_ui, NAUTILUS, VIEW_ICON_UI, GtkFlowBox)
 
 NautilusViewIconUi * nautilus_view_icon_ui_new (NautilusViewIconController *controller);
+/* TODO: this should become the "nautilus_view_set_selection" once we have a proper
+ * MVC also in the nautilus-view level. */
+void nautilus_view_icon_ui_set_selection (NautilusViewIconUi *self,
+                                          GQueue             *selection);
 
 G_END_DECLS
 
diff --git a/src/nautilus-view-item-model.c b/src/nautilus-view-item-model.c
index 970fb28..e50f2d8 100644
--- a/src/nautilus-view-item-model.c
+++ b/src/nautilus-view-item-model.c
@@ -7,7 +7,6 @@ struct _NautilusViewItemModel
     guint icon_size;
     NautilusFile *file;
     GtkLabel *label;
-    gboolean selected;
     GtkWidget *item_ui;
 };
 
@@ -18,7 +17,6 @@ enum
     PROP_0,
     PROP_FILE,
     PROP_ICON_SIZE,
-    PROP_SELECTED,
     PROP_ITEM_UI,
     N_PROPS
 };
@@ -51,12 +49,6 @@ nautilus_view_item_model_get_property (GObject    *object,
         }
         break;
 
-        case PROP_SELECTED:
-        {
-            g_value_set_boolean (value, self->selected);
-        }
-        break;
-
         case PROP_ITEM_UI:
         {
             g_value_set_object (value, self->item_ui);
@@ -92,12 +84,6 @@ nautilus_view_item_model_set_property (GObject      *object,
         }
         break;
 
-        case PROP_SELECTED:
-        {
-            nautilus_view_item_model_set_selected (self, g_value_get_boolean (value));
-        }
-        break;
-
         case PROP_ITEM_UI:
         {
             nautilus_view_item_model_set_item_ui (self, g_value_get_object (value));
@@ -141,13 +127,6 @@ nautilus_view_item_model_class_init (NautilusViewItemModelClass *klass)
                                                           "The file the icon item represents",
                                                           NAUTILUS_TYPE_FILE,
                                                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-    g_object_class_install_property (object_class,
-                                     PROP_SELECTED,
-                                     g_param_spec_boolean ("selected",
-                                                           "Selected",
-                                                           "Sets the item as selected",
-                                                           FALSE,
-                                                           G_PARAM_READWRITE));
 
     g_object_class_install_property (object_class,
                                      PROP_ITEM_UI,
@@ -207,27 +186,6 @@ nautilus_view_item_model_set_file (NautilusViewItemModel *self,
     g_object_notify (G_OBJECT (self), "file");
 }
 
-gboolean
-nautilus_view_item_model_get_is_selected (NautilusViewItemModel *self)
-{
-    g_return_val_if_fail (NAUTILUS_IS_VIEW_ITEM_MODEL (self), FALSE);
-
-    return self->selected;
-}
-
-void
-nautilus_view_item_model_set_selected (NautilusViewItemModel *self,
-                                       gboolean               selected)
-{
-    g_return_if_fail (NAUTILUS_IS_VIEW_ITEM_MODEL (self));
-
-    if (self->selected != !!selected)
-    {
-        self->selected = !!selected;
-        g_object_notify (G_OBJECT (self), "selected");
-    }
-}
-
 GtkWidget *
 nautilus_view_item_model_get_item_ui (NautilusViewItemModel *self)
 {
diff --git a/src/nautilus-view-item-model.h b/src/nautilus-view-item-model.h
index 39a8bc0..16870de 100644
--- a/src/nautilus-view-item-model.h
+++ b/src/nautilus-view-item-model.h
@@ -25,11 +25,6 @@ void nautilus_view_item_model_set_file (NautilusViewItemModel *self,
 
 NautilusFile * nautilus_view_item_model_get_file (NautilusViewItemModel *self);
 
-void nautilus_view_item_model_set_selected (NautilusViewItemModel *self,
-                                            gboolean               selected);
-
-gboolean nautilus_view_item_model_get_is_selected (NautilusViewItemModel *self);
-
 void nautilus_view_item_model_set_item_ui (NautilusViewItemModel *self,
                                            GtkWidget             *item_ui);
 
diff --git a/src/nautilus-view-model.c b/src/nautilus-view-model.c
index 2f054e5..f45ecef 100644
--- a/src/nautilus-view-model.c
+++ b/src/nautilus-view-model.c
@@ -233,67 +233,57 @@ nautilus_view_model_remove_item (NautilusViewModel     *self,
 
     if (item_model != NULL)
     {
+        NautilusFile *file;
+
+        file = nautilus_view_item_model_get_file (item_model);
         g_list_store_remove (self->internal_model, i);
+        g_hash_table_remove (self->map_files_to_model, file);
     }
 }
 
 void
+nautilus_view_model_remove_all_items (NautilusViewModel *self)
+{
+    g_list_store_remove_all (self->internal_model);
+    g_hash_table_remove_all (self->map_files_to_model);
+}
+
+void
 nautilus_view_model_add_item (NautilusViewModel     *self,
                               NautilusViewItemModel *item)
 {
+    g_hash_table_insert (self->map_files_to_model,
+                         nautilus_view_item_model_get_file (item),
+                         item);
     g_list_store_insert_sorted (self->internal_model, item, compare_data_func, self);
 }
 
 void
-nautilus_view_model_set_selected (NautilusViewModel *self,
-                                  GQueue            *item_models)
+nautilus_view_model_add_items (NautilusViewModel *self,
+                               GQueue            *items)
 {
+    g_autofree gpointer *array = NULL;
     GList *l;
-    NautilusViewItemModel *item_model;
-
-    gint i = 0;
-    while ((item_model = g_list_model_get_item (G_LIST_MODEL (self->internal_model), i)))
-    {
-        gboolean selected;
-
-        selected = FALSE;
-        for (l = g_queue_peek_head_link (item_models); l != NULL; l = l->next)
-        {
-            NautilusViewItemModel *selected_item_model;
-
-            selected_item_model = NAUTILUS_VIEW_ITEM_MODEL (l->data);
-            if (item_model == selected_item_model)
-            {
-                selected = TRUE;
-                break;
-            }
-        }
-        i++;
-
-        nautilus_view_item_model_set_selected (item_model, selected);
-    }
-}
+    int i = 0;
 
-GQueue *
-nautilus_view_model_get_selected (NautilusViewModel *self)
-{
-    NautilusViewItemModel *item_model;
-    GQueue *selected_items;
-    gint i;
+    array = g_malloc_n (g_queue_get_length (items),
+                        sizeof (NautilusViewItemModel *));
 
-    i = 0;
-    selected_items = g_queue_new ();
-    while ((item_model = g_list_model_get_item (G_LIST_MODEL (self->internal_model), i)))
+    g_hash_table_remove_all (self->map_files_to_model);
+    for (l = g_queue_peek_head_link (items); l != NULL; l = l->next)
     {
-        if (nautilus_view_item_model_get_is_selected (item_model))
-        {
-            g_queue_push_tail (selected_items,
-                               g_object_ref (nautilus_view_item_model_get_file (item_model)));
-        }
+        array[i] = l->data;
+        g_hash_table_insert (self->map_files_to_model,
+                             nautilus_view_item_model_get_file (l->data),
+                             l->data);
         i++;
     }
 
-    return selected_items;
+    g_list_store_splice (self->internal_model,
+                         g_list_model_get_n_items (G_LIST_MODEL (self->internal_model)),
+                         0, array, g_queue_get_length (items));
+
+    g_list_store_sort (self->internal_model, compare_data_func, self);
 }
 
 void
@@ -318,8 +308,8 @@ nautilus_view_model_set_items (NautilusViewModel *self,
     }
 
     g_list_store_splice (self->internal_model,
-                         g_list_model_get_n_items (G_LIST_MODEL (self->internal_model)),
-                         0, array, g_queue_get_length (items));
+                         0, g_list_model_get_n_items (G_LIST_MODEL (self->internal_model)),
+                         array, g_queue_get_length (items));
 
     g_list_store_sort (self->internal_model, compare_data_func, self);
 }
diff --git a/src/nautilus-view-model.h b/src/nautilus-view-model.h
index 9734032..5e64d84 100644
--- a/src/nautilus-view-model.h
+++ b/src/nautilus-view-model.h
@@ -28,13 +28,15 @@ NautilusViewItemModel * nautilus_view_model_get_item_from_file (NautilusViewMode
                                                                 NautilusFile      *file);
 GQueue * nautilus_view_model_get_items_from_files (NautilusViewModel *self,
                                                    GQueue            *files);
+/* Don't use inside a loop, use nautilus_view_model_remove_all_items instead. */
 void nautilus_view_model_remove_item (NautilusViewModel     *self,
                                       NautilusViewItemModel *item);
+void nautilus_view_model_remove_all_items (NautilusViewModel *self);
+/* Don't use inside a loop, use nautilus_view_model_add_items instead. */
 void nautilus_view_model_add_item (NautilusViewModel     *self,
                                    NautilusViewItemModel *item);
-void nautilus_view_model_set_selected (NautilusViewModel *self,
-                                       GQueue            *item_models);
-GQueue * nautilus_view_model_get_selected (NautilusViewModel *self);
+void nautilus_view_model_add_items (NautilusViewModel *self,
+                                    GQueue            *items);
 void nautilus_view_model_set_items (NautilusViewModel *self,
                                     GQueue            *items);
 G_END_DECLS


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]