Include a Other Software section in Help file
[geeqie.git] / src / filedata.c
index 356b7c5..f2c8795 100644 (file)
 #include "secure_save.h"
 
 #include "exif.h"
+#include "misc.h"
 
 #include <errno.h>
+#include <grp.h>
 
 #ifdef DEBUG_FILEDATA
 gint global_file_data_count = 0;
@@ -111,16 +113,16 @@ gchar *text_from_size_abrev(gint64 size)
                }
        if (size < (gint64)1048576)
                {
-               return g_strdup_printf(_("%.1f K"), (gdouble)size / 1024.0);
+               return g_strdup_printf(_("%.1f KiB"), (gdouble)size / 1024.0);
                }
        if (size < (gint64)1073741824)
                {
-               return g_strdup_printf(_("%.1f MB"), (gdouble)size / 1048576.0);
+               return g_strdup_printf(_("%.1f MiB"), (gdouble)size / 1048576.0);
                }
 
        /* to avoid overflowing the gdouble, do division in two steps */
        size /= 1048576;
-       return g_strdup_printf(_("%.1f GB"), (gdouble)size / 1024.0);
+       return g_strdup_printf(_("%.1f GiB"), (gdouble)size / 1024.0);
 }
 
 /* note: returned string is valid until next call to text_from_time() */
@@ -370,6 +372,8 @@ static void file_data_set_path(FileData *fd, const gchar *path)
 static FileData *file_data_new(const gchar *path_utf8, struct stat *st, gboolean disable_sidecars)
 {
        FileData *fd;
+       struct passwd *user;
+       struct group *group;
 
        DEBUG_2("file_data_new: '%s' %d", path_utf8, disable_sidecars);
 
@@ -429,8 +433,32 @@ static FileData *file_data_new(const gchar *path_utf8, struct stat *st, gboolean
        fd->ref = 1;
        fd->magick = FD_MAGICK;
        fd->exifdate = 0;
-       fd->rating = 0;
+       fd->rating = STAR_RATING_NOT_READ;
        fd->format_class = filter_file_get_class(path_utf8);
+       fd->page_num = 0;
+       fd->page_total = 0;
+
+       user = getpwuid(st->st_uid);
+       if (!user)
+               {
+               fd->owner = g_strdup_printf("%u", st->st_uid);
+               }
+       else
+               {
+               fd->owner = g_strdup(user->pw_name);
+               }
+
+       group = getgrgid(st->st_gid);
+       if (!group)
+               {
+               fd->group = g_strdup_printf("%u", st->st_gid);
+               }
+       else
+               {
+               fd->group = g_strdup(group->gr_name);
+               }
+
+       fd->sym_link = get_symbolic_link(path_utf8);
 
        if (disable_sidecars) fd->disable_grouping = TRUE;
 
@@ -477,7 +505,10 @@ void read_exif_time_data(FileData *file)
                return;
                }
 
-       file->exif = exif_read_fd(file);
+       if (!file->exif)
+               {
+               exif_read_fd(file);
+               }
 
        if (file->exif)
                {
@@ -512,7 +543,10 @@ void read_exif_time_digitized_data(FileData *file)
                return;
                }
 
-       file->exif = exif_read_fd(file);
+       if (!file->exif)
+               {
+               exif_read_fd(file);
+               }
 
        if (file->exif)
                {
@@ -539,6 +573,22 @@ void read_exif_time_digitized_data(FileData *file)
                }
 }
 
