From 16caaea569d62de28e03e2174d55b8ab93a0e7c8 Mon Sep 17 00:00:00 2001 From: Colin Clark Date: Tue, 12 Apr 2022 16:25:06 +0100 Subject: [PATCH] Change sidebar rating pane layout Change the sidebar Star Rating pane to use radio buttons. --- src/Makefile.am | 2 + src/bar.c | 4 +- src/bar.h | 3 +- src/bar_rating.c | 251 +++++++++++++++++++++++++++++++++++++++++++++++ src/bar_rating.h | 29 ++++++ src/rcfile.c | 15 +++ 6 files changed, 301 insertions(+), 3 deletions(-) create mode 100644 src/bar_rating.c create mode 100644 src/bar_rating.h diff --git a/src/Makefile.am b/src/Makefile.am index ec709bc0..15013f3a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -119,6 +119,8 @@ geeqie_SOURCES = \ bar_keywords.h \ bar_exif.c \ bar_exif.h \ + bar_rating.c \ + bar_rating.h \ bar_sort.c \ bar_sort.h \ cache.c \ diff --git a/src/bar.c b/src/bar.c index 11b41689..9d81b73c 100644 --- a/src/bar.c +++ b/src/bar.c @@ -98,7 +98,7 @@ static const gchar default_config_rating[] = "" " " " " -" " +" " " " " " ""; @@ -202,7 +202,7 @@ static const KnownPanes known_panes[] = { {PANE_COMMENT, "title", N_("Title"), default_config_title}, {PANE_KEYWORDS, "keywords", N_("Keywords"), default_config_keywords}, {PANE_COMMENT, "comment", N_("Comment"), default_config_comment}, - {PANE_COMMENT, "rating", N_("Rating"), default_config_rating}, + {PANE_RATING, "rating", N_("Star Rating"), default_config_rating}, {PANE_COMMENT, "headline", N_("Headline"), default_config_headline}, {PANE_EXIF, "exif", N_("Exif"), default_config_exif}, /* other pre-configured panes */ diff --git a/src/bar.h b/src/bar.h index 12b81d1c..6569122b 100644 --- a/src/bar.h +++ b/src/bar.h @@ -28,7 +28,8 @@ typedef enum { PANE_EXIF, PANE_HISTOGRAM, PANE_KEYWORDS, - PANE_GPS + PANE_GPS, + PANE_RATING } PaneType; typedef struct _PaneData PaneData; diff --git a/src/bar_rating.c b/src/bar_rating.c new file mode 100644 index 00000000..fdd23d08 --- /dev/null +++ b/src/bar_rating.c @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2004 John Ellis + * Copyright (C) 2008 - 2022 The Geeqie Team + * + * Author: Colin Clark + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "main.h" +#include "bar_rating.h" + +#include "bar.h" +#include "filedata.h" +#include "metadata.h" +#include "rcfile.h" +#include "ui_misc.h" + +/** + * @file + * Rating values as specified by: \n + * Adobe XMP Basic namespace \n + * -1 Rejected \n + * 0 Unrated \n + * 1 to 5 Rating value + */ + +typedef struct _PaneRatingData PaneRatingData; +struct _PaneRatingData +{ + PaneData pane; + GtkWidget *widget; + GtkWidget *radio_button_first; + FileData *fd; +}; + +static void bar_pane_rating_update(PaneRatingData *prd) +{ + guint64 rating; + GSList *list; + + rating = metadata_read_int(prd->fd, RATING_KEY, 0); + + list = gtk_radio_button_get_group(GTK_RADIO_BUTTON(prd->radio_button_first)); + + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_slist_nth_data(list, 5 - rating)), TRUE); +} + +static void bar_pane_rating_set_fd(GtkWidget *pane, FileData *fd) +{ + PaneRatingData *prd; + + prd = g_object_get_data(G_OBJECT(pane), "pane_data"); + if (!prd) return; + + file_data_unref(prd->fd); + prd->fd = file_data_ref(fd); + + bar_pane_rating_update(prd); +} + +static void bar_pane_rating_write_config(GtkWidget *pane, GString *outstr, gint indent) +{ + PaneRatingData *prd; + + prd = g_object_get_data(G_OBJECT(pane), "pane_data"); + if (!prd) return; + + WRITE_NL(); + WRITE_STRING("pane.id); + write_char_option(outstr, indent, "title", gtk_label_get_text(GTK_LABEL(prd->pane.title))); + WRITE_BOOL(prd->pane, expanded); + WRITE_STRING("/>"); +} + +static void bar_pane_rating_notify_cb(FileData *fd, NotifyType type, gpointer data) +{ + PaneRatingData *prd = data; + + if ((type & (NOTIFY_REREAD | NOTIFY_CHANGE | NOTIFY_HISTMAP | NOTIFY_PIXBUF)) && fd == prd->fd) + { + DEBUG_1("Notify pane_rating: %s %04x", fd->path, type); + bar_pane_rating_update(prd); + } +} + +static void bar_pane_rating_destroy(GtkWidget *widget, gpointer data) +{ + PaneRatingData *prd = data; + + file_data_unregister_notify_func(bar_pane_rating_notify_cb, prd); + file_data_unref(prd->fd); + g_free(prd->pane.id); + g_free(prd); +} + +static void bar_pane_rating_selected_cb(GtkToggleButton *togglebutton, gpointer data) +{ + PaneRatingData *prd = data; + GSList *list; + gint i; + gchar *rating; + + if (gtk_toggle_button_get_active(togglebutton)) + { + list = gtk_radio_button_get_group(GTK_RADIO_BUTTON(togglebutton)); + i = 0; + + while (list) + { + if (list->data == togglebutton) + { + rating = g_strdup_printf("%d", 5 - i); + metadata_write_string(prd->fd, RATING_KEY, rating); + g_free(rating); + break; + } + + i++; + list = list->next; + } + } +} + +static GtkWidget *bar_pane_rating_new(const gchar *id, const gchar *title, gboolean expanded) +{ + PaneRatingData *prd; + GtkWidget *radio_rejected; + GtkWidget *radio_unrated; + GtkWidget *radio_rating; + GtkWidget *row_1; + GtkWidget *row_2; + gint i; + gchar *i_str; + + prd = g_new0(PaneRatingData, 1); + + prd->pane.pane_set_fd = bar_pane_rating_set_fd; + prd->pane.pane_write_config = bar_pane_rating_write_config; + prd->pane.title = bar_pane_expander_title(title); + prd->pane.id = g_strdup(id); + prd->pane.type = PANE_RATING; + + prd->pane.expanded = expanded; + + prd->widget = gtk_vbox_new(FALSE, PREF_PAD_GAP); + + g_object_set_data(G_OBJECT(prd->widget), "pane_data", prd); + g_signal_connect(G_OBJECT(prd->widget), "destroy", G_CALLBACK(bar_pane_rating_destroy), prd); + + row_1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_pack_start(GTK_BOX(prd->widget), row_1, FALSE, FALSE, 0); + + radio_rejected = gtk_radio_button_new_with_label(NULL, _("Rejected")); + gtk_box_pack_start(GTK_BOX(row_1), radio_rejected, FALSE, FALSE, 0); + g_signal_connect(radio_rejected, "released", G_CALLBACK(bar_pane_rating_selected_cb), prd); + + radio_unrated = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio_rejected), _("Unrated")); + gtk_box_pack_start(GTK_BOX(row_1), radio_unrated, FALSE, FALSE, 0); + g_signal_connect(radio_unrated, "released", G_CALLBACK(bar_pane_rating_selected_cb), prd); + + row_2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_pack_start(GTK_BOX(prd->widget), row_2, FALSE, FALSE, 0); + + i = 1; + while (i <= 5) + { + i_str = g_strdup_printf("%d", i); + + radio_rating = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio_rejected), i_str); + g_signal_connect(radio_rating, "released", G_CALLBACK(bar_pane_rating_selected_cb), prd); + + gtk_box_pack_start(GTK_BOX(row_2), radio_rating, FALSE, FALSE, 1); + + g_free(i_str); + i++; + } + + prd->radio_button_first = radio_rating; + + gtk_widget_show(prd->widget); + + file_data_register_notify_func(bar_pane_rating_notify_cb, prd, NOTIFY_PRIORITY_LOW); + + return prd->widget; +} + +GtkWidget *bar_pane_rating_new_from_config(const gchar **attribute_names, const gchar **attribute_values) +{ + gchar *title = NULL; + gchar *id = g_strdup("rating"); + gboolean expanded = TRUE; + GtkWidget *ret; + + while (*attribute_names) + { + const gchar *option = *attribute_names++; + const gchar *value = *attribute_values++; + + if (READ_CHAR_FULL("id", id)) continue; + if (READ_CHAR_FULL("title", title)) continue; + if (READ_BOOL_FULL("expanded", expanded)) continue; + + log_printf("unknown attribute %s = %s\n", option, value); + } + + bar_pane_translate_title(PANE_RATING, id, &title); + ret = bar_pane_rating_new(id, title, expanded); + + g_free(title); + g_free(id); + return ret; +} + +void bar_pane_rating_update_from_config(GtkWidget *pane, const gchar **attribute_names, const gchar **attribute_values) +{ + PaneRatingData *prd; + gchar *title = NULL; + + prd = g_object_get_data(G_OBJECT(pane), "pane_data"); + if (!prd) return; + + while (*attribute_names) + { + const gchar *option = *attribute_names++; + const gchar *value = *attribute_values++; + + if (READ_CHAR_FULL("title", title)) continue; + if (READ_CHAR_FULL("id", prd->pane.id)) continue; + if (READ_BOOL_FULL("expanded", prd->pane.expanded)) continue; + + log_printf("unknown attribute %s = %s\n", option, value); + } + + bar_update_expander(pane); + bar_pane_rating_update(prd); +} +/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/bar_rating.h b/src/bar_rating.h new file mode 100644 index 00000000..63a7f014 --- /dev/null +++ b/src/bar_rating.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2004 John Ellis + * Copyright (C) 2008 - 2022 The Geeqie Team + * + * Author: Colin Clark + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef BAR_RATING_H +#define BAR_RATING_H + +GtkWidget *bar_pane_rating_new_from_config(const gchar **attribute_names, const gchar **attribute_values); +void bar_pane_rating_update_from_config(GtkWidget *pane, const gchar **attribute_names, const gchar **attribute_values); + +#endif +/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/rcfile.c b/src/rcfile.c index cc80f202..1e98e4cd 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -30,6 +30,7 @@ #include "bar_exif.h" #include "bar_histogram.h" #include "bar_keywords.h" +#include "bar_rating.h" #include "bar_sort.h" #include "editors.h" #include "filefilter.h" @@ -1436,6 +1437,20 @@ static void options_parse_bar(GQParserData *parser_data, GMarkupParseContext *co } options_parse_func_push(parser_data, options_parse_leaf, NULL, NULL); } + else if (g_ascii_strcasecmp(element_name, "pane_rating") == 0) + { + GtkWidget *pane = bar_find_pane_by_id(bar, PANE_RATING, options_get_id(attribute_names, attribute_values)); + if (pane) + { + bar_pane_rating_update_from_config(pane, attribute_names, attribute_values); + } + else + { + pane = bar_pane_rating_new_from_config(attribute_names, attribute_values); + bar_add(bar, pane); + } + options_parse_func_push(parser_data, options_parse_leaf, NULL, NULL); + } else if (g_ascii_strcasecmp(element_name, "pane_keywords") == 0) { GtkWidget *pane = bar_find_pane_by_id(bar, PANE_KEYWORDS, options_get_id(attribute_names, attribute_values)); -- 2.20.1