Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
ratings.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2011 Henrik Andersson.
4 Copyright (C) 2011, 2013-2014 johannes hanika.
5 Copyright (C) 2012 Richard Wonka.
6 Copyright (C) 2012-2014, 2016 Tobias Ellinghaus.
7 Copyright (C) 2013 José Carlos García Sogo.
8 Copyright (C) 2013 parafin.
9 Copyright (C) 2013, 2019-2021 Pascal Obry.
10 Copyright (C) 2014, 2016 Roman Lebedev.
11 Copyright (C) 2016 itinerarium.
12 Copyright (C) 2018 Rick Yorgason.
13 Copyright (C) 2019-2020 Heiko Bauke.
14 Copyright (C) 2019-2020 Philippe Weyland.
15 Copyright (C) 2020-2021 Aldric Renaudin.
16 Copyright (C) 2020 Chris Elston.
17 Copyright (C) 2021 Diederik Ter Rahe.
18 Copyright (C) 2021 Hubert Kowalski.
19 Copyright (C) 2021 Ralf Brown.
20 Copyright (C) 2022 Martin Bařinka.
21 Copyright (C) 2022 solarer.
22 Copyright (C) 2023, 2025 Aurélien PIERRE.
23
24 darktable is free software: you can redistribute it and/or modify
25 it under the terms of the GNU General Public License as published by
26 the Free Software Foundation, either version 3 of the License, or
27 (at your option) any later version.
28
29 darktable is distributed in the hope that it will be useful,
30 but WITHOUT ANY WARRANTY; without even the implied warranty of
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 GNU General Public License for more details.
33
34 You should have received a copy of the GNU General Public License
35 along with darktable. If not, see <http://www.gnu.org/licenses/>.
36*/
37#include "common/collection.h"
38#include "common/darktable.h"
39#include "common/debug.h"
40#include "common/image_cache.h"
41#include "common/ratings.h"
42#include "common/undo.h"
43#include "common/grouping.h"
44#include "views/view.h"
45#include "control/conf.h"
46#include "control/control.h"
47#include "gui/gtk.h"
48
49
50#define DT_RATINGS_UPGRADE -1
51#define DT_RATINGS_DOWNGRADE -2
52#define DT_RATINGS_REJECT -3
53#define DT_RATINGS_UNREJECT -4
54
55typedef struct dt_undo_ratings_t
56{
57 int32_t imgid;
58 int before;
59 int after;
61
62char *dt_ratings_get_name(const int rating)
63{
64 switch(rating)
65 {
66 case 0:
67 return _("empty");
68 case 1:
69 return _("1 star");
70 case 2:
71 return _("2 stars");
72 case 3:
73 return _("3 stars");
74 case 4:
75 return _("4 stars");
76 case 5:
77 return _("5 stars");
78 case 6:
79 return _("rejected");
80 default:
81 return _("unknown/invalid");
82 }
83}
84
85int dt_ratings_get(const int32_t imgid)
86{
87 int stars = 0;
89 if(image)
90 {
91 if(image->flags & DT_IMAGE_REJECTED)
92 stars = DT_VIEW_REJECT;
93 else
94 stars = DT_VIEW_RATINGS_MASK & image->flags;
96 }
97 return stars;
98}
99
100static void _ratings_apply_to_image(const int32_t imgid, const int rating)
101{
102 int new_rating = rating;
104
105 if(image)
106 {
107 // apply or remove rejection
108 if(new_rating == DT_RATINGS_REJECT)
109 image->flags |= DT_IMAGE_REJECTED;
110 else if(new_rating == DT_RATINGS_UNREJECT)
111 image->flags &= ~DT_IMAGE_REJECTED;
112 else
113 {
114 image->flags = (image->flags & ~(DT_IMAGE_REJECTED | DT_VIEW_RATINGS_MASK))
115 | (DT_VIEW_RATINGS_MASK & new_rating);
116 }
117 // synch through:
119 }
120 else
121 {
123 }
124}
125
126static void _pop_undo(gpointer user_data, dt_undo_type_t type, dt_undo_data_t data, dt_undo_action_t action, GList **imgs)
127{
128 if(type == DT_UNDO_RATINGS)
129 {
130 for(GList *list = (GList *)data; list; list = g_list_next(list))
131 {
133 _ratings_apply_to_image(ratings->imgid, (action == DT_ACTION_UNDO) ? ratings->before : ratings->after);
134 *imgs = g_list_prepend(*imgs, GINT_TO_POINTER(ratings->imgid));
135 }
137 }
138}
139
140static void _ratings_undo_data_free(gpointer data)
141{
142 GList *l = (GList *)data;
143 g_list_free(l);
144 l = NULL;
145}
146
147// wrapper that does some precalculation to deal with toggle effects and rating increase/decrease
148static void _ratings_apply(GList *imgs, const int rating, GList **undo, const gboolean undo_on)
149{
150 // REJECTION and SINGLE_STAR rating can have a toggle effect
151 // but we only toggle off if ALL images have that rating
152 // so we need to check every image first
153 gboolean toggle = FALSE;
154
155 if(rating == DT_VIEW_REJECT)
156 {
157 toggle = TRUE;
158 for(const GList *images = g_list_first(imgs); images; images = g_list_next(images))
159 {
160 if(dt_ratings_get(GPOINTER_TO_INT(images->data)) != DT_VIEW_REJECT)
161 {
162 toggle = FALSE;
163 break;
164 }
165 }
166 }
167
168 for(const GList *images = g_list_first(imgs); images; images = g_list_next(images))
169 {
170 const int32_t image_id = GPOINTER_TO_INT(images->data);
171 const int old_rating = dt_ratings_get(image_id);
172 if(undo_on)
173 {
174 dt_undo_ratings_t *undoratings = (dt_undo_ratings_t *)malloc(sizeof(dt_undo_ratings_t));
175 undoratings->imgid = image_id;
176 undoratings->before = old_rating;
177 undoratings->after = rating;
178 *undo = g_list_append(*undo, undoratings);
179 }
180
181 int new_rating = rating;
182 // do not 'DT_RATINGS_UPGRADE' or 'DT_RATINGS_UPGRADE' if image was rejected
183 if(old_rating == DT_VIEW_REJECT && rating < DT_VIEW_DESERT)
184 new_rating = DT_VIEW_REJECT;
185 else if(rating == DT_RATINGS_UPGRADE)
186 new_rating = MIN(DT_VIEW_STAR_5, old_rating + 1);
187 else if(rating == DT_RATINGS_DOWNGRADE)
188 new_rating = MAX(DT_VIEW_DESERT, old_rating - 1);
189 else if(rating == DT_VIEW_STAR_1 && toggle)
190 new_rating = DT_VIEW_DESERT;
191 else if(rating == DT_VIEW_REJECT && toggle)
192 new_rating = DT_RATINGS_UNREJECT;
193 else if(rating == DT_VIEW_REJECT && !toggle)
194 new_rating = DT_RATINGS_REJECT;
195
196 _ratings_apply_to_image(image_id, new_rating);
197 }
198}
199
200void dt_ratings_apply_on_list(GList *img, const int rating, const gboolean undo_on)
201{
202 if(img)
203 {
204 GList *undo = NULL;
206
207 _ratings_apply(img, rating, &undo, undo_on);
208
209 if(undo_on)
210 {
213 }
215 dt_toast_log(_("Rating set to %s for %i image(s)"), dt_ratings_get_name(rating), g_list_length(img));
216 }
217}
218
219void dt_ratings_apply_on_image(const int32_t imgid, const int rating, const gboolean single_star_toggle,
220 const gboolean undo_on, const gboolean group_on)
221{
222 GList *imgs = NULL;
223 int new_rating = rating;
224
225 if(imgid > 0) imgs = g_list_prepend(imgs, GINT_TO_POINTER(imgid));
226
227 if(imgs)
228 {
229 GList *undo = NULL;
231 if(group_on) dt_grouping_add_grouped_images(&imgs);
232
233 if(!g_list_shorter_than(imgs, 2)) // pop up a toast if rating multiple images at once
234 {
235 const guint count = g_list_length(imgs);
236 if(new_rating == DT_VIEW_REJECT)
237 dt_control_log(ngettext("rejecting %d image", "rejecting %d images", count), count);
238 else
239 dt_control_log(ngettext("applying rating %d to %d image", "applying rating %d to %d images", count),
240 new_rating, count);
241 }
242
243 _ratings_apply(imgs, new_rating, &undo, undo_on);
244
245 if(undo_on)
246 {
249 }
250 g_list_free(imgs);
251 imgs = NULL;
252 }
253 else
254 dt_control_log(_("no images selected to apply rating"));
255}
256
257// clang-format off
258// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
259// vim: shiftwidth=2 expandtab tabstop=2 cindent
260// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
261// clang-format on
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
void dt_collection_hint_message(const dt_collection_t *collection)
int type
void dt_toast_log(const char *msg,...)
Definition control.c:808
void dt_control_log(const char *msg,...)
Definition control.c:761
darktable_t darktable
Definition darktable.c:181
static gboolean g_list_shorter_than(const GList *list, unsigned len)
Definition darktable.h:939
const dt_collection_filter_flag_t ratings[7]
Definition filter.c:448
void dt_grouping_add_grouped_images(GList **images)
Definition grouping.c:170
@ DT_IMAGE_REJECTED
Definition image.h:100
void dt_image_cache_read_release(dt_image_cache_t *cache, const dt_image_t *img)
dt_image_t * dt_image_cache_get(dt_image_cache_t *cache, const int32_t imgid, char mode)
void dt_image_cache_write_release(dt_image_cache_t *cache, dt_image_t *img, dt_image_cache_write_mode_t mode)
@ DT_IMAGE_CACHE_RELAXED
Definition image_cache.h:51
@ DT_IMAGE_CACHE_SAFE
Definition image_cache.h:49
#define DT_RATINGS_UPGRADE
Definition ratings.c:50
static void _pop_undo(gpointer user_data, dt_undo_type_t type, dt_undo_data_t data, dt_undo_action_t action, GList **imgs)
Definition ratings.c:126
#define DT_RATINGS_DOWNGRADE
Definition ratings.c:51
int dt_ratings_get(const int32_t imgid)
Definition ratings.c:85
void dt_ratings_apply_on_image(const int32_t imgid, const int rating, const gboolean single_star_toggle, const gboolean undo_on, const gboolean group_on)
Definition ratings.c:219
static void _ratings_apply(GList *imgs, const int rating, GList **undo, const gboolean undo_on)
Definition ratings.c:148
static void _ratings_apply_to_image(const int32_t imgid, const int rating)
Definition ratings.c:100
static void _ratings_undo_data_free(gpointer data)
Definition ratings.c:140
#define DT_RATINGS_UNREJECT
Definition ratings.c:53
#define DT_RATINGS_REJECT
Definition ratings.c:52
void dt_ratings_apply_on_list(GList *img, const int rating, const gboolean undo_on)
Definition ratings.c:200
char * dt_ratings_get_name(const int rating)
Definition ratings.c:62
#define DT_VIEW_RATINGS_MASK
Definition ratings.h:41
struct dt_undo_t * undo
Definition darktable.h:787
struct dt_collection_t * collection
Definition darktable.h:781
struct dt_image_cache_t * image_cache
Definition darktable.h:777
int32_t flags
Definition image.h:319
int32_t imgid
Definition ratings.c:57
#define MIN(a, b)
Definition thinplate.c:32
#define MAX(a, b)
Definition thinplate.c:29
void dt_undo_end_group(dt_undo_t *self)
Definition undo.c:149
void dt_undo_start_group(dt_undo_t *self, dt_undo_type_t type)
Definition undo.c:134
void dt_undo_record(dt_undo_t *self, gpointer user_data, dt_undo_type_t type, dt_undo_data_t data, void(*undo)(gpointer user_data, dt_undo_type_t type, dt_undo_data_t item, dt_undo_action_t action, GList **imgs), void(*free_data)(gpointer data))
Definition undo.c:163
dt_undo_type_t
Definition undo.h:39
@ DT_UNDO_RATINGS
Definition undo.h:44
void * dt_undo_data_t
Definition undo.h:67
dt_undo_action_t
Definition undo.h:62
@ DT_ACTION_UNDO
Definition undo.h:63
@ DT_VIEW_REJECT
Definition view.h:174
@ DT_VIEW_STAR_5
Definition view.h:173
@ DT_VIEW_STAR_1
Definition view.h:169
@ DT_VIEW_DESERT
Definition view.h:168