forked from AuroraMiddleware/gtk
Merge branch 'filesystemmodel-cleanups' into 'main'
filesystemmodel: Cleanup unused defines See merge request GNOME/gtk!5401
This commit is contained in:
commit
7d34e7e0f7
@ -38,7 +38,6 @@
|
||||
#define FILES_PER_QUERY 100
|
||||
|
||||
typedef struct _FileModelNode FileModelNode;
|
||||
typedef struct _GtkFileSystemModelClass GtkFileSystemModelClass;
|
||||
|
||||
struct _FileModelNode
|
||||
{
|
||||
@ -46,8 +45,8 @@ struct _FileModelNode
|
||||
GFileInfo * info; /* info for this file or NULL if unknown */
|
||||
|
||||
guint row; /* if valid (see model->n_valid_indexes), visible nodes before and including
|
||||
* this one - see the "Structure" comment above.
|
||||
*/
|
||||
* this one - see the "Structure" comment above.
|
||||
*/
|
||||
|
||||
guint visible :1; /* if the file is currently visible */
|
||||
guint filtered_out :1;/* if the file is currently filtered out (i.e. it didn't pass the filters) */
|
||||
@ -67,10 +66,10 @@ struct _GtkFileSystemModel
|
||||
GArray * files; /* array of FileModelNode containing all our files */
|
||||
guint n_nodes_valid; /* count of valid nodes (i.e. those whose node->row is accurate) */
|
||||
GHashTable * file_lookup; /* mapping of GFile => array index in model->files
|
||||
* This hash table doesn't always have the same number of entries as the files array;
|
||||
* The hash table gets re-populated in node_get_for_file() if this mismatch is
|
||||
* detected.
|
||||
*/
|
||||
* This hash table doesn't always have the same number of entries as the files array;
|
||||
* The hash table gets re-populated in node_get_for_file() if this mismatch is
|
||||
* detected.
|
||||
*/
|
||||
|
||||
GtkFileFilter * filter; /* filter to use for deciding which nodes are visible */
|
||||
|
||||
@ -84,46 +83,9 @@ struct _GtkFileSystemModel
|
||||
guint filter_folders :1;/* whether filter applies to folders */
|
||||
};
|
||||
|
||||
#define GTK_FILE_SYSTEM_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_SYSTEM_MODEL, GtkFileSystemModelClass))
|
||||
#define GTK_IS_FILE_SYSTEM_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_SYSTEM_MODEL))
|
||||
#define GTK_FILE_SYSTEM_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILE_SYSTEM_MODEL, GtkFileSystemModelClass))
|
||||
|
||||
struct _GtkFileSystemModelClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* Signals */
|
||||
|
||||
void (*finished_loading) (GtkFileSystemModel *model, GError *error);
|
||||
};
|
||||
|
||||
static void freeze_updates (GtkFileSystemModel *model);
|
||||
static void thaw_updates (GtkFileSystemModel *model);
|
||||
|
||||
static guint node_get_for_file (GtkFileSystemModel *model,
|
||||
GFile *file);
|
||||
|
||||
static void add_file (GtkFileSystemModel *model,
|
||||
GFile *file,
|
||||
GFileInfo *info);
|
||||
static void remove_file (GtkFileSystemModel *model,
|
||||
GFile *file);
|
||||
|
||||
/* iter setup:
|
||||
* @user_data: the model
|
||||
* @user_data2: GUINT_TO_POINTER of array index of current entry
|
||||
*
|
||||
* All other fields are unused. Note that the array index does not correspond
|
||||
* 1:1 with the path index as entries might not be visible.
|
||||
*/
|
||||
#define ITER_INDEX(iter) GPOINTER_TO_UINT((iter)->user_data2)
|
||||
#define ITER_IS_VALID(model, iter) ((model) == (iter)->user_data)
|
||||
#define ITER_INIT_FROM_INDEX(model, _iter, _index) G_STMT_START {\
|
||||
g_assert (_index < (model)->files->len); \
|
||||
(_iter)->user_data = (model); \
|
||||
(_iter)->user_data2 = GUINT_TO_POINTER (_index); \
|
||||
}G_STMT_END
|
||||
|
||||
/*** FileModelNode ***/
|
||||
|
||||
/* Get a FileModelNode structure given an index in the model->files array of nodes */
|
||||
@ -140,7 +102,9 @@ static void remove_file (GtkFileSystemModel *model,
|
||||
* G_MAXUINT for both arguments for “validate everything”.
|
||||
*/
|
||||
static void
|
||||
node_validate_rows (GtkFileSystemModel *model, guint up_to_index, guint up_to_row)
|
||||
node_validate_rows (GtkFileSystemModel *model,
|
||||
guint up_to_index,
|
||||
guint up_to_row)
|
||||
{
|
||||
guint i, row;
|
||||
|
||||
@ -167,7 +131,8 @@ node_validate_rows (GtkFileSystemModel *model, guint up_to_index, guint up_to_ro
|
||||
}
|
||||
|
||||
static guint G_GNUC_UNUSED
|
||||
node_get_tree_row (GtkFileSystemModel *model, guint index)
|
||||
node_get_tree_row (GtkFileSystemModel *model,
|
||||
guint index)
|
||||
{
|
||||
if (model->n_nodes_valid <= index)
|
||||
node_validate_rows (model, index, G_MAXUINT);
|
||||
@ -175,14 +140,18 @@ node_get_tree_row (GtkFileSystemModel *model, guint index)
|
||||
return get_node (model, index)->row - 1;
|
||||
}
|
||||
|
||||
static void
|
||||
node_invalidate_index (GtkFileSystemModel *model, guint id)
|
||||
static void
|
||||
node_invalidate_index (GtkFileSystemModel *model,
|
||||
guint id)
|
||||
{
|
||||
model->n_nodes_valid = MIN (model->n_nodes_valid, id);
|
||||
}
|
||||
|
||||
static void
|
||||
node_set_visible_and_filtered_out (GtkFileSystemModel *model, guint id, gboolean visible, gboolean filtered_out)
|
||||
node_set_visible_and_filtered_out (GtkFileSystemModel *model,
|
||||
guint id,
|
||||
gboolean visible,
|
||||
gboolean filtered_out)
|
||||
{
|
||||
FileModelNode *node = get_node (model, id);
|
||||
|
||||
@ -218,7 +187,8 @@ node_set_visible_and_filtered_out (GtkFileSystemModel *model, guint id, gboolean
|
||||
}
|
||||
|
||||
static gboolean
|
||||
node_should_be_filtered_out (GtkFileSystemModel *model, guint id)
|
||||
node_should_be_filtered_out (GtkFileSystemModel *model,
|
||||
guint id)
|
||||
{
|
||||
FileModelNode *node = get_node (model, id);
|
||||
|
||||
@ -234,7 +204,9 @@ node_should_be_filtered_out (GtkFileSystemModel *model, guint id)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
node_should_be_visible (GtkFileSystemModel *model, guint id, gboolean filtered_out)
|
||||
node_should_be_visible (GtkFileSystemModel *model,
|
||||
guint id,
|
||||
gboolean filtered_out)
|
||||
{
|
||||
FileModelNode *node = get_node (model, id);
|
||||
gboolean result;
|
||||
@ -266,7 +238,8 @@ node_should_be_visible (GtkFileSystemModel *model, guint id, gboolean filtered_o
|
||||
}
|
||||
|
||||
static void
|
||||
node_compute_visibility_and_filters (GtkFileSystemModel *model, guint id)
|
||||
node_compute_visibility_and_filters (GtkFileSystemModel *model,
|
||||
guint id)
|
||||
{
|
||||
gboolean filtered_out;
|
||||
gboolean visible;
|
||||
@ -277,6 +250,36 @@ node_compute_visibility_and_filters (GtkFileSystemModel *model, guint id)
|
||||
node_set_visible_and_filtered_out (model, id, visible, filtered_out);
|
||||
}
|
||||
|
||||
static guint
|
||||
node_get_for_file (GtkFileSystemModel *model,
|
||||
GFile *file)
|
||||
{
|
||||
guint i;
|
||||
|
||||
i = GPOINTER_TO_UINT (g_hash_table_lookup (model->file_lookup, file));
|
||||
if (i != 0)
|
||||
return i;
|
||||
|
||||
/* Node 0 is the editable row and has no associated file or entry in the table, so we start counting from 1.
|
||||
*
|
||||
* The invariant here is that the files in model->files[n] for n < g_hash_table_size (model->file_lookup)
|
||||
* are already added to the hash table. this loop merely rebuilds our (file -> index) mapping on demand.
|
||||
*
|
||||
* If we exit the loop, the next pending batch of mappings will be resolved when this function gets called again
|
||||
* with another file that is not yet in the mapping.
|
||||
*/
|
||||
for (i = g_hash_table_size (model->file_lookup) + 1; i < model->files->len; i++)
|
||||
{
|
||||
FileModelNode *node = get_node (model, i);
|
||||
|
||||
g_hash_table_insert (model->file_lookup, node->file, GUINT_TO_POINTER (i));
|
||||
if (g_file_equal (node->file, file))
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*** GListModel ***/
|
||||
|
||||
static GType
|
||||
@ -327,28 +330,166 @@ enum {
|
||||
|
||||
static guint file_system_model_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkFileSystemModel, gtk_file_system_model, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL,
|
||||
g_list_model_iface_init))
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkFileSystemModel, _gtk_file_system_model, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL,
|
||||
g_list_model_iface_init))
|
||||
static void
|
||||
freeze_updates (GtkFileSystemModel *model)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model));
|
||||
|
||||
model->frozen++;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_system_model_refilter_all (GtkFileSystemModel *model)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (model->frozen)
|
||||
{
|
||||
model->filter_on_thaw = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
freeze_updates (model);
|
||||
|
||||
/* start at index 1, don't change the editable */
|
||||
for (i = 1; i < model->files->len; i++)
|
||||
node_compute_visibility_and_filters (model, i);
|
||||
|
||||
model->filter_on_thaw = FALSE;
|
||||
thaw_updates (model);
|
||||
}
|
||||
|
||||
static void
|
||||
thaw_updates (GtkFileSystemModel *model)
|
||||
{
|
||||
gboolean stuff_added;
|
||||
|
||||
g_return_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model));
|
||||
g_return_if_fail (model->frozen > 0);
|
||||
|
||||
model->frozen--;
|
||||
if (model->frozen > 0)
|
||||
return;
|
||||
|
||||
stuff_added = get_node (model, model->files->len - 1)->frozen_add;
|
||||
|
||||
if (model->filter_on_thaw)
|
||||
gtk_file_system_model_refilter_all (model);
|
||||
if (stuff_added)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < model->files->len; i++)
|
||||
{
|
||||
FileModelNode *node = get_node (model, i);
|
||||
|
||||
if (!node->frozen_add)
|
||||
continue;
|
||||
node->frozen_add = FALSE;
|
||||
node_compute_visibility_and_filters (model, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_file (GtkFileSystemModel *model,
|
||||
GFile *file,
|
||||
GFileInfo *info)
|
||||
{
|
||||
FileModelNode *node;
|
||||
guint position;
|
||||
|
||||
g_return_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model));
|
||||
g_return_if_fail (G_IS_FILE (file));
|
||||
g_return_if_fail (G_IS_FILE_INFO (info));
|
||||
|
||||
node = g_slice_alloc0 (sizeof (FileModelNode));
|
||||
node->file = g_object_ref (file);
|
||||
if (info)
|
||||
{
|
||||
g_file_info_set_attribute_object (info, "standard::file", G_OBJECT (file));
|
||||
node->info = g_object_ref (info);
|
||||
}
|
||||
node->frozen_add = model->frozen ? TRUE : FALSE;
|
||||
|
||||
g_array_append_vals (model->files, node, 1);
|
||||
g_slice_free1 (sizeof (FileModelNode), node);
|
||||
|
||||
position = model->files->len - 1;
|
||||
|
||||
if (!model->frozen)
|
||||
node_compute_visibility_and_filters (model, model->files->len -1);
|
||||
|
||||
/* Ignore the first item */
|
||||
g_list_model_items_changed (G_LIST_MODEL (model), position - 1, 0, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
adjust_file_lookup (GtkFileSystemModel *model, guint id, int increment)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
gpointer key;
|
||||
gpointer value;
|
||||
|
||||
g_hash_table_iter_init (&iter, model->file_lookup);
|
||||
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
{
|
||||
guint index = GPOINTER_TO_UINT (value);
|
||||
|
||||
if (index >= id)
|
||||
{
|
||||
index += increment;
|
||||
g_hash_table_iter_replace (&iter, GUINT_TO_POINTER (index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
remove_file (GtkFileSystemModel *model,
|
||||
GFile *file)
|
||||
{
|
||||
FileModelNode *node;
|
||||
guint id;
|
||||
|
||||
g_return_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model));
|
||||
g_return_if_fail (G_IS_FILE (file));
|
||||
|
||||
id = node_get_for_file (model, file);
|
||||
if (id == 0)
|
||||
return;
|
||||
|
||||
node = get_node (model, id);
|
||||
|
||||
node_invalidate_index (model, id);
|
||||
|
||||
g_hash_table_remove (model->file_lookup, file);
|
||||
g_clear_object (&node->file);
|
||||
adjust_file_lookup (model, id, -1);
|
||||
|
||||
g_clear_object (&node->info);
|
||||
|
||||
g_array_remove_index (model->files, id);
|
||||
|
||||
g_list_model_items_changed (G_LIST_MODEL (model), id - 1, 1, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_system_model_dispose (GObject *object)
|
||||
{
|
||||
GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (object);
|
||||
|
||||
if (model->dir_thaw_source)
|
||||
{
|
||||
g_source_remove (model->dir_thaw_source);
|
||||
model->dir_thaw_source = 0;
|
||||
}
|
||||
g_clear_handle_id (&model->dir_thaw_source, g_source_remove);
|
||||
|
||||
g_cancellable_cancel (model->cancellable);
|
||||
if (model->dir_monitor)
|
||||
g_file_monitor_cancel (model->dir_monitor);
|
||||
|
||||
G_OBJECT_CLASS (_gtk_file_system_model_parent_class)->dispose (object);
|
||||
G_OBJECT_CLASS (gtk_file_system_model_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
||||
@ -373,11 +514,11 @@ gtk_file_system_model_finalize (GObject *object)
|
||||
g_clear_pointer (&model->file_lookup, g_hash_table_destroy);
|
||||
g_clear_object (&model->filter);
|
||||
|
||||
G_OBJECT_CLASS (_gtk_file_system_model_parent_class)->finalize (object);
|
||||
G_OBJECT_CLASS (gtk_file_system_model_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_file_system_model_class_init (GtkFileSystemModelClass *class)
|
||||
gtk_file_system_model_class_init (GtkFileSystemModelClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
||||
|
||||
@ -386,16 +527,15 @@ _gtk_file_system_model_class_init (GtkFileSystemModelClass *class)
|
||||
|
||||
file_system_model_signals[FINISHED_LOADING] =
|
||||
g_signal_new (I_("finished-loading"),
|
||||
G_OBJECT_CLASS_TYPE (gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GtkFileSystemModelClass, finished_loading),
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE, 1, G_TYPE_ERROR);
|
||||
G_OBJECT_CLASS_TYPE (gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, NULL, NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE, 1, G_TYPE_ERROR);
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_file_system_model_init (GtkFileSystemModel *model)
|
||||
gtk_file_system_model_init (GtkFileSystemModel *model)
|
||||
{
|
||||
model->show_files = TRUE;
|
||||
model->show_folders = TRUE;
|
||||
@ -409,7 +549,9 @@ _gtk_file_system_model_init (GtkFileSystemModel *model)
|
||||
/*** API ***/
|
||||
|
||||
static void
|
||||
gtk_file_system_model_closed_enumerator (GObject *object, GAsyncResult *res, gpointer data)
|
||||
gtk_file_system_model_closed_enumerator (GObject *object,
|
||||
GAsyncResult *res,
|
||||
gpointer data)
|
||||
{
|
||||
g_file_enumerator_close_finish (G_FILE_ENUMERATOR (object), res, NULL);
|
||||
}
|
||||
@ -426,7 +568,9 @@ thaw_func (gpointer data)
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_system_model_got_files (GObject *object, GAsyncResult *res, gpointer data)
|
||||
gtk_file_system_model_got_files (GObject *object,
|
||||
GAsyncResult *res,
|
||||
gpointer data)
|
||||
{
|
||||
GFileEnumerator *enumerator = G_FILE_ENUMERATOR (object);
|
||||
GtkFileSystemModel *model = data;
|
||||
@ -452,7 +596,7 @@ gtk_file_system_model_got_files (GObject *object, GAsyncResult *res, gpointer da
|
||||
const char *name;
|
||||
GFileInfo *info;
|
||||
GFile *file;
|
||||
|
||||
|
||||
info = walk->data;
|
||||
name = g_file_info_get_name (info);
|
||||
if (name == NULL)
|
||||
@ -469,11 +613,11 @@ gtk_file_system_model_got_files (GObject *object, GAsyncResult *res, gpointer da
|
||||
g_list_free (files);
|
||||
|
||||
g_file_enumerator_next_files_async (enumerator,
|
||||
g_file_is_native (model->dir) ? 50 * FILES_PER_QUERY : FILES_PER_QUERY,
|
||||
IO_PRIORITY,
|
||||
model->cancellable,
|
||||
gtk_file_system_model_got_files,
|
||||
model);
|
||||
g_file_is_native (model->dir) ? 50 * FILES_PER_QUERY : FILES_PER_QUERY,
|
||||
IO_PRIORITY,
|
||||
model->cancellable,
|
||||
gtk_file_system_model_got_files,
|
||||
model);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -486,8 +630,7 @@ gtk_file_system_model_got_files (GObject *object, GAsyncResult *res, gpointer da
|
||||
NULL);
|
||||
if (model->dir_thaw_source != 0)
|
||||
{
|
||||
g_source_remove (model->dir_thaw_source);
|
||||
model->dir_thaw_source = 0;
|
||||
g_clear_handle_id (&model->dir_thaw_source, g_source_remove);
|
||||
thaw_updates (model);
|
||||
}
|
||||
|
||||
@ -499,10 +642,36 @@ gtk_file_system_model_got_files (GObject *object, GAsyncResult *res, gpointer da
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_system_model_update_file (GtkFileSystemModel *model,
|
||||
GFile *file,
|
||||
GFileInfo *info)
|
||||
{
|
||||
FileModelNode *node;
|
||||
guint id;
|
||||
|
||||
g_return_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model));
|
||||
g_return_if_fail (G_IS_FILE (file));
|
||||
g_return_if_fail (G_IS_FILE_INFO (info));
|
||||
|
||||
id = node_get_for_file (model, file);
|
||||
if (id == 0)
|
||||
{
|
||||
add_file (model, file, info);
|
||||
id = node_get_for_file (model, file);
|
||||
}
|
||||
|
||||
node = get_node (model, id);
|
||||
|
||||
g_set_object (&node->info, info);
|
||||
|
||||
g_file_info_set_attribute_object (info, "standard::file", G_OBJECT (file));
|
||||
}
|
||||
|
||||
/* Helper for gtk_file_system_model_query_done and
|
||||
* gtk_file_system_model_one_query_done */
|
||||
static void
|
||||
query_done_helper (GObject * object,
|
||||
query_done_helper (GObject *object,
|
||||
GAsyncResult *res,
|
||||
gpointer data,
|
||||
gboolean do_thaw_updates)
|
||||
@ -514,7 +683,7 @@ query_done_helper (GObject * object,
|
||||
info = g_file_query_info_finish (file, res, NULL);
|
||||
if (info)
|
||||
{
|
||||
_gtk_file_system_model_update_file (model, file, info);
|
||||
gtk_file_system_model_update_file (model, file, info);
|
||||
g_object_unref (info);
|
||||
}
|
||||
|
||||
@ -608,7 +777,7 @@ gtk_file_system_model_got_enumerator (GObject *dir, GAsyncResult *res, gpointer
|
||||
static void
|
||||
gtk_file_system_model_set_directory (GtkFileSystemModel *model,
|
||||
GFile * dir,
|
||||
const char * attributes)
|
||||
const char * attributes)
|
||||
{
|
||||
g_assert (G_IS_FILE (dir));
|
||||
|
||||
@ -678,27 +847,6 @@ _gtk_file_system_model_new_for_directory (GFile *dir,
|
||||
return model;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_file_system_model_refilter_all (GtkFileSystemModel *model)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (model->frozen)
|
||||
{
|
||||
model->filter_on_thaw = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
freeze_updates (model);
|
||||
|
||||
/* start at index 1, don't change the editable */
|
||||
for (i = 1; i < model->files->len; i++)
|
||||
node_compute_visibility_and_filters (model, i);
|
||||
|
||||
model->filter_on_thaw = FALSE;
|
||||
thaw_updates (model);
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_file_system_model_set_show_hidden:
|
||||
* @model: a `GtkFileSystemModel`
|
||||
@ -709,7 +857,7 @@ gtk_file_system_model_refilter_all (GtkFileSystemModel *model)
|
||||
**/
|
||||
void
|
||||
_gtk_file_system_model_set_show_hidden (GtkFileSystemModel *model,
|
||||
gboolean show_hidden)
|
||||
gboolean show_hidden)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model));
|
||||
|
||||
@ -732,7 +880,7 @@ _gtk_file_system_model_set_show_hidden (GtkFileSystemModel *model,
|
||||
*/
|
||||
void
|
||||
_gtk_file_system_model_set_show_folders (GtkFileSystemModel *model,
|
||||
gboolean show_folders)
|
||||
gboolean show_folders)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model));
|
||||
|
||||
@ -755,7 +903,7 @@ _gtk_file_system_model_set_show_folders (GtkFileSystemModel *model,
|
||||
*/
|
||||
void
|
||||
_gtk_file_system_model_set_show_files (GtkFileSystemModel *model,
|
||||
gboolean show_files)
|
||||
gboolean show_files)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model));
|
||||
|
||||
@ -779,7 +927,7 @@ _gtk_file_system_model_set_show_files (GtkFileSystemModel *model,
|
||||
*/
|
||||
void
|
||||
_gtk_file_system_model_set_filter_folders (GtkFileSystemModel *model,
|
||||
gboolean filter_folders)
|
||||
gboolean filter_folders)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model));
|
||||
|
||||
@ -811,36 +959,6 @@ _gtk_file_system_model_get_cancellable (GtkFileSystemModel *model)
|
||||
return model->cancellable;
|
||||
}
|
||||
|
||||
static guint
|
||||
node_get_for_file (GtkFileSystemModel *model,
|
||||
GFile * file)
|
||||
{
|
||||
guint i;
|
||||
|
||||
i = GPOINTER_TO_UINT (g_hash_table_lookup (model->file_lookup, file));
|
||||
if (i != 0)
|
||||
return i;
|
||||
|
||||
/* Node 0 is the editable row and has no associated file or entry in the table, so we start counting from 1.
|
||||
*
|
||||
* The invariant here is that the files in model->files[n] for n < g_hash_table_size (model->file_lookup)
|
||||
* are already added to the hash table. this loop merely rebuilds our (file -> index) mapping on demand.
|
||||
*
|
||||
* If we exit the loop, the next pending batch of mappings will be resolved when this function gets called again
|
||||
* with another file that is not yet in the mapping.
|
||||
*/
|
||||
for (i = g_hash_table_size (model->file_lookup) + 1; i < model->files->len; i++)
|
||||
{
|
||||
FileModelNode *node = get_node (model, i);
|
||||
|
||||
g_hash_table_insert (model->file_lookup, node->file, GUINT_TO_POINTER (i));
|
||||
if (g_file_equal (node->file, file))
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
GFileInfo *
|
||||
_gtk_file_system_model_get_info_for_file (GtkFileSystemModel *model,
|
||||
GFile *file)
|
||||
@ -860,150 +978,16 @@ _gtk_file_system_model_get_info_for_file (GtkFileSystemModel *model,
|
||||
return node->info;
|
||||
}
|
||||
|
||||
/* When an element is added or removed to the model->files array, we need to
|
||||
* update the model->file_lookup mappings of (node, index), as the indexes
|
||||
* change. This function adds the specified increment to the index in that pair
|
||||
* if the index is equal or after the specified id. We use this to slide the
|
||||
* mappings up or down when a node is added or removed, respectively.
|
||||
*/
|
||||
static void
|
||||
adjust_file_lookup (GtkFileSystemModel *model, guint id, int increment)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
gpointer key;
|
||||
gpointer value;
|
||||
|
||||
g_hash_table_iter_init (&iter, model->file_lookup);
|
||||
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
{
|
||||
guint index = GPOINTER_TO_UINT (value);
|
||||
|
||||
if (index >= id)
|
||||
{
|
||||
index += increment;
|
||||
g_hash_table_iter_replace (&iter, GUINT_TO_POINTER (index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* add_file:
|
||||
* _gtk_file_system_model_update_files:
|
||||
* @model: the model
|
||||
* @file: the file to add
|
||||
* @info: the information to associate with the file
|
||||
* @files: the files
|
||||
* @infos: the new file infos
|
||||
*
|
||||
* Adds the given @file with its associated @info to the @model.
|
||||
* If the model is frozen, the file will only show up after it is thawn.
|
||||
* Tells the file system model that the files changed and that the
|
||||
* new @infos should be used for it now. If these files are not
|
||||
* part of @model, it will get added automatically.
|
||||
**/
|
||||
static void
|
||||
add_file (GtkFileSystemModel *model,
|
||||
GFile *file,
|
||||
GFileInfo *info)
|
||||
{
|
||||
FileModelNode *node;
|
||||
guint position;
|
||||
|
||||
g_return_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model));
|
||||
g_return_if_fail (G_IS_FILE (file));
|
||||
g_return_if_fail (G_IS_FILE_INFO (info));
|
||||
|
||||
node = g_slice_alloc0 (sizeof (FileModelNode));
|
||||
node->file = g_object_ref (file);
|
||||
if (info)
|
||||
{
|
||||
g_file_info_set_attribute_object (info, "standard::file", G_OBJECT (file));
|
||||
node->info = g_object_ref (info);
|
||||
}
|
||||
node->frozen_add = model->frozen ? TRUE : FALSE;
|
||||
|
||||
g_array_append_vals (model->files, node, 1);
|
||||
g_slice_free1 (sizeof (FileModelNode), node);
|
||||
|
||||
position = model->files->len - 1;
|
||||
|
||||
if (!model->frozen)
|
||||
node_compute_visibility_and_filters (model, model->files->len -1);
|
||||
|
||||
/* Ignore the first item */
|
||||
g_list_model_items_changed (G_LIST_MODEL (model), position - 1, 0, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* remove_file:
|
||||
* @model: the model
|
||||
* @file: file to remove from the model. The file must have been
|
||||
* added to the model previously
|
||||
*
|
||||
* Removes the given file from the model. If the file is not part of
|
||||
* @model, this function does nothing.
|
||||
**/
|
||||
static void
|
||||
remove_file (GtkFileSystemModel *model,
|
||||
GFile *file)
|
||||
{
|
||||
FileModelNode *node;
|
||||
guint id;
|
||||
|
||||
g_return_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model));
|
||||
g_return_if_fail (G_IS_FILE (file));
|
||||
|
||||
id = node_get_for_file (model, file);
|
||||
if (id == 0)
|
||||
return;
|
||||
|
||||
node = get_node (model, id);
|
||||
|
||||
node_invalidate_index (model, id);
|
||||
|
||||
g_hash_table_remove (model->file_lookup, file);
|
||||
g_object_unref (node->file);
|
||||
adjust_file_lookup (model, id, -1);
|
||||
|
||||
if (node->info)
|
||||
g_object_unref (node->info);
|
||||
|
||||
g_array_remove_index (model->files, id);
|
||||
|
||||
g_list_model_items_changed (G_LIST_MODEL (model), id - 1, 1, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_file_system_model_update_file:
|
||||
* @model: the model
|
||||
* @file: the file
|
||||
* @info: the new file info
|
||||
*
|
||||
* Tells the file system model that the file changed and that the
|
||||
* new @info should be used for it now. If the file is not part of
|
||||
* @model, it will get added automatically.
|
||||
**/
|
||||
void
|
||||
_gtk_file_system_model_update_file (GtkFileSystemModel *model,
|
||||
GFile *file,
|
||||
GFileInfo *info)
|
||||
{
|
||||
FileModelNode *node;
|
||||
guint id;
|
||||
|
||||
g_return_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model));
|
||||
g_return_if_fail (G_IS_FILE (file));
|
||||
g_return_if_fail (G_IS_FILE_INFO (info));
|
||||
|
||||
id = node_get_for_file (model, file);
|
||||
if (id == 0)
|
||||
{
|
||||
add_file (model, file, info);
|
||||
id = node_get_for_file (model, file);
|
||||
}
|
||||
|
||||
node = get_node (model, id);
|
||||
|
||||
g_set_object (&node->info, info);
|
||||
|
||||
g_file_info_set_attribute_object (info, "standard::file", G_OBJECT (file));
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_file_system_model_update_files (GtkFileSystemModel *model,
|
||||
GList *files,
|
||||
@ -1016,7 +1000,7 @@ _gtk_file_system_model_update_files (GtkFileSystemModel *model,
|
||||
freeze_updates (model);
|
||||
|
||||
for (l = files, i = infos; l; l = l->next, i = i->next)
|
||||
_gtk_file_system_model_update_file (model, (GFile *)l->data, (GFileInfo *)i->data);
|
||||
gtk_file_system_model_update_file (model, (GFile *)l->data, (GFileInfo *)i->data);
|
||||
|
||||
thaw_updates (model);
|
||||
}
|
||||
@ -1032,80 +1016,16 @@ _gtk_file_system_model_update_files (GtkFileSystemModel *model,
|
||||
**/
|
||||
void
|
||||
_gtk_file_system_model_set_filter (GtkFileSystemModel *model,
|
||||
GtkFileFilter * filter)
|
||||
GtkFileFilter * filter)
|
||||
{
|
||||
GtkFileFilter *old_filter;
|
||||
|
||||
g_return_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model));
|
||||
g_return_if_fail (filter == NULL || GTK_IS_FILE_FILTER (filter));
|
||||
|
||||
if (filter)
|
||||
g_object_ref (filter);
|
||||
|
||||
old_filter = model->filter;
|
||||
model->filter = filter;
|
||||
|
||||
if (old_filter)
|
||||
g_object_unref (old_filter);
|
||||
g_set_object (&model->filter, filter);
|
||||
|
||||
gtk_file_system_model_refilter_all (model);
|
||||
}
|
||||
|
||||
/**
|
||||
* freeze_updates:
|
||||
* @model: a `GtkFileSystemModel`
|
||||
*
|
||||
* Freezes most updates on the model, so that performing multiple operations on
|
||||
* the files in the model do not cause any events. Use thaw_updates() to resume
|
||||
* proper operations. It is fine to call this function multiple times as long as
|
||||
* freeze and thaw calls are balanced.
|
||||
**/
|
||||
static void
|
||||
freeze_updates (GtkFileSystemModel *model)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model));
|
||||
|
||||
model->frozen++;
|
||||
}
|
||||
|
||||
/**
|
||||
* thaw_updates:
|
||||
* @model: a `GtkFileSystemModel`
|
||||
*
|
||||
* Undoes the effect of a previous call to freeze_updates()
|
||||
**/
|
||||
static void
|
||||
thaw_updates (GtkFileSystemModel *model)
|
||||
{
|
||||
gboolean stuff_added;
|
||||
|
||||
g_return_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model));
|
||||
g_return_if_fail (model->frozen > 0);
|
||||
|
||||
model->frozen--;
|
||||
if (model->frozen > 0)
|
||||
return;
|
||||
|
||||
stuff_added = get_node (model, model->files->len - 1)->frozen_add;
|
||||
|
||||
if (model->filter_on_thaw)
|
||||
gtk_file_system_model_refilter_all (model);
|
||||
if (stuff_added)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < model->files->len; i++)
|
||||
{
|
||||
FileModelNode *node = get_node (model, i);
|
||||
|
||||
if (!node->frozen_add)
|
||||
continue;
|
||||
node->frozen_add = FALSE;
|
||||
node_compute_visibility_and_filters (model, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_file_system_model_add_and_query_file:
|
||||
* @model: a `GtkFileSystemModel`
|
||||
|
@ -24,13 +24,8 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_FILE_SYSTEM_MODEL (_gtk_file_system_model_get_type ())
|
||||
#define GTK_FILE_SYSTEM_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_SYSTEM_MODEL, GtkFileSystemModel))
|
||||
#define GTK_IS_FILE_SYSTEM_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FILE_SYSTEM_MODEL))
|
||||
|
||||
typedef struct _GtkFileSystemModel GtkFileSystemModel;
|
||||
|
||||
GType _gtk_file_system_model_get_type (void) G_GNUC_CONST;
|
||||
#define GTK_TYPE_FILE_SYSTEM_MODEL (gtk_file_system_model_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (GtkFileSystemModel, gtk_file_system_model, GTK, FILE_SYSTEM_MODEL, GObject)
|
||||
|
||||
GtkFileSystemModel *_gtk_file_system_model_new (void);
|
||||
GtkFileSystemModel *_gtk_file_system_model_new_for_directory(GFile *dir,
|
||||
@ -46,9 +41,6 @@ void _gtk_file_system_model_add_and_query_file (GtkFileSystemMod
|
||||
void _gtk_file_system_model_add_and_query_files (GtkFileSystemModel *model,
|
||||
GList *files,
|
||||
const char *attributes);
|
||||
void _gtk_file_system_model_update_file (GtkFileSystemModel *model,
|
||||
GFile *file,
|
||||
GFileInfo *info);
|
||||
void _gtk_file_system_model_update_files (GtkFileSystemModel *model,
|
||||
GList *files,
|
||||
GList *infos);
|
||||
|
Loading…
Reference in New Issue
Block a user