+void read_rating_data(FileData *file)
+{
+       gchar *rating_str;
+
+       rating_str = metadata_read_string(file, RATING_KEY, METADATA_PLAIN);
+       if (rating_str)
+               {
+               file->rating = atoi(rating_str);
+               g_free(rating_str);
+               }
+       else
+               {
+               file->rating = 0;
+               }
+}
+
 void set_exif_time_data(GList *files)
 {
        DEBUG_1("%s set_exif_time_data: ...", get_exec_time());
@@ -663,7 +713,9 @@ static void file_data_free(FileData *fd)
        g_free(fd->extended_extension);
        if (fd->thumb_pixbuf) g_object_unref(fd->thumb_pixbuf);
        histmap_free(fd->histmap);
-
+       g_free(fd->owner);
+       g_free(fd->group);
+       g_free(fd->sym_link);
        g_assert(fd->sidecar_files == NULL); /* sidecar files must be freed before calling this */
 
        file_data_change_info_free(NULL, fd);
@@ -671,7 +723,7 @@ static void file_data_free(FileData *fd)
 }
 
 /**
- * \brief Checks if the FileData is referenced
+ * @brief Checks if the FileData is referenced
  *
  * Checks the refcount and whether the FileData is locked.
  */
@@ -681,7 +733,7 @@ static gboolean file_data_check_has_ref(FileData *fd)
 }
 
 /**
- * \brief Consider freeing a FileData.
+ * @brief Consider freeing a FileData.
  *
  * This function will free a FileData and its children provided that neither its parent nor it has
  * a positive refcount, and provided that neither is locked.
@@ -749,7 +801,7 @@ void file_data_unref(FileData *fd)
 }
 
 /**
- * \brief Lock the FileData in memory.
+ * @brief Lock the FileData in memory.
  *
  * This allows the caller to prevent a FileData from being freed, even after its refcount is zero.
  * This is intended to be used in cases where a FileData _should_ stay in memory as an optimization,
@@ -771,7 +823,7 @@ void file_data_lock(FileData *fd)
 }
 
 /**
- * \brief Reset the maintain-FileData-in-memory lock
+ * @brief Reset the maintain-FileData-in-memory lock
  *
  * This again allows the FileData to be freed when its refcount drops to zero.  Automatically frees
  * the FileData if its refcount is already zero (which will happen if the lock is the only thing
@@ -790,9 +842,9 @@ void file_data_unlock(FileData *fd)
 }
 
 /**
- * \brief Lock all of the FileDatas in the provided list
+ * @brief Lock all of the FileDatas in the provided list
  *
- * \see file_data_lock(FileData)
+ * @see file_data_lock(#FileData)
  */
 void file_data_lock_list(GList *list)
 {
@@ -808,9 +860,9 @@ void file_data_lock_list(GList *list)
 }
 
 /**
- * \brief Unlock all of the FileDatas in the provided list
+ * @brief Unlock all of the FileDatas in the provided list
  *
- * \see file_data_unlock(FileData)
+ * @see #file_data_unlock(#FileData)
  */
 void file_data_unlock_list(GList *list)
 {
@@ -1161,18 +1213,6 @@ GList *filelist_insert_sort_full(GList *list, gpointer data, SortType method, gb
 
 GList *filelist_sort(GList *list, SortType method, gboolean ascend)
 {
-       if (method == SORT_EXIFTIME)
-               {
-               set_exif_time_data(list);
-               }
-       if (method == SORT_EXIFTIMEDIGITIZED)
-               {
-               set_exif_time_digitized_data(list);
-               }
-       if (method == SORT_RATING)
-               {
-               set_rating_data(list);
-               }
        return filelist_sort_full(list, method, ascend, (GCompareFunc) filelist_sort_file_cb);
 }
 
@@ -1599,6 +1639,33 @@ static void filelist_recursive_append(GList **list, GList *dirs)
                }
 }
 
+static void filelist_recursive_append_full(GList **list, GList *dirs, SortType method, gboolean ascend)
+{
+       GList *work;
+
+       work = dirs;
+       while (work)
+               {
+               FileData *fd = (FileData *)(work->data);
+               GList *f;
+               GList *d;
+
+               if (filelist_read(fd, &f, &d))
+                       {
+                       f = filelist_filter(f, FALSE);
+                       f = filelist_sort_full(f, method, ascend, (GCompareFunc) filelist_sort_file_cb);
+                       *list = g_list_concat(*list, f);
+
+                       d = filelist_filter(d, TRUE);
+                       d = filelist_sort_path(d);
+                       filelist_recursive_append_full(list, d, method, ascend);
+                       filelist_free(d);
+                       }
+
+               work = work->next;
+               }
+}
+
 GList *filelist_recursive(FileData *dir_fd)
 {
        GList *list;
@@ -1616,6 +1683,23 @@ GList *filelist_recursive(FileData *dir_fd)
        return list;
 }
 
+GList *filelist_recursive_full(FileData *dir_fd, SortType method, gboolean ascend)
+{
+       GList *list;
+       GList *d;
+
+       if (!filelist_read(dir_fd, &list, &d)) return NULL;
+       list = filelist_filter(list, FALSE);
+       list = filelist_sort_full(list, method, ascend, (GCompareFunc) filelist_sort_file_cb);
+
+       d = filelist_filter(d, TRUE);
+       d = filelist_sort_path(d);
+       filelist_recursive_append_full(&list, d, method, ascend);
+       filelist_free(d);
+
+       return list;
+}
+
 /*
  *-----------------------------------------------------------------------------
  * file modification support
@@ -1783,6 +1867,73 @@ GList *file_data_filter_marks_list(GList *list, guint filter)
        return list;
 }
 
+gboolean file_data_filter_file_filter(FileData *fd, GRegex *filter)
+{
+       return g_regex_match(filter, fd->name, 0, NULL);
+}
+
+GList *file_data_filter_file_filter_list(GList *list, GRegex *filter)
+{
+       GList *work;
+
+       work = list;
+       while (work)
+               {
+               FileData *fd = work->data;
+               GList *link = work;
+               work = work->next;
+
+               if (!file_data_filter_file_filter(fd, filter))
+                       {
+                       list = g_list_remove_link(list, link);
+                       file_data_unref(fd);
+                       g_list_free(link);
+                       }
+               }
+
+       return list;
+}
+
+static gboolean file_data_filter_class(FileData *fd, guint filter)
+{
+       gint i;
+
+       for (i = 0; i < FILE_FORMAT_CLASSES; i++)
+               {
+               if (filter & (1 << i))
+                       {
+                       if ((FileFormatClass)i == filter_file_get_class(fd->path))
+                               {
+                               return TRUE;
+                               }
+                       }
+               }
+
+       return FALSE;
+}
+
+GList *file_data_filter_class_list(GList *list, guint filter)
+{
+       GList *work;
+
+       work = list;
+       while (work)
+               {
+               FileData *fd = work->data;
+               GList *link = work;
+               work = work->next;
+
+               if (!file_data_filter_class(fd, filter))
+                       {
+                       list = g_list_remove_link(list, link);
+                       file_data_unref(fd);
+                       g_list_free(link);
+                       }
+               }
+
+       return list;
+}
+
 static void file_data_notify_mark_func(gpointer key, gpointer value, gpointer user_data)
 {
        FileData *fd = value;
@@ -1876,7 +2027,7 @@ gchar *file_data_sc_list_to_string(FileData *fd)
    COPY
    MOVE   - path is changed, name may be changed too
    RENAME - path remains unchanged, name is changed
-            extension should remain (FIXME should we allow editing extension? it will make problems wth grouping)
+            extension should remain (FIXME should we allow editing extension? it will make problems with grouping)
            sidecar names are changed too, extensions are not changed
    DELETE
    UPDATE - file size, date or grouping has been changed
@@ -2516,7 +2667,7 @@ gint file_data_verify_ci(FileData *fd, GList *list)
                        }
                else
                        {
-                       if (fd->change->type != FILEDATA_CHANGE_UNSPECIFIED) /* FIXME this is now needed for running editors */
+                       if (fd->change->type != FILEDATA_CHANGE_UNSPECIFIED) /** @FIXME this is now needed for running editors */
                                {
                                ret |= CHANGE_WARN_SAME;
                                DEBUG_1("Change checked: source and destination are the same: %s -> %s", fd->path, fd->change->dest);
@@ -2852,7 +3003,7 @@ gboolean file_data_apply_ci(FileData *fd)
 {
        FileDataChangeType type = fd->change->type;
 
-       /* FIXME delete ?*/
+       /** @FIXME delete ?*/
        if (type == FILEDATA_CHANGE_MOVE || type == FILEDATA_CHANGE_RENAME)
                {
                DEBUG_1("planned change: applying %s -> %s", fd->change->dest, fd->path);
@@ -2863,7 +3014,8 @@ gboolean file_data_apply_ci(FileData *fd)
                        /* this change overwrites another file which is already known to other modules
                           renaming fd would create duplicate FileData structure
                           the best thing we can do is nothing
-                          FIXME: maybe we could copy stuff like marks
+                       */
+                       /**  @FIXME maybe we could copy stuff like marks
                        */
                        DEBUG_1("can't rename fd, target exists %s -> %s", fd->change->dest, fd->path);
                        }
@@ -2939,7 +3091,7 @@ GList *file_data_process_groups_in_selection(GList *list, gboolean ungroup, GLis
                }
 
        /* remove sidecars from the list,
-          they can be still acessed via main_fd->sidecar_files */
+          they can be still accessed via main_fd->sidecar_files */
        work = list;
        while (work)
                {
@@ -2967,8 +3119,8 @@ GList *file_data_process_groups_in_selection(GList *list, gboolean ungroup, GLis
  * notify other modules about the change described by FileDataChangeInfo
  */
 
-/* might use file_maint_ functions for now, later it should be changed to a system of callbacks
-   FIXME do we need the ignore_list? It looks like a workaround for ineffective
+/* might use file_maint_ functions for now, later it should be changed to a system of callbacks */
+/** @FIXME do we need the ignore_list? It looks like a workaround for ineffective
    implementation in view_file_list.c */
 
 
@@ -3212,7 +3364,7 @@ gboolean marks_list_load(const gchar *path)
                        marks_value = strtok(NULL, ",");
                        if (isfile(file_path))
                                {
-                               FileData *fd = file_data_new_group(file_path);
+                               FileData *fd = file_data_new_no_grouping(file_path);
                                file_data_ref(fd);
                                gint n = 0;
                                while (n <= 9)
@@ -3289,4 +3441,49 @@ void marks_clear_all()
 {
        g_hash_table_foreach(file_data_pool, marks_clear, NULL);
 }
+
+void file_data_set_page_num(FileData *fd, gint page_num)
+{
+       if (fd->page_total > 1 && page_num < 0)
+               {
+               fd->page_num = fd->page_total - 1;
+               }
+       else if (fd->page_total > 1 && page_num <= fd->page_total)
+               {
+               fd->page_num = page_num - 1;
+               }
+       else
+               {
+               fd->page_num = 0;
+               }
+       file_data_send_notification(fd, NOTIFY_REREAD);
+}
+
+void file_data_inc_page_num(FileData *fd)
+{
+       if (fd->page_total > 0 && fd->page_num < fd->page_total - 1)
+               {
+               fd->page_num = fd->page_num + 1;
+               }
+       else if (fd->page_total == 0)
+               {
+               fd->page_num = fd->page_num + 1;
+               }
+       file_data_send_notification(fd, NOTIFY_REREAD);
+}
+
+void file_data_dec_page_num(FileData *fd)
+{
+       if (fd->page_num > 0)
+               {
+               fd->page_num = fd->page_num - 1;
+               }
+       file_data_send_notification(fd, NOTIFY_REREAD);
+}
+
+void file_data_set_page_total(FileData *fd, gint page_total)
+{
+       fd->page_total = page_total;
+}
+
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */