[nautilus/wip/alexpandelea/batchRename: 17/17] Add First/Last Created sort criteria



commit f41b0a8474007d65a1de6ff5e6e96a6125c5a996
Author: Alexandru Pandelea <alexandru pandelea gmail com>
Date:   Tue Jul 5 19:40:58 2016 +0300

    Add First/Last Created sort criteria
    
    This is available only if each file has the create date available and
    if parent directory is tracked.
    
    The create dates are queried using Tracker and then, the order of the
    files is stored in a hashtable, so that the user can sort the files by
    the creation date.

 src/nautilus-batch-rename-utilities.c            |  156 +++++++++++++++++++++-
 src/nautilus-batch-rename-utilities.h            |   12 ++-
 src/nautilus-batch-rename.c                      |   44 ++++++-
 src/nautilus-batch-rename.h                      |    2 +
 src/resources/ui/nautilus-batch-rename-dialog.ui |    5 -
 5 files changed, 208 insertions(+), 11 deletions(-)
---
diff --git a/src/nautilus-batch-rename-utilities.c b/src/nautilus-batch-rename-utilities.c
index 22861f2..db7e6a8 100644
--- a/src/nautilus-batch-rename-utilities.c
+++ b/src/nautilus-batch-rename-utilities.c
@@ -10,6 +10,11 @@
 
 #define MAX_DISPLAY_LEN 40
 
+typedef struct {
+        NautilusFile *file;
+        gint *position;
+} CreateDateElem;
+
 static gchar*
 batch_rename_append (gchar *file_name,
                      gchar *entry_text)
@@ -263,10 +268,31 @@ compare_files_by_last_modified (gconstpointer a,
                                                FALSE, TRUE);
 }
 
+gint
+compare_files_by_first_created (gconstpointer a,
+                                gconstpointer b)
+{
+        return *(((CreateDateElem*) a)->position) - *(((CreateDateElem*) b)->position);
+}
+
+gint
+compare_files_by_last_created (gconstpointer a,
+                               gconstpointer b)
+{
+        return *(((CreateDateElem*) b)->position) - *(((CreateDateElem*) a)->position);
+}
+
 GList*
 nautilus_batch_rename_sort (GList *selection,
-                            SortingMode mode)
+                            SortingMode mode,
+                            ...)
 {
+        GList *l,*l2;
+        va_list args;
+        GHashTable *hash_table;
+        NautilusFile *file;
+        GList *createDate_list, *createDate_list_sorted;
+
         if (mode == ORIGINAL_ASCENDING)
                 return g_list_sort (selection, compare_files_by_name_ascending);
 
@@ -282,5 +308,129 @@ nautilus_batch_rename_sort (GList *selection,
             return g_list_sort (selection, compare_files_by_last_modified);
         }
 
-        return NULL;
-}
\ No newline at end of file
+        if (mode == FIRST_CREATED || mode == LAST_CREATED) {
+                va_start (args, mode);
+
+                hash_table = va_arg(args, GHashTable*);
+
+                createDate_list = NULL;
+
+                for (l = selection; l != NULL; l = l->next) {
+                        CreateDateElem *elem;
+                        elem = malloc (sizeof (CreateDateElem*));
+
+                        file = NAUTILUS_FILE (l->data);
+
+                        elem->file = file;
+                        elem->position = (gint*) g_hash_table_lookup (hash_table, nautilus_file_get_name 
(file));
+
+                        createDate_list = g_list_prepend (createDate_list, (gpointer) elem);
+                }
+
+                if (mode == FIRST_CREATED)
+                        createDate_list_sorted = g_list_sort (createDate_list,
+                                                              compare_files_by_first_created);
+                else
+                        createDate_list_sorted = g_list_sort (createDate_list,
+                                                              compare_files_by_last_created);
+
+                for (l = selection, l2 = createDate_list_sorted; l2 != NULL; l = l->next, l2 = l2->next) {
+                        CreateDateElem *elem = l2->data;
+                        l->data = elem->file;
+                }
+
+                va_end (args);
+                g_list_free (createDate_list);
+        }
+
+        return selection;
+}
+
+GHashTable*
+check_creation_date_for_selection (GList *selection)
+{
+        GError *error = NULL;
+        TrackerSparqlConnection *connection;
+        TrackerSparqlCursor *cursor;
+        gchar *filter1, *filter2, *sparql, *tmp;
+        GHashTable *hash_table;
+        GList *l;
+        gint i, *value;
+        NautilusFile *file;
+        gchar *query = "SELECT nfo:fileName(?file) nie:contentCreated(?file) WHERE { ?file a 
nfo:FileDataObject. ";
+
+        filter1 = malloc (150);
+        sprintf (filter1, "FILTER(tracker:uri-is-parent('%s', nie:url(?file)))",
+                 nautilus_file_get_parent_uri (NAUTILUS_FILE (selection->data)));
+
+        sparql = concat (query, filter1);
+
+        for (l = selection; l != NULL; l = l->next) {
+                filter2 = malloc (150);
+
+                file = NAUTILUS_FILE (l->data);
+
+                if (l == selection)
+                        sprintf (filter2, "FILTER (nfo:fileName(?file) = '%s' ", nautilus_file_get_name 
(file));
+                else
+                        sprintf (filter2, "|| nfo:fileName(?file) = '%s'", nautilus_file_get_name (file));
+
+                tmp = sparql;
+                sparql = concat (sparql, filter2);
+
+                g_free (tmp);
+                g_free (filter2);
+        }
+
+        tmp = sparql;
+        sparql = concat (sparql, ")} ORDER BY ASC(nie:contentCreated(?file))");
+
+        connection = tracker_sparql_connection_get (NULL, &error);
+        if (!connection)
+            return NULL;
+
+        /* Make a synchronous query to the store */
+        cursor = tracker_sparql_connection_query (connection,
+                                                  sparql,
+                                                  NULL,
+                                                  &error);
+
+        if (error)
+                return NULL;
+
+        /* Check results */
+        if (!cursor) {
+                return NULL;
+        } else {
+                hash_table = g_hash_table_new_full (g_str_hash,
+                                                    g_str_equal,
+                                                    (GDestroyNotify) g_free,
+                                                    (GDestroyNotify) g_free);
+                i = 0;
+
+                /* Iterate, synchronously, the results */
+                while (tracker_sparql_cursor_next (cursor, NULL, &error)) {
+                        value = malloc (sizeof(int));
+                        *value = i++;
+
+                        g_hash_table_insert (hash_table,
+                                             strdup(tracker_sparql_cursor_get_string (cursor, 0, NULL)),
+                                             value);
+
+                        if (tracker_sparql_cursor_get_string (cursor, 1, NULL) == NULL) {
+                                g_object_unref (connection);
+                                g_hash_table_destroy (hash_table);
+                                g_free (filter1);
+
+                                return NULL;
+                        }
+                    }
+
+                g_object_unref (cursor);
+        }
+
+        g_object_unref (connection);
+        g_free (filter1);
+
+        return hash_table;
+}
diff --git a/src/nautilus-batch-rename-utilities.h b/src/nautilus-batch-rename-utilities.h
index 842da36..9aaa1cf 100644
--- a/src/nautilus-batch-rename-utilities.h
+++ b/src/nautilus-batch-rename-utilities.h
@@ -3,6 +3,7 @@
 
 #include <gio/gio.h>
 #include <gtk/gtk.h>
