[gtk+/gtk-2.90] Improve show_and_select_files() function



commit 2487f1837b1f36397bafa0ae30be5969665d2cbf
Author: Benjamin Otte <otte gnome org>
Date:   Wed Jul 1 10:32:26 2009 +0200

    Improve show_and_select_files() function
    
    The previous function enumerated the whole directory and used a lot of
    outdated API to decide how to show files.
    The new code queries the filesystem model to decide about this.
    The now unused old functions were removed.

 gtk/gtkfilechooserdefault.c |  248 +++++++-----------------------------------
 gtk/gtkfilechooserprivate.h |    1 -
 gtk/gtkfilesystemmodel.c    |   62 ++++++++++-
 gtk/gtkfilesystemmodel.h    |    2 +
 4 files changed, 101 insertions(+), 212 deletions(-)
---
diff --git a/gtk/gtkfilechooserdefault.c b/gtk/gtkfilechooserdefault.c
index 8587a76..ea3d1f0 100644
--- a/gtk/gtkfilechooserdefault.c
+++ b/gtk/gtkfilechooserdefault.c
@@ -369,11 +369,6 @@ static void list_row_activated         (GtkTreeView           *tree_view,
 					GtkTreeViewColumn     *column,
 					GtkFileChooserDefault *impl);
 
-static void select_func (GtkFileSystemModel *model,
-			 GtkTreePath        *path,
-			 GtkTreeIter        *iter,
-			 gpointer            user_data);
-
 static void path_bar_clicked (GtkPathBar            *path_bar,
 			      GFile                 *file,
 			      GFile                 *child,
@@ -5637,12 +5632,6 @@ gtk_file_chooser_default_dispose (GObject *object)
       impl->update_current_folder_cancellable = NULL;
     }
 
