filechooserentry: Use a GtkFileSystemModel
Replace the usage of a list store and a GtkFolder with a GtkFileSystemModel. This improves performance and reduces code size.
This commit is contained in:
parent
06a64daefc
commit
a1e0c1e042
@ -27,6 +27,7 @@
|
|||||||
#include "gtkcelllayout.h"
|
#include "gtkcelllayout.h"
|
||||||
#include "gtkcellrenderertext.h"
|
#include "gtkcellrenderertext.h"
|
||||||
#include "gtkentry.h"
|
#include "gtkentry.h"
|
||||||
|
#include "gtkfilesystemmodel.h"
|
||||||
#include "gtklabel.h"
|
#include "gtklabel.h"
|
||||||
#include "gtkmain.h"
|
#include "gtkmain.h"
|
||||||
#include "gtksizerequest.h"
|
#include "gtksizerequest.h"
|
||||||
@ -72,10 +73,6 @@ struct _GtkFileChooserEntry
|
|||||||
gchar *file_part;
|
gchar *file_part;
|
||||||
gint file_part_pos;
|
gint file_part_pos;
|
||||||
|
|
||||||
/* Folder being loaded or already loaded */
|
|
||||||
GtkFolder *current_folder;
|
|
||||||
GCancellable *load_folder_cancellable;
|
|
||||||
|
|
||||||
LoadCompleteAction load_complete_action;
|
LoadCompleteAction load_complete_action;
|
||||||
|
|
||||||
GtkTreeModel *completion_store;
|
GtkTreeModel *completion_store;
|
||||||
@ -154,8 +151,9 @@ typedef enum {
|
|||||||
|
|
||||||
static RefreshStatus refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry,
|
static RefreshStatus refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry,
|
||||||
RefreshMode refresh_mode);
|
RefreshMode refresh_mode);
|
||||||
static void finished_loading_cb (GtkFolder *folder,
|
static void finished_loading_cb (GtkFileSystemModel *model,
|
||||||
gpointer data);
|
GError *error,
|
||||||
|
GtkFileChooserEntry *chooser_entry);
|
||||||
static void autocomplete (GtkFileChooserEntry *chooser_entry);
|
static void autocomplete (GtkFileChooserEntry *chooser_entry);
|
||||||
static void install_start_autocompletion_idle (GtkFileChooserEntry *chooser_entry);
|
static void install_start_autocompletion_idle (GtkFileChooserEntry *chooser_entry);
|
||||||
static void remove_completion_feedback (GtkFileChooserEntry *chooser_entry);
|
static void remove_completion_feedback (GtkFileChooserEntry *chooser_entry);
|
||||||
@ -244,9 +242,6 @@ gtk_file_chooser_entry_finalize (GObject *object)
|
|||||||
if (chooser_entry->base_folder)
|
if (chooser_entry->base_folder)
|
||||||
g_object_unref (chooser_entry->base_folder);
|
g_object_unref (chooser_entry->base_folder);
|
||||||
|
|
||||||
if (chooser_entry->current_folder)
|
|
||||||
g_object_unref (chooser_entry->current_folder);
|
|
||||||
|
|
||||||
if (chooser_entry->current_folder_file)
|
if (chooser_entry->current_folder_file)
|
||||||
g_object_unref (chooser_entry->current_folder_file);
|
g_object_unref (chooser_entry->current_folder_file);
|
||||||
|
|
||||||
@ -258,19 +253,6 @@ gtk_file_chooser_entry_finalize (GObject *object)
|
|||||||
static void
|
static void
|
||||||
discard_loading_and_current_folder_file (GtkFileChooserEntry *chooser_entry)
|
discard_loading_and_current_folder_file (GtkFileChooserEntry *chooser_entry)
|
||||||
{
|
{
|
||||||
if (chooser_entry->current_folder)
|
|
||||||
{
|
|
||||||
g_signal_handlers_disconnect_by_func (chooser_entry->current_folder,
|
|
||||||
G_CALLBACK (finished_loading_cb), chooser_entry);
|
|
||||||
g_object_unref (chooser_entry->current_folder);
|
|
||||||
chooser_entry->current_folder = NULL;
|
|
||||||
}
|
|
||||||
if (chooser_entry->load_folder_cancellable)
|
|
||||||
{
|
|
||||||
g_cancellable_cancel (chooser_entry->load_folder_cancellable);
|
|
||||||
chooser_entry->load_folder_cancellable = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chooser_entry->current_folder_file)
|
if (chooser_entry->current_folder_file)
|
||||||
{
|
{
|
||||||
g_object_unref (chooser_entry->current_folder_file);
|
g_object_unref (chooser_entry->current_folder_file);
|
||||||
@ -478,7 +460,6 @@ find_common_prefix (GtkFileChooserEntry *chooser_entry,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
g_assert (parsed_folder_file != NULL
|
g_assert (parsed_folder_file != NULL
|
||||||
&& chooser_entry->current_folder != NULL
|
|
||||||
&& g_file_equal (parsed_folder_file, chooser_entry->current_folder_file));
|
&& g_file_equal (parsed_folder_file, chooser_entry->current_folder_file));
|
||||||
|
|
||||||
g_object_unref (parsed_folder_file);
|
g_object_unref (parsed_folder_file);
|
||||||
@ -980,7 +961,6 @@ explicitly_complete (GtkFileChooserEntry *chooser_entry)
|
|||||||
{
|
{
|
||||||
CommonPrefixResult result;
|
CommonPrefixResult result;
|
||||||
|
|
||||||
g_assert (chooser_entry->current_folder != NULL);
|
|
||||||
g_assert (chooser_entry->current_folder_loaded);
|
g_assert (chooser_entry->current_folder_loaded);
|
||||||
|
|
||||||
/* FIXME: see what Emacs does in case there is no common prefix, or there is more than one match:
|
/* FIXME: see what Emacs does in case there is no common prefix, or there is more than one match:
|
||||||
@ -1054,7 +1034,7 @@ start_explicit_completion (GtkFileChooserEntry *chooser_entry)
|
|||||||
case REFRESH_OK:
|
case REFRESH_OK:
|
||||||
g_assert (chooser_entry->current_folder_file != NULL);
|
g_assert (chooser_entry->current_folder_file != NULL);
|
||||||
|
|
||||||
if (chooser_entry->current_folder && chooser_entry->current_folder_loaded)
|
if (chooser_entry->current_folder_loaded)
|
||||||
explicitly_complete (chooser_entry);
|
explicitly_complete (chooser_entry);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1212,53 +1192,49 @@ discard_completion_store (GtkFileChooserEntry *chooser_entry)
|
|||||||
chooser_entry->completion_store = NULL;
|
chooser_entry->completion_store = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
completion_store_set (GtkFileSystemModel *model,
|
||||||
|
GFile *file,
|
||||||
|
GFileInfo *info,
|
||||||
|
int column,
|
||||||
|
GValue *value,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
switch (column)
|
||||||
|
{
|
||||||
|
case FILE_COLUMN:
|
||||||
|
g_value_set_object (value, file);
|
||||||
|
break;
|
||||||
|
case DISPLAY_NAME_COLUMN:
|
||||||
|
if (_gtk_file_info_consider_as_directory (info))
|
||||||
|
g_value_take_string (value, g_strconcat (g_file_info_get_display_name (info), G_DIR_SEPARATOR_S, NULL));
|
||||||
|
else
|
||||||
|
g_value_set_string (value, g_file_info_get_display_name (info));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Fills the completion store from the contents of the current folder */
|
/* Fills the completion store from the contents of the current folder */
|
||||||
static void
|
static void
|
||||||
populate_completion_store (GtkFileChooserEntry *chooser_entry)
|
populate_completion_store (GtkFileChooserEntry *chooser_entry)
|
||||||
{
|
{
|
||||||
GSList *files;
|
|
||||||
GSList *tmp_list;
|
|
||||||
|
|
||||||
discard_completion_store (chooser_entry);
|
discard_completion_store (chooser_entry);
|
||||||
|
|
||||||
files = _gtk_folder_list_children (chooser_entry->current_folder);
|
chooser_entry->completion_store = GTK_TREE_MODEL (
|
||||||
|
_gtk_file_system_model_new_for_directory (chooser_entry->current_folder_file,
|
||||||
chooser_entry->completion_store = GTK_TREE_MODEL (gtk_list_store_new (N_COLUMNS,
|
"standard::name,standard::display-name,standard::type",
|
||||||
|
completion_store_set,
|
||||||
|
chooser_entry,
|
||||||
|
N_COLUMNS,
|
||||||
G_TYPE_STRING,
|
G_TYPE_STRING,
|
||||||
G_TYPE_FILE));
|
G_TYPE_FILE));
|
||||||
|
g_signal_connect (chooser_entry->completion_store, "finished-loading",
|
||||||
for (tmp_list = files; tmp_list; tmp_list = tmp_list->next)
|
G_CALLBACK (finished_loading_cb), chooser_entry);
|
||||||
{
|
|
||||||
GFileInfo *info;
|
|
||||||
GFile *file;
|
|
||||||
|
|
||||||
file = tmp_list->data;
|
|
||||||
|
|
||||||
info = _gtk_folder_get_info (chooser_entry->current_folder, file);
|
|
||||||
|
|
||||||
if (info)
|
|
||||||
{
|
|
||||||
gchar *display_name = g_strdup (g_file_info_get_display_name (info));
|
|
||||||
GtkTreeIter iter;
|
|
||||||
|
|
||||||
if (_gtk_file_info_consider_as_directory (info))
|
|
||||||
display_name = g_strconcat (g_file_info_get_display_name (info), G_DIR_SEPARATOR_S, NULL);
|
|
||||||
else
|
|
||||||
display_name = g_strdup (g_file_info_get_display_name (info));
|
|
||||||
|
|
||||||
gtk_list_store_append (GTK_LIST_STORE (chooser_entry->completion_store), &iter);
|
|
||||||
gtk_list_store_set (GTK_LIST_STORE (chooser_entry->completion_store), &iter,
|
|
||||||
DISPLAY_NAME_COLUMN, display_name,
|
|
||||||
FILE_COLUMN, file,
|
|
||||||
-1);
|
|
||||||
|
|
||||||
g_object_unref (info);
|
|
||||||
g_free (display_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_slist_foreach (files, (GFunc) g_object_unref, NULL);
|
|
||||||
g_slist_free (files);
|
|
||||||
|
|
||||||
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (chooser_entry->completion_store),
|
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (chooser_entry->completion_store),
|
||||||
DISPLAY_NAME_COLUMN, GTK_SORT_ASCENDING);
|
DISPLAY_NAME_COLUMN, GTK_SORT_ASCENDING);
|
||||||
@ -1296,7 +1272,6 @@ perform_load_complete_action (GtkFileChooserEntry *chooser_entry)
|
|||||||
static void
|
static void
|
||||||
finish_folder_load (GtkFileChooserEntry *chooser_entry)
|
finish_folder_load (GtkFileChooserEntry *chooser_entry)
|
||||||
{
|
{
|
||||||
populate_completion_store (chooser_entry);
|
|
||||||
perform_load_complete_action (chooser_entry);
|
perform_load_complete_action (chooser_entry);
|
||||||
|
|
||||||
gtk_widget_set_tooltip_text (GTK_WIDGET (chooser_entry), NULL);
|
gtk_widget_set_tooltip_text (GTK_WIDGET (chooser_entry), NULL);
|
||||||
@ -1304,29 +1279,11 @@ finish_folder_load (GtkFileChooserEntry *chooser_entry)
|
|||||||
|
|
||||||
/* Callback when the current folder finishes loading */
|
/* Callback when the current folder finishes loading */
|
||||||
static void
|
static void
|
||||||
finished_loading_cb (GtkFolder *folder,
|
finished_loading_cb (GtkFileSystemModel *model,
|
||||||
gpointer data)
|
GError *error,
|
||||||
|
GtkFileChooserEntry *chooser_entry)
|
||||||
{
|
{
|
||||||
GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (data);
|
|
||||||
|
|
||||||
chooser_entry->current_folder_loaded = TRUE;
|
chooser_entry->current_folder_loaded = TRUE;
|
||||||
finish_folder_load (chooser_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Callback when the current folder's handle gets obtained (not necessarily loaded completely) */
|
|
||||||
static void
|
|
||||||
load_directory_get_folder_callback (GCancellable *cancellable,
|
|
||||||
GtkFolder *folder,
|
|
||||||
const GError *error,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
gboolean cancelled = g_cancellable_is_cancelled (cancellable);
|
|
||||||
GtkFileChooserEntry *chooser_entry = data;
|
|
||||||
|
|
||||||
if (cancellable != chooser_entry->load_folder_cancellable)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
chooser_entry->load_folder_cancellable = NULL;
|
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
@ -1344,26 +1301,11 @@ load_directory_get_folder_callback (GCancellable *cancellable,
|
|||||||
beep (chooser_entry);
|
beep (chooser_entry);
|
||||||
pop_up_completion_feedback (chooser_entry, error->message);
|
pop_up_completion_feedback (chooser_entry, error->message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cancelled || error)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
g_assert (folder != NULL);
|
|
||||||
chooser_entry->current_folder = g_object_ref (folder);
|
|
||||||
|
|
||||||
discard_completion_store (chooser_entry);
|
|
||||||
|
|
||||||
chooser_entry->current_folder_loaded = _gtk_folder_is_finished_loading (chooser_entry->current_folder);
|
|
||||||
if (chooser_entry->current_folder_loaded)
|
|
||||||
finish_folder_load (chooser_entry);
|
finish_folder_load (chooser_entry);
|
||||||
else
|
|
||||||
g_signal_connect (chooser_entry->current_folder, "finished-loading",
|
|
||||||
G_CALLBACK (finished_loading_cb), chooser_entry);
|
|
||||||
|
|
||||||
out:
|
|
||||||
g_object_unref (chooser_entry);
|
|
||||||
g_object_unref (cancellable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static RefreshStatus
|
static RefreshStatus
|
||||||
@ -1373,8 +1315,7 @@ reload_current_folder (GtkFileChooserEntry *chooser_entry,
|
|||||||
g_assert (folder_file != NULL);
|
g_assert (folder_file != NULL);
|
||||||
|
|
||||||
if (chooser_entry->current_folder_file
|
if (chooser_entry->current_folder_file
|
||||||
&& g_file_equal (folder_file, chooser_entry->current_folder_file)
|
&& g_file_equal (folder_file, chooser_entry->current_folder_file))
|
||||||
&& chooser_entry->load_folder_cancellable)
|
|
||||||
return REFRESH_OK;
|
return REFRESH_OK;
|
||||||
|
|
||||||
if (chooser_entry->current_folder_file)
|
if (chooser_entry->current_folder_file)
|
||||||
@ -1387,13 +1328,9 @@ reload_current_folder (GtkFileChooserEntry *chooser_entry,
|
|||||||
return REFRESH_NOT_LOCAL;
|
return REFRESH_NOT_LOCAL;
|
||||||
|
|
||||||
chooser_entry->current_folder_file = g_object_ref (folder_file);
|
chooser_entry->current_folder_file = g_object_ref (folder_file);
|
||||||
|
chooser_entry->current_folder_loaded = FALSE;
|
||||||
|
|
||||||
chooser_entry->load_folder_cancellable =
|
populate_completion_store (chooser_entry);
|
||||||
_gtk_file_system_get_folder (chooser_entry->file_system,
|
|
||||||
chooser_entry->current_folder_file,
|
|
||||||
"standard::name,standard::display-name,standard::type",
|
|
||||||
load_directory_get_folder_callback,
|
|
||||||
g_object_ref (chooser_entry));
|
|
||||||
|
|
||||||
return REFRESH_OK;
|
return REFRESH_OK;
|
||||||
}
|
}
|
||||||
@ -1492,14 +1429,10 @@ refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry,
|
|||||||
|
|
||||||
g_assert (/* we are OK and we have a current folder file and (loading process or folder handle)... */
|
g_assert (/* we are OK and we have a current folder file and (loading process or folder handle)... */
|
||||||
((result == REFRESH_OK)
|
((result == REFRESH_OK)
|
||||||
&& (chooser_entry->current_folder_file != NULL)
|
&& (chooser_entry->current_folder_file != NULL))
|
||||||
&& (((chooser_entry->load_folder_cancellable != NULL) && (chooser_entry->current_folder == NULL))
|
|
||||||
|| ((chooser_entry->load_folder_cancellable == NULL) && (chooser_entry->current_folder != NULL))))
|
|
||||||
/* ... OR we have an error, and we don't have a current folder file nor a loading process nor a folder handle */
|
/* ... OR we have an error, and we don't have a current folder file nor a loading process nor a folder handle */
|
||||||
|| ((result != REFRESH_OK)
|
|| ((result != REFRESH_OK)
|
||||||
&& (chooser_entry->current_folder_file == NULL)
|
&& (chooser_entry->current_folder_file == NULL)));
|
||||||
&& (chooser_entry->load_folder_cancellable == NULL)
|
|
||||||
&& (chooser_entry->current_folder == NULL)));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1507,8 +1440,7 @@ refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry,
|
|||||||
static void
|
static void
|
||||||
autocomplete (GtkFileChooserEntry *chooser_entry)
|
autocomplete (GtkFileChooserEntry *chooser_entry)
|
||||||
{
|
{
|
||||||
if (!(chooser_entry->current_folder != NULL
|
if (!(chooser_entry->current_folder_loaded
|
||||||
&& chooser_entry->current_folder_loaded
|
|
||||||
&& gtk_editable_get_position (GTK_EDITABLE (chooser_entry)) == gtk_entry_get_text_length (GTK_ENTRY (chooser_entry))))
|
&& gtk_editable_get_position (GTK_EDITABLE (chooser_entry)) == gtk_entry_get_text_length (GTK_ENTRY (chooser_entry))))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1527,7 +1459,7 @@ start_autocompletion (GtkFileChooserEntry *chooser_entry)
|
|||||||
case REFRESH_OK:
|
case REFRESH_OK:
|
||||||
g_assert (chooser_entry->current_folder_file != NULL);
|
g_assert (chooser_entry->current_folder_file != NULL);
|
||||||
|
|
||||||
if (chooser_entry->current_folder && chooser_entry->current_folder_loaded)
|
if (chooser_entry->current_folder_loaded)
|
||||||
autocomplete (chooser_entry);
|
autocomplete (chooser_entry);
|
||||||
else
|
else
|
||||||
chooser_entry->load_complete_action = LOAD_COMPLETE_AUTOCOMPLETE;
|
chooser_entry->load_complete_action = LOAD_COMPLETE_AUTOCOMPLETE;
|
||||||
@ -1803,22 +1735,19 @@ gboolean
|
|||||||
_gtk_file_chooser_entry_get_is_folder (GtkFileChooserEntry *chooser_entry,
|
_gtk_file_chooser_entry_get_is_folder (GtkFileChooserEntry *chooser_entry,
|
||||||
GFile *file)
|
GFile *file)
|
||||||
{
|
{
|
||||||
gboolean retval = FALSE;
|
GtkTreeIter iter;
|
||||||
|
GFileInfo *info;
|
||||||
|
|
||||||
if (chooser_entry->current_folder)
|
if (chooser_entry->completion_store == NULL ||
|
||||||
{
|
!_gtk_file_system_model_get_iter_for_file (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store),
|
||||||
GFileInfo *file_info;
|
&iter,
|
||||||
|
file))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
file_info = _gtk_folder_get_info (chooser_entry->current_folder, file);
|
info = _gtk_file_system_model_get_info (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store),
|
||||||
|
&iter);
|
||||||
|
|
||||||
if (file_info)
|
return _gtk_file_info_consider_as_directory (info);
|
||||||
{
|
|
||||||
retval = _gtk_file_info_consider_as_directory (file_info);
|
|
||||||
g_object_unref (file_info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user