@@ -38,7 +38,6 @@
# define FILES_PER_QUERY 100
typedef struct _FileModelNode FileModelNode ;
typedef struct _GtkFileSystemModelClass GtkFileSystemModelClass ;
struct _FileModelNode
{
@@ -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 ) ;
@@ -176,13 +141,17 @@ node_get_tree_row (GtkFileSystemModel *model, guint index)
}
static void
node_invalidate_index ( GtkFileSystemModel * model , guint id )
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,20 @@ 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 )
{
gpointer position ;
if ( ! g_hash_table_lookup_extended ( model - > file_lookup ,
file , NULL ,
& position ) )
return GTK_INVALID_LIST_POSITION ;
return GPOINTER_TO_UINT ( position ) ;
}
/*** GListModel ***/
static GType
@@ -290,7 +277,7 @@ list_model_get_n_items (GListModel *list_model)
{
GtkFileSystemModel * model = GTK_FILE_SYSTEM_MODEL ( list_model ) ;
return model - > files - > len - 1 ;
return model - > files - > len ;
}
static gpointer
@@ -300,12 +287,10 @@ list_model_get_item (GListModel *list_model,
GtkFileSystemModel * model = GTK_FILE_SYSTEM_MODEL ( list_model ) ;
FileModelNode * node ;
/* The first items of GtkFileSystemModel is not really a file,
* so ignore it. */
if ( position + 1 > = model - > files - > len )
if ( position > = model - > files - > len )
return NULL ;
node = get_node ( model , position + 1 ) ;
node = get_node ( model , position ) ;
return g_object_ref ( node - > info ) ;
}
@@ -327,89 +312,164 @@ enum {
static guint file_system_model_signals [ LAST_SIGNAL ] = { 0 } ;
G_DEFINE_TYPE_WITH_CODE ( GtkFileSystemModel , _gtk_file_system_model , G_TYPE_OBJECT ,
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
gtk_file_system_model_dispose ( GObject * object )
gtk_file_system_model_refilter_all ( GtkFileSystemModel * model )
{
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_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 ) ;
}
static void
gtk_file_system_model_finalize ( GObject * object )
{
GtkFileSystemModel * model = GTK_FILE_SYSTEM_MODEL ( object ) ;
guint i ;
for ( i = 0 ; i < model - > files - > len ; i + + )
i f ( model - > frozen )
{
FileModelNode * node = get_node ( model , i ) ;
g_clear_object ( & node - > file ) ;
g_clear_object ( & node - > info ) ;
model - > filter_on_thaw = TRUE ;
return ;
}
g_array_free ( model - > files , TRUE ) ;
g_clear_object ( & model - > cancellable ) ;
g_clear_pointer ( & model - > attributes , g_free ) ;
g_clear_object ( & model - > dir ) ;
g_clear_object ( & model - > dir_monitor ) ;
g_clear_pointer ( & model - > file_lookup , g_hash_table_destroy ) ;
g_clear_object ( & model - > filter ) ;
freeze_updates ( model ) ;
G_OBJECT_CLASS ( _gtk_file_system_model_parent_class ) - > finalize ( object ) ;
for ( i = 0 ; i < model - > files - > len ; i + + )
node_compute_visibility_and_filters ( model , i ) ;
model - > filter_on_thaw = FALSE ;
thaw_updates ( model ) ;
}
static void
_gtk_file_system_model_class_init ( GtkFileSystemModelClass * class )
freeze_updates ( GtkFileSystemModel * model )
{
GObjectClass * gobject_class = G_OBJECT_CLASS ( class ) ;
g_return_if_fail ( GTK_IS_FILE_SYSTEM_MODEL ( model ) ) ;
gobject_class - > finalize = gtk_file_system_model_finalize ;
gobject_class - > dispose = gtk_file_system_model_dispose ;
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 ) ;
model - > frozen + + ;
}
static void
_gtk_file_system_model_init ( GtkFileSystemModel * model )
thaw_updates ( GtkFileSystemModel * model )
{
model - > show_files = TRU E;
model - > show_folders = TRUE ;
model - > show_hidden = FALSE ;
model - > filter_folders = FALSE ;
gboolean stuff_added = FALS E;
model - > file_lookup = g_hash_table_new ( g_file_hash , ( GEqualFunc ) g_file_equal ) ;
model - > cancellable = g_cancellable_new ( ) ;
g_return_if_fail ( GTK_IS_FILE_SYSTEM_MODEL ( model ) ) ;
g_return_if_fail ( model - > frozen > 0 ) ;
model - > frozen - - ;
if ( model - > frozen > 0 )
return ;
if ( model - > files - > len > 0 )
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 ) ;
}
}
}
/*** API ***/
/* 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 ) ) ;
}
}
}
static void
gtk _file_system_model_closed_enumerator ( GObject * object , GAsyncResult * res , gpointer data )
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 , position ) ;
g_list_model_items_changed ( G_LIST_MODEL ( model ) , position , 0 , 1 ) ;
}
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 = = GTK_INVALID_LIST_POSITION )
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 , 0 ) ;
}
static void
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 +486,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 ;
@@ -486,8 +548,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 +560,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 = = GTK_INVALID_LIST_POSITION )
{
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 )
@@ -523,7 +610,7 @@ query_done_helper (GObject * object,
}
static void
gtk_file_system_model_query_done ( GObject * object ,
gtk_file_system_model_query_done ( GObject * object ,
GAsyncResult * res ,
gpointer data )
{
@@ -531,9 +618,9 @@ gtk_file_system_model_query_done (GObject * object,
}
static void
gtk_file_system_model_monitor_change ( GFileMonitor * monitor ,
GFile * file ,
GFile * other_file ,
gtk_file_system_model_monitor_change ( GFileMonitor * monitor ,
GFile * file ,
GFile * other_file ,
GFileMonitorEvent type ,
GtkFileSystemModel * model )
{
@@ -569,7 +656,9 @@ gtk_file_system_model_monitor_change (GFileMonitor * monitor,
}
static void
gtk_file_system_model_got_enumerator ( GObject * dir , GAsyncResult * res , gpointer data )
gtk_file_system_model_got_enumerator ( GObject * dir ,
GAsyncResult * res ,
gpointer data )
{
GtkFileSystemModel * model = data ;
GFileEnumerator * enumerator ;
@@ -607,8 +696,8 @@ 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 )
GFile * dir ,
const char * attributes )
{
g_assert ( G_IS_FILE ( dir ) ) ;
@@ -625,6 +714,85 @@ gtk_file_system_model_set_directory (GtkFileSystemModel *model,
}
static void
gtk_file_system_model_one_query_done ( GObject * object ,
GAsyncResult * res ,
gpointer data )
{
query_done_helper ( object , res , data , TRUE ) ;
}
/* GObject overrides */
static void
gtk_file_system_model_dispose ( GObject * object )
{
GtkFileSystemModel * model = GTK_FILE_SYSTEM_MODEL ( object ) ;
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 ) ;
}
static void
gtk_file_system_model_finalize ( GObject * object )
{
GtkFileSystemModel * model = GTK_FILE_SYSTEM_MODEL ( object ) ;
guint i ;
for ( i = 0 ; i < model - > files - > len ; i + + )
{
FileModelNode * node = get_node ( model , i ) ;
g_clear_object ( & node - > file ) ;
g_clear_object ( & node - > info ) ;
}
g_array_free ( model - > files , TRUE ) ;
g_clear_object ( & model - > cancellable ) ;
g_clear_pointer ( & model - > attributes , g_free ) ;
g_clear_object ( & model - > dir ) ;
g_clear_object ( & model - > dir_monitor ) ;
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 ) ;
}
static void
gtk_file_system_model_class_init ( GtkFileSystemModelClass * class )
{
GObjectClass * gobject_class = G_OBJECT_CLASS ( class ) ;
gobject_class - > finalize = gtk_file_system_model_finalize ;
gobject_class - > dispose = gtk_file_system_model_dispose ;
file_system_model_signals [ FINISHED_LOADING ] =
g_signal_new ( I_ ( " finished-loading " ) ,
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 )
{
model - > show_files = TRUE ;
model - > show_folders = TRUE ;
model - > show_hidden = FALSE ;
model - > filter_folders = FALSE ;
model - > file_lookup = g_hash_table_new ( g_file_hash , ( GEqualFunc ) g_file_equal ) ;
model - > cancellable = g_cancellable_new ( ) ;
}
/*** API ***/
/**
* _gtk_file_system_model_new:
*
@@ -640,11 +808,7 @@ _gtk_file_system_model_new (void)
GtkFileSystemModel * model ;
model = g_object_new ( GTK_TYPE_FILE_SYSTEM_MODEL , NULL ) ;
model - > files = g_array_sized_new ( FALSE , FALSE , sizeof ( FileModelNode ) , FILES_PER_QUERY ) ;
/* add editable node at start */
g_array_set_size ( model - > files , 1 ) ;
memset ( get_node ( model , 0 ) , 0 , sizeof ( FileModelNode ) ) ;
return model ;
}
@@ -678,27 +842,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`
@@ -779,7 +922,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 +954,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 )
@@ -853,157 +966,23 @@ _gtk_file_system_model_get_info_for_file (GtkFileSystemModel *model,
i = node_get_for_file ( model , file ) ;
if ( i = = 0 )
if ( i = = GTK_INVALID_LIST_POSITION )
return NULL ;
node = get_node ( model , i ) ;
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
*
* Add s 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.
* Tell s 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 ,
@@ -1031,81 +1010,16 @@ _gtk_file_system_model_update_files (GtkFileSystemModel *model,
* _gtk_file_system_model_set_filter_folders().
**/
void
_gtk_file_system_model_set_filter ( GtkFileSystemModel * model ,
GtkFileFilter * filter )
_gtk_file_system_model_set_filter ( GtkFileSystemModel * model ,
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`
@@ -1118,8 +1032,8 @@ thaw_updates (GtkFileSystemModel *model)
**/
void
_gtk_file_system_model_add_and_query_file ( GtkFileSystemModel * model ,
GFile * file ,
const char * attributes )
GFile * file ,
const char * attributes )
{
g_return_if_fail ( GTK_IS_FILE_SYSTEM_MODEL ( model ) ) ;
g_return_if_fail ( G_IS_FILE ( file ) ) ;
@@ -1134,14 +1048,6 @@ _gtk_file_system_model_add_and_query_file (GtkFileSystemModel *model,
model ) ;
}
static void
gtk_file_system_model_one_query_done ( GObject * object ,
GAsyncResult * res ,
gpointer data )
{
query_done_helper ( object , res , data , TRUE ) ;
}
void
_gtk_file_system_model_add_and_query_files ( GtkFileSystemModel * model ,
GList * list ,