-  if (impl->show_and_select_files_cancellable)
-    {
-      g_cancellable_cancel (impl->show_and_select_files_cancellable);
-      impl->show_and_select_files_cancellable = NULL;
-    }
-
   if (impl->should_respond_get_info_cancellable)
     {
       g_cancellable_cancel (impl->should_respond_get_info_cancellable);
@@ -5862,52 +5851,6 @@ gtk_file_chooser_default_size_allocate (GtkWidget     *widget,
   GTK_WIDGET_CLASS (_gtk_file_chooser_default_parent_class)->size_allocate (widget, allocation);
 }
 
-static gboolean
-get_is_file_filtered (GtkFileChooserDefault *impl,
-		      GFile                 *file,
-		      GFileInfo             *file_info)
-{
-  GtkFileFilterInfo filter_info;
-  GtkFileFilterFlags needed;
-  gboolean result;
-
-  if (!impl->current_filter)
-    return FALSE;
-
-  filter_info.contains = GTK_FILE_FILTER_DISPLAY_NAME | GTK_FILE_FILTER_MIME_TYPE;
-
-  needed = gtk_file_filter_get_needed (impl->current_filter);
-
-  filter_info.display_name = g_file_info_get_display_name (file_info);
-  filter_info.mime_type = g_content_type_get_mime_type (g_file_info_get_content_type (file_info));
-
-  if (needed & GTK_FILE_FILTER_FILENAME)
-    {
-      filter_info.filename = g_file_get_path (file);
-      if (filter_info.filename)
-	filter_info.contains |= GTK_FILE_FILTER_FILENAME;
-    }
-  else
-    filter_info.filename = NULL;
-
-  if (needed & GTK_FILE_FILTER_URI)
-    {
-      filter_info.uri = g_file_get_uri (file);
-      if (filter_info.uri)
-	filter_info.contains |= GTK_FILE_FILTER_URI;
-    }
-  else
-    filter_info.uri = NULL;
-
-  result = gtk_file_filter_filter (impl->current_filter, &filter_info);
-
-  g_free ((gchar *)filter_info.filename);
-  g_free ((gchar *)filter_info.uri);
-  g_free ((gchar *)filter_info.mime_type);
-
-  return !result;
-}
-
 static void
 set_sort_column (GtkFileChooserDefault *impl)
 {
@@ -6356,151 +6299,58 @@ browse_files_center_selected_row (GtkFileChooserDefault *impl)
   gtk_tree_selection_selected_foreach (selection, center_selected_row_foreach_cb, &closure);
 }
 
-struct ShowAndSelectPathsData
-{
-  GtkFileChooserDefault *impl;
-  GSList *files;
-};
-
-static void
-show_and_select_files_finished_loading (GtkFolder *folder,
-					gpointer   user_data)
+static gboolean
+show_and_select_files (GtkFileChooserDefault *impl,
+		       GSList                *files)
 {
-  gboolean have_hidden;
-  gboolean have_filtered;
-  GSList *l;
-  struct ShowAndSelectPathsData *data = user_data;
-
-  have_hidden = FALSE;
-  have_filtered = FALSE;
-
-  for (l = data->files; l; l = l->next)
-    {
-      GFile *file;
-      GFileInfo *info;
-
-      file = l->data;
-
-      info = _gtk_folder_get_info (folder, file);
-      if (info)
-	{
-	  if (!have_hidden)
-	    have_hidden = g_file_info_get_is_hidden (info)
-	                    || g_file_info_get_is_backup (info);
-
-	  if (!have_filtered)
-	    have_filtered = (! _gtk_file_info_consider_as_directory (info)) &&
-			     get_is_file_filtered (data->impl, file, info);
-	
-	  g_object_unref (info);
-
-	  if (have_hidden && have_filtered)
-	    break; /* we now have all the information we need */
-	}
-    }
-
-  g_signal_handlers_disconnect_by_func (folder,
-					show_and_select_files_finished_loading,
-				        user_data);
-
-  if (have_hidden)
-    g_object_set (data->impl, "show-hidden", TRUE, NULL);
+  GtkTreeSelection *selection;
+  GtkFileSystemModel *fsmodel;
+  gboolean can_have_hidden, can_have_filtered, selected_a_file;
+  GSList *walk;
 
-  if (have_filtered)
-    set_current_filter (data->impl, NULL);
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
+  fsmodel = GTK_FILE_SYSTEM_MODEL (gtk_tree_view_get_model (GTK_TREE_VIEW (impl->browse_files_tree_view)));
+  can_have_hidden = !impl->show_hidden;
+  can_have_filtered = impl->current_filter != NULL;
+  selected_a_file = FALSE;
 
-  for (l = data->files; l; l = l->next)
+  for (walk = files; walk && (can_have_hidden || can_have_filtered); walk = walk->next)
     {
-      GFile *file;
-      GtkTreePath *path;
+      GFile *file = walk->data;
       GtkTreeIter iter;
 
-      file = l->data;
-      if (!_gtk_file_system_model_get_iter_for_file (data->impl->browse_files_model,
-                                                     &iter,
-                                                     file))
-        return;
-
-      path = gtk_tree_model_get_path (GTK_TREE_MODEL (data->impl->browse_files_model), &iter);
-      select_func (data->impl->browse_files_model, path, &iter, data->impl);
-      gtk_tree_path_free (path);
-    }
-
-  browse_files_center_selected_row (data->impl);
-
-  g_object_unref (data->impl);
-  g_slist_foreach (data->files, (GFunc) g_object_unref, NULL);
-  g_slist_free (data->files);
-  g_free (data);
-}
-
-static void
-show_and_select_files_get_folder_cb (GCancellable *cancellable,
-				     GtkFolder    *folder,
-				     const GError *error,
-				     gpointer      user_data)
-{
-  gboolean cancelled = g_cancellable_is_cancelled (cancellable);
-  struct ShowAndSelectPathsData *data = user_data;
-
-  if (data->impl->show_and_select_files_cancellable != cancellable)
-    goto out;
-
-  data->impl->show_and_select_files_cancellable = NULL;
-
-  if (cancelled || error)
-    goto out;
-
-  g_object_unref (cancellable);
-
-  if (_gtk_folder_is_finished_loading (folder))
-    show_and_select_files_finished_loading (folder, user_data);
-  else
-    g_signal_connect (folder, "finished-loading",
-		      G_CALLBACK (show_and_select_files_finished_loading),
-		      user_data);
-
-  return;
-
-out:
-  g_object_unref (data->impl);
-  g_slist_foreach (data->files, (GFunc) g_object_unref, NULL);
-  g_slist_free (data->files);
-  g_free (data);
-
-  g_object_unref (cancellable);
-}
+      if (!_gtk_file_system_model_get_iter_for_file (fsmodel, &iter, file))
+        continue;
 
-static gboolean
-show_and_select_files (GtkFileChooserDefault *impl,
-		       GFile                 *parent_file,
-		       GSList                *files)
-{
-  struct ShowAndSelectPathsData *info;
+      if (!_gtk_file_system_model_get_is_visible (fsmodel, &iter))
+        {
+          GFileInfo *info = _gtk_file_system_model_get_info (fsmodel, &iter);
 
-  profile_start ("start", NULL);
+          if (can_have_hidden &&
+              (g_file_info_get_is_hidden (info) ||
+               g_file_info_get_is_backup (info)))
+            {
+              g_object_set (impl, "show-hidden", TRUE, NULL);
+              can_have_hidden = FALSE;
+            }
 
-  if (!files)
-    {
-      profile_end ("end", NULL);
-      return TRUE;
+          if (can_have_filtered)
+            {
+              set_current_filter (impl, NULL);
+              can_have_filtered = FALSE;
+            }
+        }
+          
+      if (_gtk_file_system_model_get_is_visible (fsmodel, &iter))
+        {
+          gtk_tree_selection_select_iter (selection, &iter);
+          selected_a_file = TRUE;
+        }
     }
 
-  info = g_new (struct ShowAndSelectPathsData, 1);
-  info->impl = g_object_ref (impl);
-  info->files = g_slist_copy (files);
-  g_slist_foreach (info->files, (GFunc) g_object_ref, NULL);
+  browse_files_center_selected_row (impl);
 
-  if (impl->show_and_select_files_cancellable)
-    g_cancellable_cancel (impl->show_and_select_files_cancellable);
-
-  impl->show_and_select_files_cancellable =
-    _gtk_file_system_get_folder (impl->file_system, parent_file,
- 				 "standard::is-hidden,standard::is-backup,standard::type,standard::name,standard::content-type",
-			         show_and_select_files_get_folder_cb, info);
-
-  profile_end ("end", NULL);
-  return TRUE;
+  return selected_a_file;
 }
 
 /* Processes the pending operation when a folder is finished loading */
@@ -6512,7 +6362,7 @@ pending_select_files_process (GtkFileChooserDefault *impl)
 
   if (impl->pending_select_files)
     {
-      show_and_select_files (impl, impl->current_folder, impl->pending_select_files);
+      show_and_select_files (impl, impl->pending_select_files);
       pending_select_files_free (impl);
       browse_files_center_selected_row (impl);
     }
@@ -7376,20 +7226,6 @@ gtk_file_chooser_default_set_current_name (GtkFileChooser *chooser,
   _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), name);
 }
 