+#include <tracker-sparql.h>
 
 gchar* get_new_name             (NautilusBatchRenameModes  mode,
                                  gchar                     *file_name,
@@ -27,7 +28,8 @@ gchar* concat                   (gchar                       *s1,
                                  gchar                       *s2);
 
 GList* nautilus_batch_rename_sort (GList       *selection,
-                                   SortingMode mode);
+                                   SortingMode mode,
+                                   ...);
 
 gint compare_files_by_last_modified     (gconstpointer a,
                                          gconstpointer b);
@@ -41,4 +43,12 @@ gint compare_files_by_name_descending   (gconstpointer a,
 gint compare_files_by_name_ascending    (gconstpointer a,
                                          gconstpointer b);
 
+gint compare_files_by_first_created     (gconstpointer a,
+                                         gconstpointer b);
+
+gint compare_files_by_last_created      (gconstpointer a,
+                                         gconstpointer b);
+
+GHashTable* check_creation_date_for_selection  (GList *selection);
+
 #endif /* NAUTILUS_BATCH_RENAME_UTILITIES_H */
\ No newline at end of file
diff --git a/src/nautilus-batch-rename.c b/src/nautilus-batch-rename.c
index 8420cb6..40d54cd 100644
--- a/src/nautilus-batch-rename.c
+++ b/src/nautilus-batch-rename.c
@@ -64,6 +64,8 @@ struct _NautilusBatchRename
         GActionGroup            *action_group;
 
         GMenu                   *numbering_order_menu;
+
+        GHashTable              *create_date;
 };
 
 static void     batch_rename_dialog_on_closed           (GtkDialog              *dialog);
