Commit 61459409 authored by Paolo Bacchilega's avatar Paolo Bacchilega
Browse files

changed gth_file_source

*) added for_each_child virtual function
*) implemented list with for_each_child
parent 749b672a
......@@ -417,129 +417,240 @@ gth_file_source_catalogs_read_metadata (GthFileSource *file_source,
}
/* -- list -- */
/* -- gth_file_source_catalogs_for_each_child -- */
typedef struct {
GthFileSource *file_source;
gboolean recursive;
const char *attributes;
StartDirCallback start_dir_func;
ForEachChildCallback for_each_file_func;
ReadyCallback ready_func;
gpointer user_data;
GthCatalog *catalog;
GList *to_visit;
} ForEachChildData;
static void
list__done_func (GError *error,
gpointer user_data)
for_each_child_data_free (ForEachChildData *data)
{
GthFileSourceCatalogs *catalogs = user_data;
_g_object_list_unref (data->to_visit);
g_object_ref (data->catalog);
g_object_ref (data->file_source);
}
if (G_IS_OBJECT (catalogs))
gth_file_source_set_active (GTH_FILE_SOURCE (catalogs), FALSE);
if (error != NULL) {
_g_object_list_unref (catalogs->priv->files);
catalogs->priv->files = NULL;
g_clear_error (&error);
static void
for_each_child_data_done (ForEachChildData *data,
GError *error)
{
gth_file_source_set_active (data->file_source, FALSE);
data->ready_func (G_OBJECT (data->file_source), error, data->user_data);
for_each_child_data_free (data);
}
static void for_each_child__visit_file (ForEachChildData *data,
GthFileData *library);
static void
for_each_child__continue (ForEachChildData *data)
{
GthFileData *file;
GList *tmp;
if (! data->recursive || (data->to_visit == NULL)) {
for_each_child_data_done (data, NULL);
return;
}
g_object_ref (catalogs);
catalogs->priv->ready_func ((GthFileSource *) catalogs,
catalogs->priv->files,
error,
catalogs->priv->ready_data);
g_object_unref (catalogs);
file = data->to_visit->data;
tmp = data->to_visit;
data->to_visit = g_list_remove_link (data->to_visit, tmp);
g_list_free (tmp);
for_each_child__visit_file (data, file);
g_object_unref (file);
}
static void
list__for_each_file_func (GFile *file,
GFileInfo *info,
gpointer user_data)
for_each_child__done_func (GError *error,
gpointer user_data)
{
GthFileSourceCatalogs *catalogs = user_data;
GthFileData *file_data;
for_each_child__continue ((ForEachChildData *) user_data);
}
file_data = gth_file_source_get_file_data (GTH_FILE_SOURCE (catalogs), file, info);
if (file_data != NULL)
catalogs->priv->files = g_list_prepend (catalogs->priv->files, file_data);
static void
for_each_child__for_each_file_func (GFile *file,
GFileInfo *info,
gpointer user_data)
{
ForEachChildData *data = user_data;
GthFileData *file_data;
file_data = gth_file_source_get_file_data (data->file_source, file, info);
if (file_data == NULL)
return;
data->for_each_file_func (file_data->file, file_data->info, data->user_data);
if (data->recursive && (g_file_info_get_file_type (file_data->info) == G_FILE_TYPE_DIRECTORY))
data->to_visit = g_list_append (data->to_visit, g_object_ref (file_data));
g_object_unref (file_data);
}
static DirOp
list__start_dir_func (GFile *directory,
GFileInfo *info,
GError **error,
gpointer user_data)
for_each_child__start_dir_func (GFile *directory,
GFileInfo *info,
GError **error,
gpointer user_data)
{
return DIR_OP_CONTINUE;
}
static void
catalog_list_ready_cb (GthCatalog *catalog,
GList *files,
GError *error,
gpointer user_data)
for_each_child__catalog_list_ready_cb (GthCatalog *catalog,
GList *files,
GError *error,
gpointer user_data)
{
GthFileSourceCatalogs *catalogs = user_data;
ForEachChildData *data = user_data;
GList *scan;
g_object_ref (catalogs);
for (scan = files; scan; scan = scan->next) {
GthFileData *file_data = scan->data;
catalogs->priv->ready_func ((GthFileSource *) catalogs,
files,
error,
catalogs->priv->ready_data);
data->for_each_file_func (file_data->file,
file_data->info,
data->user_data);
}
gth_catalog_set_file_list (catalogs->priv->catalog, NULL);
g_object_unref (catalogs);
if (G_IS_OBJECT (catalogs))
gth_file_source_set_active (GTH_FILE_SOURCE (catalogs), FALSE);
for_each_child__continue (data);
}
static void
gth_file_source_catalogs_list (GthFileSource *file_source,
GFile *folder,
const char *attributes,
ListReady func,
gpointer user_data)
for_each_child__visit_file (ForEachChildData *data,
GthFileData *file_data)
{
GthFileSourceCatalogs *catalogs = (GthFileSourceCatalogs *) file_source;
char *uri;
GFile *gio_file;
gth_file_source_set_active (GTH_FILE_SOURCE (catalogs), TRUE);
g_cancellable_reset (gth_file_source_get_cancellable (file_source));
GFile *gio_file;
char *uri;
_g_object_list_unref (catalogs->priv->files);
catalogs->priv->files = NULL;
if (data->start_dir_func != NULL) {
GError *error = NULL;
catalogs->priv->ready_func = func;
catalogs->priv->ready_data = user_data;
uri = g_file_get_uri (folder);
gio_file = gth_file_source_to_gio_file (file_source, folder);
switch (data->start_dir_func (file_data->file, file_data->info, &error, data->user_data)) {
case DIR_OP_CONTINUE:
break;
case DIR_OP_SKIP:
for_each_child__continue (data);
return;
case DIR_OP_STOP:
for_each_child_data_done (data, NULL);
return;
}
}
gio_file = gth_file_source_to_gio_file (data->file_source, file_data->file);
uri = g_file_get_uri (file_data->file);
if (g_str_has_suffix (uri, ".gqv")
|| g_str_has_suffix (uri, ".catalog")
|| g_str_has_suffix (uri, ".search"))
{
gth_catalog_set_file (catalogs->priv->catalog, gio_file);
gth_catalog_list_async (catalogs->priv->catalog,
attributes,
gth_file_source_get_cancellable (file_source),
catalog_list_ready_cb,
file_source);
gth_catalog_set_file (data->catalog, gio_file);
gth_catalog_list_async (data->catalog,
data->attributes,
gth_file_source_get_cancellable (data->file_source),
for_each_child__catalog_list_ready_cb,
data);
}
else
g_directory_foreach_child (gio_file,
FALSE,
TRUE,
attributes,
gth_file_source_get_cancellable (file_source),
list__start_dir_func,
list__for_each_file_func,
list__done_func,
file_source);
"standard::name,standard::type",
gth_file_source_get_cancellable (data->file_source),
for_each_child__start_dir_func,
for_each_child__for_each_file_func,
for_each_child__done_func,
data);
g_object_unref (gio_file);
g_free (uri);
}
static void
for_each_child__parent_info_ready_cb (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
{
ForEachChildData *data = user_data;
GFile *file;
GFileInfo *info;
GError *error = NULL;
GthFileData *file_data;
file = G_FILE (source_object);
info = g_file_query_info_finish (file, result, &error);
if (info == NULL) {
for_each_child_data_done (data, error);
return;
}
file_data = gth_file_source_get_file_data (data->file_source, file, info);
for_each_child__visit_file (data, file_data);
g_object_unref (file_data);
}
static void
gth_file_source_catalogs_for_each_child (GthFileSource *file_source,
GFile *parent,
gboolean recursive,
const char *attributes,
StartDirCallback start_dir_func,
ForEachChildCallback for_each_file_func,
ReadyCallback ready_func,
gpointer user_data)
{
ForEachChildData *data;
GFile *gio_parent;
data = g_new0 (ForEachChildData, 1);
data->file_source = g_object_ref (file_source);
data->recursive = recursive;
data->attributes = attributes;
data->start_dir_func = start_dir_func;
data->for_each_file_func = for_each_file_func;
data->ready_func = ready_func;
data->user_data = user_data;
data->catalog = gth_catalog_new ();
gio_parent = gth_file_source_to_gio_file (file_source, parent);
g_file_query_info_async (gio_parent,
"standard::name,standard::type",
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_DEFAULT,
gth_file_source_get_cancellable (data->file_source),
for_each_child__parent_info_ready_cb,
data);
g_object_unref (gio_parent);
}
/* -- gth_file_source_catalogs_copy -- */
......@@ -883,7 +994,7 @@ gth_file_source_catalogs_class_init (GthFileSourceCatalogsClass *class)
file_source_class->get_file_data = gth_file_source_catalogs_get_file_data;
file_source_class->write_metadata = gth_file_source_catalogs_write_metadata;
file_source_class->read_metadata = gth_file_source_catalogs_read_metadata;
file_source_class->list = gth_file_source_catalogs_list;
file_source_class->for_each_child = gth_file_source_catalogs_for_each_child;
file_source_class->copy = gth_file_source_catalogs_copy;
file_source_class->is_reorderable = gth_file_source_catalogs_is_reorderable;
file_source_class->reorder = gth_file_source_catalogs_reorder;
......
......@@ -37,13 +37,16 @@
struct _GthFileSourceVfsPrivate
{
GList *files;
ListReady ready_func;
gpointer ready_data;
GHashTable *monitors;
GList *monitor_queue[GTH_MONITOR_N_EVENTS];
guint monitor_update_id;
GUnixMountMonitor *mount_monitor;
GList *files;
ListReady list_ready_func;
StartDirCallback start_dir_func;
ForEachChildCallback for_each_file_func;
ReadyCallback ready_func;
gpointer user_data;
GHashTable *monitors;
GList *monitor_queue[GTH_MONITOR_N_EVENTS];
guint monitor_update_id;
GUnixMountMonitor *mount_monitor;
};
......@@ -157,60 +160,53 @@ gth_file_source_vfs_get_file_info (GthFileSource *file_source,
}
/* -- gth_file_source_vfs_list -- */
/* -- gth_file_source_vfs_for_each_child -- */
static void
list__done_func (GError *error,
gpointer user_data)
fec__done_func (GError *error,
gpointer user_data)
{
GthFileSourceVfs *file_source_vfs = user_data;
if (G_IS_OBJECT (file_source_vfs))
gth_file_source_set_active (GTH_FILE_SOURCE (file_source_vfs), FALSE);
file_source_vfs->priv->ready_func ((GthFileSource *)file_source_vfs,
file_source_vfs->priv->files,
gth_file_source_set_active (GTH_FILE_SOURCE (file_source_vfs), FALSE);
file_source_vfs->priv->ready_func (G_OBJECT (file_source_vfs),
error,
file_source_vfs->priv->ready_data);
g_object_unref (file_source_vfs);
file_source_vfs->priv->user_data);
}
static void
list__for_each_file_func (GFile *file,
GFileInfo *info,
gpointer user_data)
fec__for_each_file_func (GFile *file,
GFileInfo *info,
gpointer user_data)
{
GthFileSourceVfs *file_source_vfs = user_data;
switch (g_file_info_get_file_type (info)) {
case G_FILE_TYPE_REGULAR:
case G_FILE_TYPE_DIRECTORY:
file_source_vfs->priv->files = g_list_prepend (file_source_vfs->priv->files, gth_file_data_new (file, info));
break;
default:
break;
}
file_source_vfs->priv->for_each_file_func (file, info, file_source_vfs->priv->user_data);
}
static DirOp
list__start_dir_func (GFile *directory,
GFileInfo *info,
GError **error,
gpointer user_data)
fec__start_dir_func (GFile *directory,
GFileInfo *info,
GError **error,
gpointer user_data)
{
return DIR_OP_CONTINUE;
GthFileSourceVfs *file_source_vfs = user_data;
return file_source_vfs->priv->start_dir_func (directory, info, error, file_source_vfs->priv->user_data);
}
static void
gth_file_source_vfs_list (GthFileSource *file_source,
GFile *folder,
const char *attributes,
ListReady func,
gpointer user_data)
gth_file_source_vfs_for_each_child (GthFileSource *file_source,
GFile *parent,
gboolean recursive,
const char *attributes,
StartDirCallback start_dir_func,
ForEachChildCallback for_each_file_func,
ReadyCallback ready_func,
gpointer user_data)
{
GthFileSourceVfs *file_source_vfs = (GthFileSourceVfs *) file_source;
GFile *gio_folder;
......@@ -218,22 +214,20 @@ gth_file_source_vfs_list (GthFileSource *file_source,
gth_file_source_set_active (file_source, TRUE);
g_cancellable_reset (gth_file_source_get_cancellable (file_source));
_g_object_list_unref (file_source_vfs->priv->files);
file_source_vfs->priv->files = NULL;
file_source_vfs->priv->ready_func = func;
file_source_vfs->priv->ready_data = user_data;
file_source_vfs->priv->start_dir_func = start_dir_func;
file_source_vfs->priv->for_each_file_func = for_each_file_func;
file_source_vfs->priv->ready_func = ready_func;
file_source_vfs->priv->user_data = user_data;
g_object_ref (file_source);
gio_folder = gth_file_source_to_gio_file (file_source, folder);
gio_folder = gth_file_source_to_gio_file (file_source, parent);
g_directory_foreach_child (gio_folder,
FALSE,
recursive,
TRUE,
attributes,
gth_file_source_get_cancellable (file_source),
list__start_dir_func,
list__for_each_file_func,
list__done_func,
fec__start_dir_func,
fec__for_each_file_func,
fec__done_func,
file_source);
g_object_unref (gio_folder);
......@@ -576,7 +570,7 @@ gth_file_source_vfs_class_init (GthFileSourceVfsClass *class)
file_source_class->get_entry_points = gth_file_source_vfs_get_entry_points;
file_source_class->to_gio_file = gth_file_source_vfs_to_gio_file;
file_source_class->get_file_info = gth_file_source_vfs_get_file_info;
file_source_class->list = gth_file_source_vfs_list;
file_source_class->for_each_child = gth_file_source_vfs_for_each_child;
file_source_class->copy = gth_file_source_vfs_copy;
file_source_class->can_cut = gth_file_source_vfs_can_cut;
file_source_class->monitor_entry_points = gth_file_source_vfs_monitor_entry_points;
......
......@@ -50,6 +50,7 @@ typedef enum {
FILE_SOURCE_OP_WRITE_METADATA,
FILE_SOURCE_OP_READ_METADATA,
FILE_SOURCE_OP_LIST,
FILE_SOURCE_OP_FOR_EACH_CHILD,
FILE_SOURCE_OP_READ_ATTRIBUTES,
FILE_SOURCE_OP_RENAME,
FILE_SOURCE_OP_COPY,
......@@ -117,11 +118,23 @@ typedef struct {
} ReadMetadataData;
typedef struct {
GFile *parent;
gboolean recursive;
const char *attributes;
StartDirCallback dir_func;
ForEachChildCallback child_func;
ReadyCallback ready_func;
gpointer data;
} ForEachChildData;
typedef struct {
GthFileSource *file_source;
FileSourceOp op;
union {
ListData list;
ForEachChildData fec;
ReadAttributesData read_attributes;
RenameData rename;
CopyData copy;
......@@ -147,6 +160,9 @@ file_source_async_op_free (FileSourceAsyncOp *async_op)
case FILE_SOURCE_OP_LIST:
g_object_unref (async_op->data.list.folder);
break;
case FILE_SOURCE_OP_FOR_EACH_CHILD:
g_object_unref (async_op->data.fec.parent);
break;
case FILE_SOURCE_OP_READ_ATTRIBUTES:
_g_object_list_unref (async_op->data.read_attributes.files);
break;
......@@ -231,6 +247,33 @@ gth_file_source_queue_list (GthFileSource *file_source,
}
static void
gth_file_source_queue_for_each_child (GthFileSource *file_source,
GFile *parent,
gboolean recursive,
const char *attributes,
StartDirCallback dir_func,
ForEachChildCallback child_func,
ReadyCallback ready_func,
gpointer data)
{
FileSourceAsyncOp *async_op;
async_op = g_new0 (FileSourceAsyncOp, 1);
async_op->file_source = file_source;
async_op->op = FILE_SOURCE_OP_FOR_EACH_CHILD;
async_op->data.fec.parent = g_file_dup (parent);
async_op->data.fec.recursive = recursive;
async_op->data.fec.attributes = attributes;
async_op->data.fec.dir_func = dir_func;
async_op->data.fec.child_func = child_func;
async_op->data.fec.ready_func = ready_func;
async_op->data.fec.data = data;
file_source->priv->queue = g_list_append (file_source->priv->queue, async_op);
}
static void
gth_file_source_queue_read_attributes (GthFileSource *file_source,
GList *files,
......@@ -358,6 +401,16 @@ gth_file_source_exec_next_in_queue (GthFileSource *file_source)
async_op->data.list.func,
async_op->data.list.data);
break;
case FILE_SOURCE_OP_FOR_EACH_CHILD:
gth_file_source_for_each_child (file_source,
async_op->data.fec.parent,
async_op->data.fec.recursive,
async_op->data.fec.attributes,
async_op->data.fec.dir_func,
async_op->data.fec.child_func,
async_op->data.fec.ready_func,
async_op->data.fec.data);
break;
case FILE_SOURCE_OP_READ_ATTRIBUTES:
gth_file_source_read_attributes (file_source,
async_op->data.read_attributes.files,
......@@ -548,17 +601,6 @@ base_read_metadata (GthFileSource *file_source,
}
static void
base_list (GthFileSource *file_source,
GFile *folder,
const char *attributes,
ListReady func,
gpointer data)
{
/* void */
}
static void
base_rename (GthFileSource *file_source,
GFile *file,
......@@ -636,7 +678,7 @@ gth_file_source_finalize (GObject *object)
if (file_source->priv != NULL) {
gth_file_source_clear_queue (file_source);
_g_string_list_free (file_source->priv->schemes);
g_object_unref (file_source->priv->cancellable);
_g_object_unref (file_source->priv->cancellable);
g_free (file_source->priv);
file_source->priv = NULL;
......@@ -662,7 +704,6 @@ gth_file_source_class_init (GthFileSourceClass *class)
class->get_file_data = base_get_file_data;
class->write_metadata = base_write_metadata;
class->read_metadata = base_read_metadata;
class->list = base_list;
class->rename = base_rename;
class->can_cut = base_can_cut;
class->monitor_entry_points = base_monitor_entry_points;
......@@ -853,18 +894,105 @@ gth_file_source_read_metadata (GthFileSource *file_source,
}
/* -- gth_file_source_list -- */
typedef struct {
GthFileSource *file_source;
ListReady ready_func;
gpointer user_data;
GList *files;
} ListOpData;
static void