-static void
-select_func (GtkFileSystemModel *model,
-	     GtkTreePath        *path,
-	     GtkTreeIter        *iter,
-	     gpointer            user_data)
-{
-  GtkFileChooserDefault *impl = user_data;
-  GtkTreeSelection *selection;
-
-  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
-
-  gtk_tree_selection_select_iter (selection, iter);
-}
-
 static gboolean
 gtk_file_chooser_default_select_file (GtkFileChooser  *chooser,
 				      GFile           *file,
@@ -7425,7 +7261,7 @@ gtk_file_chooser_default_select_file (GtkFileChooser  *chooser,
       files.data = (gpointer) file;
       files.next = NULL;
 
-      result = show_and_select_files (impl, parent_file, &files);
+      result = show_and_select_files (impl, &files);
       g_object_unref (parent_file);
       return result;
     }
diff --git a/gtk/gtkfilechooserprivate.h b/gtk/gtkfilechooserprivate.h
index 933bd86..9f02b42 100644
--- a/gtk/gtkfilechooserprivate.h
+++ b/gtk/gtkfilechooserprivate.h
@@ -233,7 +233,6 @@ struct _GtkFileChooserDefault
   GSList *reload_icon_cancellables;
   GCancellable *file_list_drag_data_received_cancellable;
   GCancellable *update_current_folder_cancellable;
-  GCancellable *show_and_select_files_cancellable;
   GCancellable *should_respond_get_info_cancellable;
   GCancellable *file_exists_get_info_cancellable;
   GCancellable *update_from_entry_cancellable;
diff --git a/gtk/gtkfilesystemmodel.c b/gtk/gtkfilesystemmodel.c
index 300addf..e2a7c4e 100644
--- a/gtk/gtkfilesystemmodel.c
+++ b/gtk/gtkfilesystemmodel.c
@@ -968,11 +968,6 @@ gtk_file_system_model_got_files (GObject *object, GAsyncResult *res, gpointer da
                                      model->cancellable,
                                      gtk_file_system_model_closed_enumerator,
                                      NULL);
-      if (error)
-        g_error_free (error);
-      else
-        g_signal_emit (model, file_system_model_signals[FINISHED_LOADING], 0, NULL);
-
       if (model->dir_thaw_source != 0)
         {
           g_source_remove (model->dir_thaw_source);
@@ -980,6 +975,11 @@ gtk_file_system_model_got_files (GObject *object, GAsyncResult *res, gpointer da
           _gtk_file_system_model_thaw_updates (model);
         }
 
+      if (error)
+        g_error_free (error);
+      else
+        g_signal_emit (model, file_system_model_signals[FINISHED_LOADING], 0, NULL);
+
       g_object_unref (model);
     }
   else
@@ -1315,6 +1315,17 @@ _gtk_file_system_model_set_show_files (GtkFileSystemModel *model,
     }
 }
 