@@ -83,12 +85,12 @@ numbering_order_changed (GSimpleAction       *action,
         dialog = NAUTILUS_BATCH_RENAME (user_data);
 
         target_name = g_variant_get_string (value, NULL);
-        g_message("%s",target_name);
 
         if (g_strcmp0 (target_name, "name-ascending") == 0) {
                 gtk_label_set_label (GTK_LABEL (dialog->numbering_order_label),
                                      "Original name (Ascending)  ");
-                dialog->selection = nautilus_batch_rename_sort (dialog->selection, ORIGINAL_ASCENDING);
+                dialog->selection = nautilus_batch_rename_sort (dialog->selection,
+                                                                ORIGINAL_ASCENDING);
         }
 
         if (g_strcmp0 (target_name, "name-descending") == 0) {
@@ -112,6 +114,22 @@ numbering_order_changed (GSimpleAction       *action,
                                                                 LAST_MODIFIED);
         }
 
+        if (g_strcmp0 (target_name, "first-created") == 0) {
+                gtk_label_set_label (GTK_LABEL (dialog->numbering_order_label),
+                                     "First Created                         ");
+                dialog->selection = nautilus_batch_rename_sort (dialog->selection,
+                                                                FIRST_CREATED,
+                                                                dialog->create_date);
+        }
+
+        if (g_strcmp0 (target_name, "last-created") == 0) {
+                gtk_label_set_label (GTK_LABEL (dialog->numbering_order_label),
+                                     "Last Created                         ");
+                dialog->selection = nautilus_batch_rename_sort (dialog->selection,
+                                                                LAST_CREATED,
+                                                                dialog->create_date);
+        }
+
         g_simple_action_set_state (action, value);
 
         g_signal_emit_by_name (dialog->numbering_order_popover, "closed");
@@ -400,6 +418,9 @@ numbering_order_popover_closed (NautilusBatchRename *dialog)
 static void
 nautilus_batch_rename_initialize_actions (NautilusBatchRename *dialog)
 {
+        GMenuItem *first_created;
+        GMenuItem *last_created;
+
         dialog->action_group = G_ACTION_GROUP (g_simple_action_group_new ());
 
         g_action_map_add_action_entries (G_ACTION_MAP (dialog->action_group),
@@ -409,6 +430,25 @@ nautilus_batch_rename_initialize_actions (NautilusBatchRename *dialog)
         gtk_widget_insert_action_group (GTK_WIDGET (dialog),
                                         "dialog",
                                         G_ACTION_GROUP (dialog->action_group));
+
+        dialog->create_date = check_creation_date_for_selection (dialog->selection);
+
+        if (dialog->create_date != NULL) {
+                first_created = g_menu_item_new ("First Created",
+                                                 "dialog.numbering-order-changed");
+
+                g_menu_item_set_attribute (first_created, "target", "s", "first-created");
+
+                g_menu_append_item (dialog->numbering_order_menu, first_created);
+
+                last_created = g_menu_item_new ("Last Created",
+                                                 "dialog.numbering-order-changed");
+
+                g_menu_item_set_attribute (last_created, "target", "s", "last-created");
+
+                g_menu_append_item (dialog->numbering_order_menu, last_created);
+
+        }
 }
 
 static void
diff --git a/src/nautilus-batch-rename.h b/src/nautilus-batch-rename.h
index c5f0197..3f34e07 100644
--- a/src/nautilus-batch-rename.h
+++ b/src/nautilus-batch-rename.h
@@ -20,6 +20,8 @@ typedef enum {
         ORIGINAL_DESCENDING = 1,
         FIRST_MODIFIED = 2,
         LAST_MODIFIED = 3,
+        FIRST_CREATED = 4,
+        LAST_CREATED = 5,
 } SortingMode;
 
 #define NAUTILUS_TYPE_BATCH_RENAME (nautilus_batch_rename_get_type())
diff --git a/src/resources/ui/nautilus-batch-rename-dialog.ui 
b/src/resources/ui/nautilus-batch-rename-dialog.ui
index edf4d80..8715c02 100644
--- a/src/resources/ui/nautilus-batch-rename-dialog.ui
+++ b/src/resources/ui/nautilus-batch-rename-dialog.ui
@@ -324,28 +324,23 @@
   <menu id="numbering_order_menu">
     <section>
       <item>
-        <attribute name="id">name_ascending</attribute>
         <attribute name="label" translatable="yes">Original name (Ascending) </attribute>
         <attribute name="action">dialog.numbering-order-changed</attribute>
         <attribute name="target">name-ascending</attribute>
       </item>
       <item>
-        <attribute name="id">name_descending</attribute>
         <attribute name="label" translatable="yes">Original name (Descending)</attribute>
         <attribute name="action">dialog.numbering-order-changed</attribute>
         <attribute name="target">name-descending</attribute>
       </item>
       <item>
-        <attribute name="id">first_modified</attribute>
         <attribute name="label" translatable="yes">First Modified</attribute>
         <attribute name="action">dialog.numbering-order-changed</attribute>
         <attribute name="target">first-modified</attribute>
       </item>
       <item>
-        <attribute name="id">last_modified</attribute>
         <attribute name="label" translatable="yes">Last Modified</attribute>
         <attribute name="action">dialog.numbering-order-changed</attribute>
-        <attribute name="verb-icon">object-select-symbolic</attribute>
         <attribute name="target">last-modified</attribute>
       </item>
     </section>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]