forked from AuroraMiddleware/gtk
Merge branch 'directorylist-monitor' into 'master'
directorylist: Add monitoring See merge request GNOME/gtk!2207
This commit is contained in:
commit
49ce680d53
@ -1444,6 +1444,8 @@ gtk_directory_list_get_file
|
||||
gtk_directory_list_set_file
|
||||
gtk_directory_list_get_io_priority
|
||||
gtk_directory_list_set_io_priority
|
||||
gtk_directory_list_get_monitored
|
||||
gtk_directory_list_set_monitored
|
||||
gtk_directory_list_is_loading
|
||||
gtk_directory_list_get_error
|
||||
<SUBSECTION Standard>
|
||||
|
@ -62,6 +62,7 @@ enum {
|
||||
PROP_IO_PRIORITY,
|
||||
PROP_ITEM_TYPE,
|
||||
PROP_LOADING,
|
||||
PROP_MONITORED,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
@ -70,8 +71,10 @@ struct _GtkDirectoryList
|
||||
GObject parent_instance;
|
||||
|
||||
char *attributes;
|
||||
int io_priority;
|
||||
GFile *file;
|
||||
GFileMonitor *monitor;
|
||||
gboolean monitored;
|
||||
int io_priority;
|
||||
|
||||
GCancellable *cancellable;
|
||||
GError *error; /* Error while loading */
|
||||
@ -147,13 +150,17 @@ gtk_directory_list_set_property (GObject *object,
|
||||
gtk_directory_list_set_io_priority (self, g_value_get_int (value));
|
||||
break;
|
||||
|
||||
case PROP_MONITORED:
|
||||
gtk_directory_list_set_monitored (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static void
|
||||
gtk_directory_list_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
@ -187,6 +194,10 @@ gtk_directory_list_get_property (GObject *object,
|
||||
g_value_set_boolean (value, gtk_directory_list_is_loading (self));
|
||||
break;
|
||||
|
||||
case PROP_MONITORED:
|
||||
g_value_set_boolean (value, gtk_directory_list_get_monitored (self));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -204,12 +215,27 @@ gtk_directory_list_stop_loading (GtkDirectoryList *self)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void directory_changed (GFileMonitor *monitor,
|
||||
GFile *file,
|
||||
GFile *other_file,
|
||||
GFileMonitorEvent event,
|
||||
gpointer data);
|
||||
|
||||
static void
|
||||
gtk_directory_list_stop_monitoring (GtkDirectoryList *self)
|
||||
{
|
||||
if (self->monitor)
|
||||
g_signal_handlers_disconnect_by_func (self->monitor, directory_changed, self);
|
||||
g_clear_object (&self->monitor);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_directory_list_dispose (GObject *object)
|
||||
{
|
||||
GtkDirectoryList *self = GTK_DIRECTORY_LIST (object);
|
||||
|
||||
gtk_directory_list_stop_loading (self);
|
||||
gtk_directory_list_stop_monitoring (self);
|
||||
|
||||
g_clear_object (&self->file);
|
||||
g_clear_pointer (&self->attributes, g_free);
|
||||
@ -301,6 +327,18 @@ gtk_directory_list_class_init (GtkDirectoryListClass *class)
|
||||
FALSE,
|
||||
GTK_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkDirectoryList:monitored:
|
||||
*
|
||||
* %TRUE if the directory is monitored for changed
|
||||
*/
|
||||
properties[PROP_MONITORED] =
|
||||
g_param_spec_boolean ("monitored",
|
||||
P_("monitored"),
|
||||
P_("TRUE if the directory is monitored for changes"),
|
||||
TRUE,
|
||||
GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);
|
||||
}
|
||||
|
||||
@ -309,6 +347,7 @@ gtk_directory_list_init (GtkDirectoryList *self)
|
||||
{
|
||||
self->items = g_sequence_new (g_object_unref);
|
||||
self->io_priority = G_PRIORITY_DEFAULT;
|
||||
self->monitored = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -324,7 +363,6 @@ gtk_directory_list_init (GtkDirectoryList *self)
|
||||
GtkDirectoryList *
|
||||
gtk_directory_list_new (const char *attributes,
|
||||
GFile *file)
|
||||
|
||||
{
|
||||
g_return_val_if_fail (file == NULL || G_IS_FILE (file), NULL);
|
||||
|
||||
@ -410,7 +448,7 @@ gtk_directory_list_got_files_cb (GObject *source,
|
||||
{
|
||||
GFileInfo *info;
|
||||
GFile *file;
|
||||
|
||||
|
||||
info = l->data;
|
||||
file = g_file_enumerator_get_child (enumerator, info);
|
||||
g_file_info_set_attribute_object (info, "standard::file", G_OBJECT (file));
|
||||
@ -496,6 +534,141 @@ gtk_directory_list_start_loading (GtkDirectoryList *self)
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LOADING]);
|
||||
}
|
||||
|
||||
static void
|
||||
got_new_file_info_cb (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer data)
|
||||
{
|
||||
GFile *file = G_FILE (source);
|
||||
GtkDirectoryList *self = GTK_DIRECTORY_LIST (data);
|
||||
GFileInfo *info;
|
||||
guint position;
|
||||
|
||||
info = g_file_query_info_finish (file, res, NULL);
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
g_file_info_set_attribute_object (info, "standard::file", G_OBJECT (file));
|
||||
position = g_sequence_get_length (self->items);
|
||||
g_sequence_append (self->items, info);
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), position, 0, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
got_existing_file_info_cb (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer data)
|
||||
{
|
||||
GFile *file = G_FILE (source);
|
||||
GtkDirectoryList *self = GTK_DIRECTORY_LIST (data);
|
||||
GFileInfo *info;
|
||||
GSequenceIter *iter;
|
||||
|
||||
info = g_file_query_info_finish (file, res, NULL);
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
g_file_info_set_attribute_object (info, "standard::file", G_OBJECT (file));
|
||||
|
||||
iter = g_sequence_get_begin_iter (self->items);
|
||||
while (!g_sequence_iter_is_end (iter))
|
||||
{
|
||||
GFileInfo *item = g_sequence_get (iter);
|
||||
GFile *f = G_FILE (g_file_info_get_attribute_object (item, "standard::file"));
|
||||
if (g_file_equal (f, file))
|
||||
{
|
||||
guint position = g_sequence_iter_get_position (iter);
|
||||
g_sequence_set (iter, g_object_ref (info));
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), position, 1, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_directory_list_remove_file (GtkDirectoryList *self,
|
||||
GFile *file)
|
||||
{
|
||||
GSequenceIter *iter;
|
||||
|
||||
iter = g_sequence_get_begin_iter (self->items);
|
||||
while (!g_sequence_iter_is_end (iter))
|
||||
{
|
||||
GFileInfo *item = g_sequence_get (iter);
|
||||
GFile *f = G_FILE (g_file_info_get_attribute_object (item, "standard::file"));
|
||||
if (g_file_equal (f, file))
|
||||
{
|
||||
guint position = g_sequence_iter_get_position (iter);
|
||||
g_sequence_remove (iter);
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), position, 1, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
directory_changed (GFileMonitor *monitor,
|
||||
GFile *file,
|
||||
GFile *other_file,
|
||||
GFileMonitorEvent event,
|
||||
gpointer data)
|
||||
{
|
||||
GtkDirectoryList *self = GTK_DIRECTORY_LIST (data);
|
||||
switch (event)
|
||||
{
|
||||
case G_FILE_MONITOR_EVENT_CREATED:
|
||||
g_file_query_info_async (file,
|
||||
self->attributes,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
self->io_priority,
|
||||
self->cancellable,
|
||||
got_new_file_info_cb,
|
||||
self);
|
||||
break;
|
||||
|
||||
case G_FILE_MONITOR_EVENT_DELETED:
|
||||
gtk_directory_list_remove_file (self, file);
|
||||
break;
|
||||
|
||||
case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
|
||||
g_file_query_info_async (file,
|
||||
self->attributes,
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
self->io_priority,
|
||||
self->cancellable,
|
||||
got_existing_file_info_cb,
|
||||
self);
|
||||
break;
|
||||
|
||||
case G_FILE_MONITOR_EVENT_CHANGED:
|
||||
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
|
||||
case G_FILE_MONITOR_EVENT_PRE_UNMOUNT:
|
||||
case G_FILE_MONITOR_EVENT_UNMOUNTED:
|
||||
case G_FILE_MONITOR_EVENT_MOVED:
|
||||
case G_FILE_MONITOR_EVENT_RENAMED:
|
||||
case G_FILE_MONITOR_EVENT_MOVED_IN:
|
||||
case G_FILE_MONITOR_EVENT_MOVED_OUT:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_directory_list_start_monitoring (GtkDirectoryList *self)
|
||||
{
|
||||
g_assert (self->monitor == NULL);
|
||||
self->monitor = g_file_monitor_directory (self->file, G_FILE_MONITOR_NONE, NULL, NULL);
|
||||
g_signal_connect (self->monitor, "changed", G_CALLBACK (directory_changed), self);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_directory_list_update_monitoring (GtkDirectoryList *self)
|
||||
{
|
||||
gtk_directory_list_stop_monitoring (self);
|
||||
if (self->file && self->monitored)
|
||||
gtk_directory_list_start_monitoring (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_directory_list_set_file:
|
||||
* @self: a #GtkDirectoryList
|
||||
@ -520,6 +693,7 @@ gtk_directory_list_set_file (GtkDirectoryList *self,
|
||||
|
||||
g_set_object (&self->file, file);
|
||||
|
||||
gtk_directory_list_update_monitoring (self);
|
||||
gtk_directory_list_start_loading (self);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FILE]);
|
||||
@ -679,3 +853,52 @@ gtk_directory_list_get_error (GtkDirectoryList *self)
|
||||
return self->error;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_directory_list_set_monitored:
|
||||
* @self: a #GtkDirectoryList
|
||||
* @monitored: %TRUE to monitor the directory for changes
|
||||
*
|
||||
* Sets whether the directory list will monitor the directory
|
||||
* for changes. If monitoring is enabled, the
|
||||
* #GListModel::items-changed signal will be emitted when the
|
||||
* directory contents change.
|
||||
*
|
||||
* When monitoring is turned on after the initial creation
|
||||
* of the directory list, the directory is reloaded to avoid
|
||||
* missing files that appeared between the initial loading
|
||||
* and when monitoring was turned on.
|
||||
*/
|
||||
void
|
||||
gtk_directory_list_set_monitored (GtkDirectoryList *self,
|
||||
gboolean monitored)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_DIRECTORY_LIST (self));
|
||||
|
||||
if (self->monitored == monitored)
|
||||
return;
|
||||
|
||||
self->monitored = monitored;
|
||||
|
||||
gtk_directory_list_update_monitoring (self);
|
||||
if (monitored)
|
||||
gtk_directory_list_start_loading (self);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MONITORED]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_directory_list_get_monitored:
|
||||
* @self: a #GtkDirectoryList
|
||||
*
|
||||
* Returns whether the directory list is monitoring
|
||||
* the directory for changes.
|
||||
*
|
||||
* Returns: %TRUE if the directory is monitored
|
||||
*/
|
||||
gboolean
|
||||
gtk_directory_list_get_monitored (GtkDirectoryList *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_DIRECTORY_LIST (self), TRUE);
|
||||
|
||||
return self->monitored;
|
||||
}
|
||||
|
@ -62,6 +62,12 @@ gboolean gtk_directory_list_is_loading (GtkDirectoryLis
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const GError * gtk_directory_list_get_error (GtkDirectoryList *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_directory_list_set_monitored (GtkDirectoryList *self,
|
||||
gboolean monitored);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_directory_list_get_monitored (GtkDirectoryList *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_DIRECTORY_LIST_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user