Fix #1089: Sync xmp:Rating across all sidecar images
[geeqie.git] / src / collect-table.cc
index 1a79b1f..0d3016f 100644 (file)
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include "main.h"
 #include "collect-table.h"
 
+#include <cstddef>
+#include <utility>
+
+#include <cairo.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gio/gio.h>
+#include <glib-object.h>
+
 #include "cellrenderericon.h"
 #include "collect-dlg.h"
 #include "collect-io.h"
+#include "collect.h"
+#include "compat.h"
+#include "debug.h"
 #include "dnd.h"
 #include "dupe.h"
 #include "filedata.h"
 #include "img-view.h"
-#include "layout.h"
+#include "intl.h"
 #include "layout-image.h"
+#include "layout.h"
+#include "main-defines.h"
 #include "menu.h"
 #include "metadata.h"
-#include "pixbuf-util.h"
+#include "misc.h"
+#include "options.h"
 #include "print.h"
-#include "utilops.h"
+#include "typedefs.h"
 #include "ui-fileops.h"
 #include "ui-menu.h"
 #include "ui-tree-edit.h"
 #include "uri-utils.h"
+#include "utilops.h"
 #include "view-file.h"
 
+namespace
+{
+
 /* between these, the icon width is increased by thumb_max_width / 2 */
-#define THUMB_MIN_ICON_WIDTH 128
-#define THUMB_MAX_ICON_WIDTH 150
+constexpr gint THUMB_MIN_ICON_WIDTH = 128;
+constexpr gint THUMB_MAX_ICON_WIDTH = 150;
 
-#define COLLECT_TABLE_MAX_COLUMNS 32
-#define THUMB_BORDER_PADDING 2
+constexpr gint COLLECT_TABLE_MAX_COLUMNS = 32;
 
-#define COLLECT_TABLE_TIP_DELAY 500
-#define COLLECT_TABLE_TIP_DELAY_PATH (COLLECT_TABLE_TIP_DELAY * 1.7)
+constexpr gint THUMB_BORDER_PADDING = 2;
 
+constexpr gint COLLECT_TABLE_TIP_DELAY = 500;
+constexpr gint COLLECT_TABLE_TIP_DELAY_PATH = 850;
 
 enum {
        CTABLE_COLUMN_POINTER = 0,
        CTABLE_COLUMN_COUNT
 };
 
-#define INFO_SELECTED(x) (x->flag_mask & SELECTION_SELECTED)
+struct ColumnData
+{
+       CollectTable *ct;
+       gint number;
+};
+
+inline gboolean info_selected(const CollectInfo *info)
+{
+       return info->flag_mask & SELECTION_SELECTED;
+}
 
+} // namespace
 
 static void collection_table_populate_at_new_size(CollectTable *ct, gint w, gint h, gboolean force);
 
@@ -123,7 +150,8 @@ static gboolean collection_table_find_position(CollectTable *ct, CollectInfo *in
 static gboolean collection_table_find_iter(CollectTable *ct, CollectInfo *info, GtkTreeIter *iter, gint *column)
 {
        GtkTreeModel *store;
-       gint row, col;
+       gint row;
+       gint col;
 
        store = gtk_tree_view_get_model(GTK_TREE_VIEW(ct->listview));
        if (!collection_table_find_position(ct, info, &row, &col)) return FALSE;
@@ -422,7 +450,7 @@ static void collection_table_select_invert_all(CollectTable *ct)
                {
                auto info = static_cast<CollectInfo *>(work->data);
 
-               if (INFO_SELECTED(info))
+               if (info_selected(info))
                        {
                        collection_table_selection_remove(ct, info, SELECTION_SELECTED, nullptr);
                        }
@@ -446,7 +474,7 @@ void collection_table_select(CollectTable *ct, CollectInfo *info)
 {
        ct->prev_selection = info;
 
-       if (!info || INFO_SELECTED(info)) return;
+       if (!info || info_selected(info)) return;
 
        ct->selection = g_list_append(ct->selection, info);
        collection_table_selection_add(ct, info, SELECTION_SELECTED, nullptr);
@@ -458,7 +486,7 @@ static void collection_table_unselect(CollectTable *ct, CollectInfo *info)
 {
        ct->prev_selection = info;
 
-       if (!info || !INFO_SELECTED(info) ) return;
+       if (!info || !info_selected(info) ) return;
 
        ct->selection = g_list_remove(ct->selection, info);
        collection_table_selection_remove(ct, info, SELECTION_SELECTED, nullptr);
@@ -480,10 +508,12 @@ static void collection_table_select_util(CollectTable *ct, CollectInfo *info, gb
 
 static void collection_table_select_region_util(CollectTable *ct, CollectInfo *start, CollectInfo *end, gboolean select)
 {
-       gint row1, col1;
-       gint row2, col2;
-       gint t;
-       gint i, j;
+       gint row1;
+       gint col1;
+       gint row2;
+       gint col2;
+       gint i;
+       gint j;
 
        if (!collection_table_find_position(ct, start, &row1, &col1) ||
            !collection_table_find_position(ct, end, &row2, &col2) ) return;
@@ -518,15 +548,11 @@ static void collection_table_select_region_util(CollectTable *ct, CollectInfo *s
 
        if (row2 < row1)
                {
-               t = row1;
-               row1 = row2;
-               row2 = t;
+               std::swap(row1, row2);
                }
        if (col2 < col1)
                {
-               t = col1;
-               col1 = col2;
-               col2 = t;
+               std::swap(col1, col2);
                }
 
        DEBUG_1("table: %d x %d to %d x %d", row1, col1, row2, col2);
@@ -560,7 +586,8 @@ static GList *collection_table_get_list(CollectTable *ct)
 static void tip_show(CollectTable *ct)
 {
        GtkWidget *label;
-       gint x, y;
+       gint x;
+       gint y;
        GdkDisplay *display;
        GdkSeat *seat;
        GdkDevice *device;
@@ -582,7 +609,7 @@ static void tip_show(CollectTable *ct)
        label = gtk_label_new(ct->show_text ? ct->tip_info->fd->path : ct->tip_info->fd->name);
 
        g_object_set_data(G_OBJECT(ct->tip_window), "tip_label", label);
-       gtk_container_add(GTK_CONTAINER(ct->tip_window), label);
+       gq_gtk_container_add(GTK_WIDGET(ct->tip_window), label);
        gtk_widget_show(label);
 
        display = gdk_display_get_default();
@@ -591,13 +618,13 @@ static void tip_show(CollectTable *ct)
        gdk_device_get_position(device, nullptr, &x, &y);
 
        if (!gtk_widget_get_realized(ct->tip_window)) gtk_widget_realize(ct->tip_window);
-       gtk_window_move(GTK_WINDOW(ct->tip_window), x + 16, y + 16);
+       gq_gtk_window_move(GTK_WINDOW(ct->tip_window), x + 16, y + 16);
        gtk_widget_show(ct->tip_window);
 }
 
 static void tip_hide(CollectTable *ct)
 {
-       if (ct->tip_window) gtk_widget_destroy(ct->tip_window);
+       if (ct->tip_window) gq_gtk_widget_destroy(ct->tip_window);
        ct->tip_window = nullptr;
 }
 
@@ -647,10 +674,11 @@ static void tip_update(CollectTable *ct, CollectInfo *info)
 
        if (ct->tip_window)
                {
-               gint x, y;
+               gint x;
+               gint y;
                gdk_device_get_position(device, nullptr, &x, &y);
 
-               gtk_window_move(GTK_WINDOW(ct->tip_window), x + 16, y + 16);
+               gq_gtk_window_move(GTK_WINDOW(ct->tip_window), x + 16, y + 16);
 
                if (info != ct->tip_info)
                        {
@@ -702,7 +730,7 @@ static GList *collection_table_popup_file_list(CollectTable *ct)
 {
        if (!ct->click_info) return nullptr;
 
-       if (INFO_SELECTED(ct->click_info))
+       if (info_selected(ct->click_info))
                {
                return collection_table_selection_get_list(ct);
                }
@@ -854,7 +882,7 @@ static void collection_table_popup_remove_cb(GtkWidget *, gpointer data)
 
        if (!ct->click_info) return;
 
-       if (INFO_SELECTED(ct->click_info))
+       if (info_selected(ct->click_info))
                {
                list = g_list_copy(ct->selection);
                }
@@ -1070,7 +1098,8 @@ static GtkWidget *collection_table_popup_menu(CollectTable *ct, gboolean over_ic
 void collection_table_set_focus(CollectTable *ct, CollectInfo *info)
 {
        GtkTreeIter iter;
-       gint row, col;
+       gint row;
+       gint col;
 
        if (g_list_find(ct->cd->list, ct->focus_info))
                {
@@ -1285,7 +1314,7 @@ static gboolean collection_table_press_key_cb(GtkWidget *widget, GdkEventKey *ev
                                ct->click_info = info;
                                if (event->state & GDK_CONTROL_MASK)
                                        {
-                                       collection_table_select_util(ct, info, !INFO_SELECTED(info));
+                                       collection_table_select_util(ct, info, !info_selected(info));
                                        }
                                else
                                        {
@@ -1478,11 +1507,11 @@ static void collection_table_insert_marker(CollectTable *ct, CollectInfo *info,
        gboolean after = FALSE;
        GdkRectangle cell;
        GdkWindow *parent;
-       gint x_parent, y_parent;
+       gint x_parent;
+       gint y_parent;
        GError *error = nullptr;
        GInputStream *in_stream;
        GdkPixbuf *pb;
-       gchar *path;
 
        parent = gtk_widget_get_window(gtk_widget_get_toplevel(ct->listview));
        gdk_window_get_position(parent, &x_parent, &y_parent);
@@ -1505,10 +1534,7 @@ static void collection_table_insert_marker(CollectTable *ct, CollectInfo *info,
                GdkWindowAttr attributes;
                gint attributes_mask;
 
-               path = g_build_filename(GQ_RESOURCE_PATH_ICONS, "gq-marker.xpm", NULL);
-               in_stream = g_resources_open_stream(path, G_RESOURCE_LOOKUP_FLAGS_NONE, &error);
-               g_free(path);
-
+               in_stream = g_resources_open_stream(GQ_RESOURCE_PATH_ICONS "/gq-marker.xpm", G_RESOURCE_LOOKUP_FLAGS_NONE, &error);
                pb = gdk_pixbuf_new_from_stream(in_stream, nullptr, &error);
                g_object_unref(in_stream);
 
@@ -1553,8 +1579,10 @@ static void collection_table_insert_marker(CollectTable *ct, CollectInfo *info,
 
        if (info)
                {
-               gint x, y;
-               gint w, h;
+               gint x;
+               gint y;
+               gint w;
+               gint h;
 
                w = gdk_window_get_width(ct->marker_window);
                h = gdk_window_get_height(ct->marker_window);
@@ -1610,8 +1638,10 @@ static gboolean collection_table_auto_scroll_idle_cb(gpointer data)
 {
        auto ct = static_cast<CollectTable *>(data);
        GdkWindow *window;
-       gint x, y;
-       gint w, h;
+       gint x;
+       gint y;
+       gint w;
+       gint h;
        GdkSeat *seat;
        GdkDevice *device;
 
@@ -1744,7 +1774,7 @@ static gboolean collection_table_release_cb(GtkWidget *, GdkEventButton *bevent,
 
                if (bevent->state & GDK_CONTROL_MASK)
                        {
-                       gboolean select = !INFO_SELECTED(info);
+                       gboolean select = !info_selected(info);
 
                        if ((bevent->state & GDK_SHIFT_MASK) && ct->prev_selection)
                                {
@@ -1773,7 +1803,7 @@ static gboolean collection_table_release_cb(GtkWidget *, GdkEventButton *bevent,
        else if (bevent->button == MOUSE_BUTTON_MIDDLE &&
                 info && ct->click_info == info)
                {
-               collection_table_select_util(ct, info, !INFO_SELECTED(info));
+               collection_table_select_util(ct, info, !info_selected(info));
                }
 
        return TRUE;
@@ -1916,19 +1946,17 @@ static void collection_table_sync(CollectTable *ct)
        GtkTreeModel *store;
        GtkTreeIter iter;
        GList *work;
-       gint r, c;
+       gint r;
 
        store = gtk_tree_view_get_model(GTK_TREE_VIEW(ct->listview));
 
        r = -1;
-       c = 0;
 
        work = ct->cd->list;
        while (work)
                {
                GList *list;
                r++;
-               c = 0;
                if (gtk_tree_model_iter_nth_child(store, &iter, nullptr, r))
                        {
                        gtk_tree_model_get(store, &iter, CTABLE_COLUMN_POINTER, &list, -1);
@@ -1946,7 +1974,6 @@ static void collection_table_sync(CollectTable *ct)
                                {
                                info = static_cast<CollectInfo *>(work->data);
                                work = work->next;
-                               c++;
                                }
                        else
                                {
@@ -2097,7 +2124,8 @@ static void collection_table_move_by_info_list(CollectTable *ct, GList *info_lis
 void collection_table_file_update(CollectTable *ct, CollectInfo *info)
 {
        GtkTreeIter iter;
-       gint row, col;
+       gint row;
+       gint col;
        gdouble value;
 
        if (!info)
@@ -2142,7 +2170,7 @@ void collection_table_file_insert(CollectTable *ct, CollectInfo *)
 
 void collection_table_file_remove(CollectTable *ct, CollectInfo *ci)
 {
-       if (ci && INFO_SELECTED(ci))
+       if (ci && info_selected(ci))
                {
                ct->selection = g_list_remove(ct->selection, ci);
                }
@@ -2277,7 +2305,7 @@ static void collection_table_dnd_get(GtkWidget *, GdkDragContext *,
 
        if (!ct->click_info) return;
 
-       selected = INFO_SELECTED(ct->click_info);
+       selected = info_selected(ct->click_info);
 
        switch (info)
                {
@@ -2409,7 +2437,7 @@ static void collection_table_dnd_begin(GtkWidget *widget, GdkDragContext *contex
                {
                gint items;
 
-               if (INFO_SELECTED(ct->click_info))
+               if (info_selected(ct->click_info))
                        items = g_list_length(ct->selection);
                else
                        items = 1;
@@ -2474,24 +2502,18 @@ static void collection_table_dnd_init(CollectTable *ct)
  *-----------------------------------------------------------------------------
  */
 
-struct ColumnData
-{
-       CollectTable *ct;
-       gint number;
-};
-
 static void collection_table_cell_data_cb(GtkTreeViewColumn *, GtkCellRenderer *cell,
                                          GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
 {
        auto cd = static_cast<ColumnData *>(data);
-       CollectTable *ct;
-       GtkStyle *style;
-       GList *list;
        CollectInfo *info;
-       GdkColor color_fg;
-       GdkColor color_bg;
-       gchar *star_rating = nullptr;
+       CollectTable *ct;
        gchar *display_text = nullptr;
+       gchar *star_rating = nullptr;
+       GdkRGBA color_bg;
+       GdkRGBA color_fg;
+       GList *list;
+       GtkStyle *style;
 
        ct = cd->ct;
 
@@ -2509,13 +2531,13 @@ static void collection_table_cell_data_cb(GtkTreeViewColumn *, GtkCellRenderer *
        style = gtk_widget_get_style(ct->listview);
        if (info && (info->flag_mask & SELECTION_SELECTED) )
                {
-               memcpy(&color_fg, &style->text[GTK_STATE_SELECTED], sizeof(color_fg));
-               memcpy(&color_bg, &style->base[GTK_STATE_SELECTED], sizeof(color_bg));
+               convert_gdkcolor_to_gdkrgba(&style->text[GTK_STATE_SELECTED], &color_fg);
+               convert_gdkcolor_to_gdkrgba(&style->base[GTK_STATE_SELECTED], &color_bg);
                }
        else
                {
-               memcpy(&color_fg, &style->text[GTK_STATE_NORMAL], sizeof(color_fg));
-               memcpy(&color_bg, &style->base[GTK_STATE_NORMAL], sizeof(color_bg));
+               convert_gdkcolor_to_gdkrgba(&style->text[GTK_STATE_NORMAL], &color_fg);
+               convert_gdkcolor_to_gdkrgba(&style->base[GTK_STATE_NORMAL], &color_bg);
                }
 
        if (info && (info->flag_mask & SELECTION_PRELIGHT))
@@ -2562,9 +2584,9 @@ static void collection_table_cell_data_cb(GtkTreeViewColumn *, GtkCellRenderer *
                        {
                        g_object_set(cell,      "pixbuf", info->pixbuf,
                                                "text",  display_text,
-                                               "cell-background-gdk", &color_bg,
+                                               "cell-background-rgba", &color_bg,
                                                "cell-background-set", TRUE,
-                                               "foreground-gdk", &color_fg,
+                                               "foreground-rgba", &color_fg,
                                                "foreground-set", TRUE,
                                                "has-focus", (ct->focus_info == info), NULL);
                        }
@@ -2634,7 +2656,7 @@ static void collection_table_destroy(GtkWidget *, gpointer data)
                {
                g_signal_handlers_disconnect_matched(G_OBJECT(ct->popup), G_SIGNAL_MATCH_DATA,
                                                     0, 0, nullptr, nullptr, ct);
-               gtk_widget_destroy(ct->popup);
+               gq_gtk_widget_destroy(ct->popup);
                }
 
        if (ct->sync_idle_id) g_source_remove(ct->sync_idle_id);
@@ -2665,8 +2687,8 @@ CollectTable *collection_table_new(CollectionData *cd)
        ct->show_text = options->show_icon_names;
        ct->show_stars = options->show_star_rating;
 
-       ct->scrolled = gtk_scrolled_window_new(nullptr, nullptr);
-       gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(ct->scrolled), GTK_SHADOW_IN);
+       ct->scrolled = gq_gtk_scrolled_window_new(nullptr, nullptr);
+       gq_gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(ct->scrolled), GTK_SHADOW_IN);
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ct->scrolled),
                                       GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 
@@ -2697,7 +2719,7 @@ CollectTable *collection_table_new(CollectionData *cd)
        g_signal_connect(G_OBJECT(ct->listview), "key_press_event",
                         G_CALLBACK(collection_table_press_key_cb), ct);
 
-       gtk_container_add(GTK_CONTAINER(ct->scrolled), ct->listview);
+       gq_gtk_container_add(GTK_WIDGET(ct->scrolled), ct->listview);
        gtk_widget_show(ct->listview);
 
        collection_table_dnd_init(ct);