clang-tidy: readability-duplicate-include
[geeqie.git] / src / bar-rating.cc
1 /*
2  * Copyright (C) 2004 John Ellis
3  * Copyright (C) 2008 - 2022 The Geeqie Team
4  *
5  * Author: Colin Clark
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include "main.h"
23 #include "bar-rating.h"
24
25 #include "bar.h"
26 #include "filedata.h"
27 #include "metadata.h"
28 #include "rcfile.h"
29 #include "ui-misc.h"
30
31 /**
32  * @file
33  * Rating values as specified by: \n
34  * Adobe XMP Basic namespace \n
35  * -1 Rejected \n
36  * 0 Unrated \n
37  * 1 to 5 Rating value
38  */
39
40 struct PaneRatingData
41 {
42         PaneData pane;
43         GtkWidget *widget;
44         GtkWidget *radio_button_first;
45         FileData *fd;
46         GtkCheckButton *rating_buttons[7];
47 };
48
49 static void bar_pane_rating_update(PaneRatingData *prd)
50 {
51         guint64 rating;
52
53         rating = metadata_read_int(prd->fd, RATING_KEY, 0) + 1;
54
55         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(prd->rating_buttons[rating]), TRUE);
56 }
57
58 static void bar_pane_rating_set_fd(GtkWidget *pane, FileData *fd)
59 {
60         PaneRatingData *prd;
61
62         prd = static_cast<PaneRatingData *>(g_object_get_data(G_OBJECT(pane), "pane_data"));
63         if (!prd) return;
64
65         file_data_unref(prd->fd);
66         prd->fd = file_data_ref(fd);
67
68         bar_pane_rating_update(prd);
69 }
70
71 static void bar_pane_rating_write_config(GtkWidget *pane, GString *outstr, gint indent)
72 {
73         PaneRatingData *prd;
74
75         prd = static_cast<PaneRatingData *>(g_object_get_data(G_OBJECT(pane), "pane_data"));
76         if (!prd) return;
77
78         WRITE_NL();
79         WRITE_STRING("<pane_rating ");
80         write_char_option(outstr, indent, "id", prd->pane.id);
81         write_char_option(outstr, indent, "title", gtk_label_get_text(GTK_LABEL(prd->pane.title)));
82         WRITE_BOOL(prd->pane, expanded);
83         WRITE_STRING("/>");
84 }
85
86 static void bar_pane_rating_notify_cb(FileData *fd, NotifyType type, gpointer data)
87 {
88         auto prd = static_cast<PaneRatingData *>(data);
89
90         if ((type & (NOTIFY_REREAD | NOTIFY_CHANGE | NOTIFY_HISTMAP | NOTIFY_PIXBUF)) && fd == prd->fd)
91                 {
92                 DEBUG_1("Notify pane_rating: %s %04x", fd->path, type);
93                 bar_pane_rating_update(prd);
94                 }
95 }
96
97 static void bar_pane_rating_destroy(GtkWidget *, gpointer data)
98 {
99         auto prd = static_cast<PaneRatingData *>(data);
100
101         file_data_unregister_notify_func(bar_pane_rating_notify_cb, prd);
102         file_data_unref(prd->fd);
103         g_free(prd->pane.id);
104         g_free(prd);
105 }
106
107 static void bar_pane_rating_selected_cb(GtkCheckButton *checkbutton, gpointer data)
108 {
109         auto prd = static_cast<PaneRatingData *>(data);
110         gchar *rating;
111
112 #ifdef HAVE_GTK4
113         const gchar *rating_label;
114
115         rating_label = gtk_check_button_get_label(checkbutton);
116
117         if (g_strcmp0(rating_label, "Rejected") == 0)
118                 {
119                 rating = g_strdup("-1");
120                 }
121         else if (g_strcmp0(rating_label, "Unrated") == 0)
122                 {
123                 rating = g_strdup("0");
124                 }
125         else
126                 {
127                 rating = g_strdup(rating_label);
128                 }
129
130         metadata_write_string(prd->fd, RATING_KEY, rating);
131
132         g_free(rating);
133 #else
134         gint i;
135
136         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbutton)))
137                 {
138                 i = 0;
139                 while (i < 7)
140                         {
141                         if (prd->rating_buttons[i] == checkbutton)
142                                 {
143                                 rating = g_strdup_printf("%d",   i - 1 );
144                                 metadata_write_string(prd->fd, RATING_KEY, rating);
145                                 g_free(rating);
146                                 break;
147                                 }
148
149                         i++;
150                         }
151                 }
152 #endif
153 }
154
155 static GtkWidget *bar_pane_rating_new(const gchar *id, const gchar *title, gboolean expanded)
156 {
157         PaneRatingData *prd;
158         GtkWidget *radio_rejected;
159         GtkWidget *radio_unrated;
160         GtkWidget *radio_rating;
161         GtkWidget *row_1;
162         GtkWidget *row_2;
163         gint i;
164         gchar *i_str;
165
166         prd = g_new0(PaneRatingData, 1);
167
168         prd->pane.pane_set_fd = bar_pane_rating_set_fd;
169         prd->pane.pane_write_config = bar_pane_rating_write_config;
170         prd->pane.title = bar_pane_expander_title(title);
171         prd->pane.id = g_strdup(id);
172         prd->pane.type = PANE_RATING;
173
174         prd->pane.expanded = expanded;
175
176         prd->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
177
178         g_object_set_data(G_OBJECT(prd->widget), "pane_data", prd);
179         g_signal_connect(G_OBJECT(prd->widget), "destroy", G_CALLBACK(bar_pane_rating_destroy), prd);
180
181         row_1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, PREF_PAD_GAP);
182         gq_gtk_box_pack_start(GTK_BOX(prd->widget), row_1, FALSE, FALSE, 0);
183
184 #ifdef HAVE_GTK4
185         radio_rejected = gtk_check_button_new_with_label(_("Rejected"));
186 #else
187         radio_rejected = gtk_radio_button_new_with_label(nullptr, _("Rejected"));
188 #endif
189         gq_gtk_box_pack_start(GTK_BOX(row_1), radio_rejected, FALSE, FALSE, 0);
190         g_signal_connect(radio_rejected, "released", G_CALLBACK(bar_pane_rating_selected_cb), prd);
191         prd->rating_buttons[0] = GTK_CHECK_BUTTON(radio_rejected);
192
193 #ifdef HAVE_GTK4
194         radio_unrated = gtk_check_button_new_with_label(_("Unrated"));
195         gtk_check_button_set_group(GTK_CHECK_BUTTON(radio_unrated), GTK_CHECK_BUTTON(radio_rejected));
196 #else
197         radio_unrated = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio_rejected), _("Unrated"));
198 #endif
199         gq_gtk_box_pack_start(GTK_BOX(row_1), radio_unrated, FALSE, FALSE, 0);
200         g_signal_connect(radio_unrated, "released", G_CALLBACK(bar_pane_rating_selected_cb), prd);
201         prd->rating_buttons[1] = GTK_CHECK_BUTTON(radio_unrated);
202
203         row_2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, PREF_PAD_GAP);
204         gq_gtk_box_pack_start(GTK_BOX(prd->widget), row_2, FALSE, FALSE, 0);
205
206         i = 2;
207         while (i <= 6)
208                 {
209                 i_str = g_strdup_printf("%d", i - 1);
210
211 #ifdef HAVE_GTK4
212                 radio_rating = gtk_check_button_new_with_label(i_str);
213                 gtk_check_button_set_group(GTK_CHECK_BUTTON(radio_rating), GTK_CHECK_BUTTON(radio_rejected));
214 #else
215                 radio_rating = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio_rejected), i_str);
216 #endif
217                 g_signal_connect(radio_rating, "released", G_CALLBACK(bar_pane_rating_selected_cb), prd);
218
219                 gq_gtk_box_pack_start(GTK_BOX(row_2), radio_rating, FALSE, FALSE, 1);
220                 prd->rating_buttons[i ] = GTK_CHECK_BUTTON(radio_rating);
221
222                 g_free(i_str);
223                 i++;
224                 }
225
226         prd->radio_button_first = radio_rating;
227
228         gtk_widget_show(prd->widget);
229
230         file_data_register_notify_func(bar_pane_rating_notify_cb, prd, NOTIFY_PRIORITY_LOW);
231
232         return prd->widget;
233 }
234
235 GtkWidget *bar_pane_rating_new_from_config(const gchar **attribute_names, const gchar **attribute_values)
236 {
237         gchar *title = nullptr;
238         gchar *id = g_strdup("rating");
239         gboolean expanded = TRUE;
240         GtkWidget *ret;
241
242         while (*attribute_names)
243                 {
244                 const gchar *option = *attribute_names++;
245                 const gchar *value = *attribute_values++;
246
247                 if (READ_CHAR_FULL("id", id)) continue;
248                 if (READ_CHAR_FULL("title", title)) continue;
249                 if (READ_BOOL_FULL("expanded", expanded)) continue;
250
251                 log_printf("unknown attribute %s = %s\n", option, value);
252                 }
253
254         bar_pane_translate_title(PANE_RATING, id, &title);
255         ret = bar_pane_rating_new(id, title, expanded);
256
257         g_free(title);
258         g_free(id);
259         return ret;
260 }
261
262 void bar_pane_rating_update_from_config(GtkWidget *pane, const gchar **attribute_names, const gchar **attribute_values)
263 {
264         PaneRatingData *prd;
265         gchar *title = nullptr;
266
267         prd = static_cast<PaneRatingData *>(g_object_get_data(G_OBJECT(pane), "pane_data"));
268         if (!prd) return;
269
270         while (*attribute_names)
271                 {
272                 const gchar *option = *attribute_names++;
273                 const gchar *value = *attribute_values++;
274
275                 if (READ_CHAR_FULL("title", title)) continue;
276                 if (READ_CHAR_FULL("id", prd->pane.id)) continue;
277                 if (READ_BOOL_FULL("expanded", prd->pane.expanded)) continue;
278
279                 log_printf("unknown attribute %s = %s\n", option, value);
280                 }
281
282         bar_update_expander(pane);
283         bar_pane_rating_update(prd);
284 }
285 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */