Commit 7ad43247 authored by Paolo Bacchilega's avatar Paolo Bacchilega
Browse files

[organize_task] more work on the organize catalog

parent 3c219720
......@@ -325,11 +325,17 @@ sort_catalogs (gconstpointer a,
GthFileData *file_data_a = (GthFileData *) a;
GthFileData *file_data_b = (GthFileData *) b;
if (g_file_info_get_attribute_boolean (file_data_a->info, "gthumb::no-child") != g_file_info_get_attribute_boolean (file_data_b->info, "gthumb::no-child"))
if (g_file_info_get_attribute_boolean (file_data_a->info, "gthumb::no-child") != g_file_info_get_attribute_boolean (file_data_b->info, "gthumb::no-child")) {
/* put the libraries before the catalogs */
return g_file_info_get_attribute_boolean (file_data_a->info, "gthumb::no-child") ? 1 : -1;
else
}
else if (g_file_info_get_sort_order (file_data_a->info) == g_file_info_get_sort_order (file_data_b->info))
return g_utf8_collate (g_file_info_get_display_name (file_data_a->info),
g_file_info_get_display_name (file_data_b->info));
else if (g_file_info_get_sort_order (file_data_a->info) < g_file_info_get_sort_order (file_data_b->info))
return -1;
else
return 1;
}
......@@ -654,6 +660,7 @@ catalogs__gth_browser_update_extra_widget_cb (GthBrowser *browser)
if (data->organize_button == NULL) {
data->organize_button = gtk_button_new ();
gtk_container_add (GTK_CONTAINER (data->organize_button), gtk_label_new (_("Organize")));
gtk_widget_set_tooltip_text (data->organize_button, _("Automatically organize files by date"));
g_object_add_weak_pointer (G_OBJECT (data->organize_button), (gpointer *)&data->organize_button);
gtk_button_set_relief (GTK_BUTTON (data->organize_button), GTK_RELIEF_NONE);
gtk_widget_show_all (data->organize_button);
......
......@@ -97,117 +97,198 @@
</packing>
</child>
<child>
<object class="GtkVBox" id="vbox3">
<object class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkHBox" id="hbox1">
<object class="GtkVBox" id="vbox3">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label2">
<object class="GtkVBox" id="vbox4">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Organization:</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkHBox" id="hbox4">
<property name="visible">True</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Organization:</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="n_catalogs_label">
<property name="visible">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox5">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="width_request">300</property>
<property name="height_request">250</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">automatic</property>
<property name="vscrollbar_policy">automatic</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="organization_treeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">results_liststore</property>
<property name="headers_clickable">False</property>
<property name="rules_hint">True</property>
<property name="search_column">0</property>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn1">
<property name="title">Catalog</property>
<property name="expand">True</property>
<property name="clickable">True</property>
<property name="reorderable">True</property>
<property name="sort_indicator">True</property>
<property name="sort_column_id">3</property>
<child>
<object class="GtkCellRendererPixbuf" id="icon_cellrendererpixbuf"/>
<attributes>
<attribute name="pixbuf">4</attribute>
</attributes>
</child>
<child>
<object class="GtkCellRendererText" id="catalog_name_cellrenderertext"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn2">
<property name="title">Files</property>
<property name="expand">True</property>
<property name="clickable">True</property>
<property name="reorderable">True</property>
<property name="sort_indicator">True</property>
<property name="sort_column_id">1</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext2"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn3">
<property name="title">Create</property>
<child>
<object class="GtkCellRendererToggle" id="create_cellrenderertoggle"/>
<attributes>
<attribute name="active">2</attribute>
</attributes>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="n_catalogs_label">
<object class="GtkHBox" id="hbox6">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="spacing">6</property>
<child>
<object class="GtkButton" id="select_all_button">
<property name="label" translatable="yes">Select All</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="select_none_button">
<property name="label" translatable="yes">Select None</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox4">
<property name="visible">True</property>
<object class="GtkVBox" id="preview_box">
<property name="width_request">350</property>
<property name="height_request">350</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="width_request">300</property>
<property name="height_request">150</property>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">automatic</property>
<property name="vscrollbar_policy">automatic</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="organization_treeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">results_liststore</property>
<property name="headers_clickable">False</property>
<property name="rules_hint">True</property>
<property name="search_column">0</property>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn1">
<property name="title">Catalog</property>
<property name="expand">True</property>
<property name="reorderable">True</property>
<property name="sort_indicator">True</property>
<property name="sort_column_id">3</property>
<child>
<object class="GtkCellRendererPixbuf" id="icon_cellrendererpixbuf"/>
<attributes>
<attribute name="pixbuf">4</attribute>
</attributes>
</child>
<child>
<object class="GtkCellRendererText" id="cellrenderertext1"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn2">
<property name="title">Files</property>
<property name="expand">True</property>
<property name="reorderable">True</property>
<property name="sort_indicator">True</property>
<property name="sort_column_id">1</property>
<child>
<object class="GtkCellRendererText" id="cellrenderertext2"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="treeviewcolumn3">
<property name="title">Create</property>
<child>
<object class="GtkCellRendererToggle" id="create_cellrenderertoggle"/>
<attributes>
<attribute name="active">2</attribute>
</attributes>
</child>
</object>
</child>
</object>
</child>
<property name="xalign">0</property>
<property name="label" translatable="yes">Catalog _Preview:</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
......
......@@ -53,7 +53,8 @@
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">A catalog will be created for each group.</property>
<property name="label" translatable="yes">Files will be organized in catalogs.</property>
<property name="wrap">True</property>
</object>
</child>
</object>
......@@ -69,7 +70,7 @@
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Group by:</property>
<property name="label" translatable="yes">_Group files by:</property>
<property name="use_underline">True</property>
</object>
<packing>
......@@ -94,37 +95,37 @@
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="include_subfolders_checkbutton">
<property name="label" translatable="yes">_Include sub-folders</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="ignore_singletons_checkbutton">
<property name="label" translatable="yes">Ignore groups with a single file</property>
<object class="GtkCheckButton" id="include_subfolders_checkbutton">
<property name="label" translatable="yes">_Include sub-folders</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="ignore_singletons_checkbutton">
<property name="label" translatable="yes">Ignore catalogs with a single file</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
......@@ -162,7 +163,7 @@
</child>
</object>
<packing>
<property name="position">3</property>
<property name="position">4</property>
</packing>
</child>
</object>
......
......@@ -52,6 +52,10 @@ struct _GthOrganizeTaskPrivate
GtkListStore *results_liststore;
GHashTable *catalogs;
GdkPixbuf *icon_pixbuf;
gboolean organized;
GtkWidget *file_list;
int n_catalogs;
int n_files;
};
......@@ -89,12 +93,6 @@ save_catalog (gpointer key,
gsize size;
GError *error = NULL;
if (! self->priv->create_singletons) {
GList *file_list = gth_catalog_get_file_list (catalog);
if ((file_list == NULL) || (file_list->next == NULL))
return;
}
gio_file = gth_catalog_file_to_gio_file (gth_catalog_get_file (catalog));
gio_parent = g_file_get_parent (gio_file);
g_file_make_directory_with_parents (gio_parent, NULL, NULL);
......@@ -117,46 +115,48 @@ save_catalog (gpointer key,
}
static void
create_singletons_catalog (gpointer key,
gpointer value,
gpointer user_data)
{
GthOrganizeTask *self = user_data;
GthCatalog *catalog = value;
GList *file_list;
file_list = gth_catalog_get_file_list (catalog);
if ((file_list != NULL) && (file_list->next == NULL))
gth_catalog_append_file (self->priv->singletons_catalog, (GFile *) file_list->data);
}
static void
save_catalogs (GthOrganizeTask *self)
{
g_hash_table_foreach (self->priv->catalogs, save_catalog, self);
GtkTreeIter iter;
if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->priv->results_liststore), &iter)) {
do {
char *key;
char *name;
gboolean create;
gtk_tree_model_get (GTK_TREE_MODEL (self->priv->results_liststore), &iter,
KEY_COLUMN, &key,
NAME_COLUMN, &name,
CREATE_CATALOG_COLUMN, &create,
-1);
if (create) {
GthCatalog *catalog;
char *original_name;
catalog = g_hash_table_lookup (self->priv->catalogs, key);
/* remove the name if it is equal to the date
* to avoid a duplication in the display-name
* attribute. */
original_name = gth_datetime_strftime (gth_catalog_get_date (catalog), "%x");
if (g_strcmp0 (original_name, name) != 0)
gth_catalog_set_name (catalog, name);
else
gth_catalog_set_name (catalog, NULL);
g_free (original_name);
}
else
g_hash_table_remove (self->priv->catalogs, key);
if (! self->priv->create_singletons && (self->priv->singletons_catalog != NULL)) {
GFile *gio_file;
char *data;
gsize size;
g_hash_table_foreach (self->priv->catalogs, create_singletons_catalog, self);
gio_file = gth_catalog_file_to_gio_file (gth_catalog_get_file (self->priv->singletons_catalog));
data = gth_catalog_to_data (self->priv->singletons_catalog, &size);
g_write_file (gio_file,
FALSE,
G_FILE_CREATE_NONE,
data,
size,
gth_task_get_cancellable (GTH_TASK (self)),
NULL);
g_free (data);
g_object_unref (gio_file);
g_free (name);
g_free (key);
}
while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->priv->results_liststore), &iter));
}
g_hash_table_foreach (self->priv->catalogs, save_catalog, self);
gth_task_completed (GTH_TASK (self), NULL);
}
......@@ -167,13 +167,65 @@ done_func (GError *error,
gpointer user_data)
{
GthOrganizeTask *self = user_data;
char *status_text;
if (error != NULL) {
if ((error != NULL) && ! g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
gth_task_completed (GTH_TASK (self), error);
return;
}
gtk_label_set_text (GTK_LABEL (GET_WIDGET ("progress_label")), _("Operation completed."));
if (! self->priv->create_singletons) {
GtkTreeIter iter;
int singletons = 0;
if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->priv->results_liststore), &iter)) {
do {
char *key;
int n;
gtk_tree_model_get (GTK_TREE_MODEL (self->priv->results_liststore), &iter,
KEY_COLUMN, &key,
CARDINALITY_COLUMN, &n,
-1);
if (n == 1) {
GthCatalog *catalog;
GList *file_list;
gtk_list_store_set (self->priv->results_liststore, &iter,
CREATE_CATALOG_COLUMN, FALSE,
-1);
singletons++;
catalog = g_hash_table_lookup (self->priv->catalogs, key);
file_list = gth_catalog_get_file_list (catalog);
gth_catalog_append_file (self->priv->singletons_catalog, file_list->data);
if (singletons == 1)
g_hash_table_insert (self->priv->catalogs,
g_strdup (gth_catalog_get_name (self->priv->singletons_catalog)),
g_object_ref (self->priv->singletons_catalog));
}
g_free (key);
}
while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->priv->results_liststore), &iter));
}
if ((self->priv->singletons_catalog != NULL) && (singletons > 0)) {
gtk_list_store_append (self->priv->results_liststore, &iter);
gtk_list_store_set (self->priv->results_liststore, &iter,
KEY_COLUMN, gth_catalog_get_name (self->priv->singletons_catalog),
NAME_COLUMN, gth_catalog_get_name (self->priv->singletons_catalog),
CARDINALITY_COLUMN, singletons,
CREATE_CATALOG_COLUMN, TRUE,
ICON_COLUMN, self->priv->icon_pixbuf,
-1);
}
}
self->priv->organized = TRUE;
status_text = g_strdup_printf (_("Operation completed. Catalogs: %d. Images: %d."), self->priv->n_catalogs, self->priv->n_files);
gtk_label_set_text (GTK_LABEL (GET_WIDGET ("progress_label")), status_text);
gtk_label_set_ellipsize (GTK_LABEL (GET_WIDGET ("progress_label")), PANGO_ELLIPSIZE_NONE);
g_free (status_text);
gtk_widget_hide (GET_WIDGET ("cancel_button"));
gtk_widget_show (GET_WIDGET ("close_button"));
......@@ -291,6 +343,7 @@ for_each_file_func (GFile *file,
CREATE_CATALOG_COLUMN, TRUE,
ICON_COLUMN, self->priv->icon_pixbuf,
-1);
self->priv->n_catalogs++;
g_free (name);
g_object_unref (catalog_file);
......@@ -315,6 +368,8 @@ for_each_file_func (GFile *file,
gtk_list_store_set (self->priv->results_liststore, &iter,
CARDINALITY_COLUMN, n + 1,
-1);
self->priv->n_files++;
g_free (k);
break;
}
......@@ -361,8 +416,10 @@ gth_organize_task_exec (GthTask *base)
self = GTH_ORGANIZE_TASK (base);
self->priv->organized = FALSE;
self->priv->n_catalogs = 0;
self->priv->n_files = 0;
gtk_list_store_clear (self->priv->results_liststore);
switch (self->priv->group_policy) {
case GTH_GROUP_POLICY_DIGITALIZED_DATE:
attributes = "standard::name,standard::type,time::modified,time::modified-usec,Embedded::Image::DateTime";
......@@ -388,7 +445,7 @@ gth_organize_task_exec (GthTask *base)
gtk_window_set_modal (GTK_WINDOW (GET_WIDGET ("organize_files_dialog")), TRUE);
gtk_widget_show (GET_WIDGET ("organize_files_dialog"));
gth_task_dialog (base, TRUE); /* FIXME */
gth_task_dialog (base, TRUE);
}