From 4be0ac6d0b706ba2c0a861d60593f4b666452bc7 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 10 May 2007 12:40:02 +0100 Subject: Use GtkTreeModelSort to proxy the recent files list Add a new indirection, allowing sorting to work over the filtered list of recent files displayed by the file list view. Signed-off-by: Emmanuele Bassi --- gtk/gtkfilechooserdefault.c | 130 +++++++++++++++++++++++++++++++----------- gtk/gtkfilechooserprivate.h | 1 + 2 files changed, 97 insertions(+), 34 deletions(-) diff --git a/gtk/gtkfilechooserdefault.c b/gtk/gtkfilechooserdefault.c index 71b4884..68455ce 100644 --- a/gtk/gtkfilechooserdefault.c +++ b/gtk/gtkfilechooserdefault.c @@ -489,6 +489,10 @@ static void recent_clear_model (GtkFileChooserDefault *impl, static gboolean recent_should_respond (GtkFileChooserDefault *impl); static void recent_switch_to_browse_mode (GtkFileChooserDefault *impl); static GSList * recent_get_selected_paths (GtkFileChooserDefault *impl); +static void recent_get_valid_child_iter (GtkFileChooserDefault *impl, + GtkTreeIter *child_iter, + GtkTreeIter *iter); + @@ -2653,8 +2657,7 @@ add_bookmark_foreach_cb (GtkTreeModel *model, break; case OPERATION_MODE_RECENT: - gtk_tree_model_filter_convert_iter_to_child_iter (impl->recent_model_filter, - &child_iter, iter); + recent_get_valid_child_iter (impl, &child_iter, iter); gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter, RECENT_MODEL_COL_PATH, &file_path, -1); @@ -2788,7 +2791,7 @@ selection_check_foreach_cb (GtkTreeModel *model, break; case OPERATION_MODE_RECENT: - gtk_tree_model_filter_convert_iter_to_child_iter (closure->impl->recent_model_filter, &child_iter, iter); + recent_get_valid_child_iter (closure->impl, &child_iter, iter); gtk_tree_model_get (GTK_TREE_MODEL (closure->impl->recent_model), &child_iter, RECENT_MODEL_COL_IS_FOLDER, &is_folder, -1); @@ -2862,7 +2865,7 @@ get_selected_path_foreach_cb (GtkTreeModel *model, break; case OPERATION_MODE_RECENT: - gtk_tree_model_filter_convert_iter_to_child_iter (closure->impl->recent_model_filter, &child_iter, iter); + recent_get_valid_child_iter (closure->impl, &child_iter, iter); gtk_tree_model_get (GTK_TREE_MODEL (closure->impl->recent_model), &child_iter, RECENT_MODEL_COL_PATH, &closure->path, -1); @@ -2925,7 +2928,7 @@ update_tooltip (GtkTreeModel *model, break; case OPERATION_MODE_RECENT: - gtk_tree_model_filter_convert_iter_to_child_iter (udata->impl->recent_model_filter, &child_iter, iter); + recent_get_valid_child_iter (udata->impl, &child_iter, iter); gtk_tree_model_get (GTK_TREE_MODEL (udata->impl->recent_model), &child_iter, RECENT_MODEL_COL_DISPLAY_NAME, &display_name, -1); @@ -6691,9 +6694,7 @@ update_chooser_entry (GtkFileChooserDefault *impl) } else if (impl->operation_mode == OPERATION_MODE_RECENT) { - gtk_tree_model_filter_convert_iter_to_child_iter (impl->recent_model_filter, - &child_iter, - &closure.first_selected_iter); + recent_get_valid_child_iter (impl, &child_iter, &closure.first_selected_iter); gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter, RECENT_MODEL_COL_DISPLAY_NAME, &file_part, -1); @@ -9301,6 +9302,9 @@ recent_clear_model (GtkFileChooserDefault *impl, g_object_unref (impl->recent_model_filter); impl->recent_model_filter = NULL; + g_object_unref (impl->recent_model_sort); + impl->recent_model_sort = NULL; + if (remove_from_treeview) gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view), NULL); } @@ -9364,6 +9368,12 @@ recent_column_mtime_sort_func (GtkTreeModel *model, RECENT_MODEL_COL_IS_FOLDER, &is_folder_b, RECENT_MODEL_COL_INFO, &info_b, -1); + + if (!info_a) + return 1; + + if (!info_b) + return -1; /* folders always go first */ if (is_folder_a != is_folder_b) @@ -9377,6 +9387,26 @@ recent_column_mtime_sort_func (GtkTreeModel *model, return 0; } +static gint +recent_column_path_sort_func (GtkTreeModel *model, + GtkTreeIter *a, + GtkTreeIter *b, + gpointer user_data) +{ + gchar *name_a, *name_b; + + gtk_tree_model_get (model, a, RECENT_MODEL_COL_DISPLAY_NAME, &name_a, -1); + gtk_tree_model_get (model, b, RECENT_MODEL_COL_DISPLAY_NAME, &name_b, -1); + + if (!name_a) + return 1; + + if (!name_b); + return -1; + + return strcmp (name_a, name_b); +} + static gboolean recent_get_is_filtered (GtkFileChooserDefault *impl, const GtkFilePath *path, @@ -9457,6 +9487,7 @@ recent_setup_model (GtkFileChooserDefault *impl) { g_assert (impl->recent_model == NULL); g_assert (impl->recent_model_filter == NULL); + g_assert (impl->recent_model_sort == NULL); /* We store these columns in the search model: * @@ -9479,15 +9510,6 @@ recent_setup_model (GtkFileChooserDefault *impl) G_TYPE_POINTER, G_TYPE_BOOLEAN, G_TYPE_POINTER); - - gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->recent_model), - RECENT_MODEL_COL_INFO, - recent_column_mtime_sort_func, - impl, - NULL); - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (impl->recent_model), - RECENT_MODEL_COL_INFO, - GTK_SORT_DESCENDING); impl->recent_model_filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL (impl->recent_model), NULL)); @@ -9495,6 +9517,28 @@ recent_setup_model (GtkFileChooserDefault *impl) recent_model_visible_func, impl, NULL); + + /* this is the model that will actually be added to + * the browse_files_tree_view widget; remember: we are + * stuffing the real model into a filter model and then + * into a sort model; this means we'll have to translate + * the child iterator *twice* to get from a path or an + * iterator coming from the tree view widget to the + * real data inside the model. + */ + impl->recent_model_sort = + GTK_TREE_MODEL_SORT (gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (impl->recent_model_filter))); + gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->recent_model_sort), + RECENT_MODEL_COL_INFO, + recent_column_mtime_sort_func, + impl, NULL); + gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->recent_model_sort), + RECENT_MODEL_COL_PATH, + recent_column_path_sort_func, + impl, NULL); + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (impl->recent_model_sort), + RECENT_MODEL_COL_INFO, + GTK_SORT_DESCENDING); } typedef struct @@ -9512,7 +9556,7 @@ recent_idle_cleanup (gpointer data) GtkFileChooserDefault *impl = load_data->impl; gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view), - GTK_TREE_MODEL (impl->recent_model_filter)); + GTK_TREE_MODEL (impl->recent_model_sort)); set_busy_cursor (impl, FALSE); @@ -9749,8 +9793,6 @@ recent_hide_entry (GtkFileChooserDefault *impl) gtk_widget_hide (impl->location_button); gtk_widget_hide (impl->location_entry_box); } - - /* EB: hide the filter combo? */ } /* Main entry point to the recent files functions; this gets called when @@ -9792,6 +9834,33 @@ recent_activate (GtkFileChooserDefault *impl) recent_start_loading (impl); } +/* convert an iterator coming from the model bound to + * browse_files_tree_view to an interator inside the + * real recent_model + */ +static void +recent_get_valid_child_iter (GtkFileChooserDefault *impl, + GtkTreeIter *child_iter, + GtkTreeIter *iter) +{ + GtkTreeIter middle; + + if (!impl->recent_model) + return; + + if (!impl->recent_model_filter || !impl->recent_model_sort) + return; + + /* pass 1: get the iterator in the filter model */ + gtk_tree_model_sort_convert_iter_to_child_iter (impl->recent_model_sort, + &middle, iter); + + /* pass 2: get the iterator in the real model */ + gtk_tree_model_filter_convert_iter_to_child_iter (impl->recent_model_filter, + child_iter, + &middle); +} + static void set_current_filter (GtkFileChooserDefault *impl, @@ -9893,13 +9962,11 @@ check_preview_change (GtkFileChooserDefault *impl) { GtkTreeIter iter; - gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->recent_model_filter), + gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->recent_model_sort), &iter, cursor_path); gtk_tree_path_free (cursor_path); - gtk_tree_model_filter_convert_iter_to_child_iter (impl->recent_model_filter, - &child_iter, &iter); - + recent_get_valid_child_iter (impl, &child_iter, &iter); gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter, RECENT_MODEL_COL_PATH, &new_path, RECENT_MODEL_COL_DISPLAY_NAME, &new_display_name, @@ -10298,12 +10365,10 @@ list_row_activated (GtkTreeView *tree_view, GtkFilePath *file_path; gboolean is_folder; - if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->recent_model_filter), &iter, path)) + if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->recent_model_sort), &iter, path)) return; - gtk_tree_model_filter_convert_iter_to_child_iter (impl->recent_model_filter, - &child_iter, &iter); - + recent_get_valid_child_iter (impl, &child_iter, &iter); gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter, RECENT_MODEL_COL_PATH, &file_path, RECENT_MODEL_COL_IS_FOLDER, &is_folder, @@ -10416,9 +10481,7 @@ list_icon_data_func (GtkTreeViewColumn *tree_column, GtkTreeIter child_iter; GtkRecentInfo *info; - gtk_tree_model_filter_convert_iter_to_child_iter (impl->recent_model_filter, - &child_iter, iter); - + recent_get_valid_child_iter (impl, &child_iter, iter); gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter, RECENT_MODEL_COL_INFO, &info, -1); @@ -10520,8 +10583,7 @@ list_name_data_func (GtkTreeViewColumn *tree_column, GtkRecentInfo *recent_info; char *tmp, *text; - gtk_tree_model_filter_convert_iter_to_child_iter (impl->recent_model_filter, &child_iter, iter); - + recent_get_valid_child_iter (impl, &child_iter, iter); gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter, RECENT_MODEL_COL_INFO, &recent_info, -1); @@ -10652,7 +10714,7 @@ list_mtime_data_func (GtkTreeViewColumn *tree_column, GtkTreeIter child_iter; GtkRecentInfo *info; - gtk_tree_model_filter_convert_iter_to_child_iter (impl->recent_model_filter, &child_iter, iter); + recent_get_valid_child_iter (impl, &child_iter, iter); gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter, RECENT_MODEL_COL_INFO, &info, -1); diff --git a/gtk/gtkfilechooserprivate.h b/gtk/gtkfilechooserprivate.h index d5e87d8..16abb5c 100644 --- a/gtk/gtkfilechooserprivate.h +++ b/gtk/gtkfilechooserprivate.h @@ -203,6 +203,7 @@ struct _GtkFileChooserDefault GtkListStore *recent_model; guint load_recent_id; GtkTreeModelFilter *recent_model_filter; + GtkTreeModelSort *recent_model_sort; GtkWidget *filter_combo_hbox; GtkWidget *filter_combo; -- 1.4.4.2