+/**
+ * _gtk_file_system_model_get_cancellable:
+ * @model: the model
+ *
+ * Gets the cancellable used by the @model. This is the cancellable used
+ * internally by the @model that will be cancelled when @model is 
+ * disposed. So you can use it for operations that should be cancelled
+ * when the model goes away.
+ *
+ * Returns: The cancellable used by @model
+ **/
 GCancellable *
 _gtk_file_system_model_get_cancellable (GtkFileSystemModel *model)
 {
@@ -1324,6 +1335,32 @@ _gtk_file_system_model_get_cancellable (GtkFileSystemModel *model)
 }
 
 /**
+ * _gtk_file_system_model_get_is_visible:
+ * @model: the model
+ * @iter: a valid iterator
+ *
+ * Checks if the iterator is visible. A visible iterator references
+ * a row that is currently exposed using the #GtkTreeModel API. If
+ * the iterator is invisible, it references a file that is not shown
+ * for some reason, such as being filtered by the current filter or
+ * being a hidden file.
+ *
+ * Returns: %TRUE if the iterator is visible
+ **/
+gboolean
+_gtk_file_system_model_get_is_visible (GtkFileSystemModel *model,
+				       GtkTreeIter        *iter)
+{
+  FileModelNode *node;
+
+  g_return_val_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model), FALSE);
+  g_return_val_if_fail (iter != NULL, FALSE);
+
+  node = get_node (model, ITER_INDEX (iter));
+  return node->visible;
+}
+
+/**
  * _gtk_file_system_model_get_info:
  * @model: a #GtkFileSystemModel
  * @iter: a #GtkTreeIter pointing to a row of @model
@@ -1347,6 +1384,7 @@ _gtk_file_system_model_get_info (GtkFileSystemModel *model,
   FileModelNode *node;
 
   g_return_val_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model), NULL);
+  g_return_val_if_fail (iter != NULL, NULL);
 
   node = get_node (model, ITER_INDEX (iter));
   g_assert (node->info == NULL || G_IS_FILE_INFO (node->info));
@@ -1447,6 +1485,20 @@ node_get_for_file (GtkFileSystemModel *model,
   return 0;
 }
 
+/**
+ * _gtk_file_system_model_get_iter_for_file:
+ * @model: the model
+ * @iter: the iterator to be initialized
+ * @file: the file to look up
+ *
+ * Initializes @iter to point to the row used for @file, if @file is part 
+ * of the model. Note that upon successful return, @iter may point to an 
+ * invisible row in the @model. Use 
+ * _gtk_file_system_model_get_is_visible() to make sure it is visible to
+ * the tree view.
+ *
+ * Returns: %TRUE if file is part of the model and @iter was initialized
+ **/
 gboolean
 _gtk_file_system_model_get_iter_for_file (GtkFileSystemModel *model,
 					  GtkTreeIter        *iter,
diff --git a/gtk/gtkfilesystemmodel.h b/gtk/gtkfilesystemmodel.h
index 0ff4450..aebc3c8 100644
--- a/gtk/gtkfilesystemmodel.h
+++ b/gtk/gtkfilesystemmodel.h
@@ -53,6 +53,8 @@ GtkFileSystemModel *_gtk_file_system_model_new_for_directory(GFile *
                                                              guint               n_columns,
                                                              ...);
 GCancellable *      _gtk_file_system_model_get_cancellable  (GtkFileSystemModel *model);
+gboolean            _gtk_file_system_model_get_is_visible   (GtkFileSystemModel *model,
+							     GtkTreeIter        *iter);
 GFileInfo *         _gtk_file_system_model_get_info         (GtkFileSystemModel *model,
 							     GtkTreeIter        *iter);
 gboolean            _gtk_file_system_model_get_iter_for_file(GtkFileSystemModel *model,



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