Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
duplicate.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2015-2016, 2019-2022 Aldric Renaudin.
4 Copyright (C) 2018-2019 Matthieu Moy.
5 Copyright (C) 2018-2021 Pascal Obry.
6 Copyright (C) 2018 rawfiner.
7 Copyright (C) 2019-2020, 2022-2023, 2025-2026 Aurélien PIERRE.
8 Copyright (C) 2019 Edgardo Hoszowski.
9 Copyright (C) 2019-2020 Philippe Weyland.
10 Copyright (C) 2020 Chris Elston.
11 Copyright (C) 2020-2022 Diederik Ter Rahe.
12 Copyright (C) 2020 Hanno Schwalm.
13 Copyright (C) 2020 Hubert Kowalski.
14 Copyright (C) 2020 Marco.
15 Copyright (C) 2020 Mark-64.
16 Copyright (C) 2020, 2022 Nicolas Auffray.
17 Copyright (C) 2021 Fabio Heer.
18 Copyright (C) 2021 Ralf Brown.
19 Copyright (C) 2022 Martin Bařinka.
20 Copyright (C) 2023 Alynx Zhou.
21
22 darktable is free software: you can redistribute it and/or modify
23 it under the terms of the GNU General Public License as published by
24 the Free Software Foundation, either version 3 of the License, or
25 (at your option) any later version.
26
27 darktable is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU General Public License for more details.
31
32 You should have received a copy of the GNU General Public License
33 along with darktable. If not, see <http://www.gnu.org/licenses/>.
34*/
35
36#include "common/collection.h"
37#include "common/darktable.h"
38#include "common/debug.h"
39#include "common/history.h"
40#include "common/metadata.h"
41#include "common/selection.h"
42#include "common/styles.h"
43#include "control/conf.h"
44#include "control/control.h"
45#include "develop/develop.h"
47#include "dtgtk/thumbnail.h"
48
49#include "gui/gtk.h"
50#include "gui/styles.h"
51#include "libs/lib.h"
52
53DT_MODULE(1)
54
55static sqlite3_stmt *_duplicate_versions_stmt = NULL;
56
57typedef struct dt_lib_duplicate_t
58{
60 int32_t imgid; // duplicate currently held under mouse press, UNKNOWN_IMAGE if none
61 dt_dev_snapshot_t preview; // hold-to-preview render + pan/zoom-synced crop cache, see develop/dev_snapshot.h
62 int32_t preview_cached_imgid; // which imgid `preview` currently holds, UNKNOWN_IMAGE if none
63
64 GList *thumbs;
66
67const char *name(struct dt_lib_module_t *self)
68{
69 return _("Duplicates");
70}
71
72const char **views(dt_lib_module_t *self)
73{
74 static const char *v[] = {"darkroom", NULL};
75 return v;
76}
77
82
84{
85 return 850;
86}
87
88static void _lib_duplicate_init_callback(gpointer instance, dt_lib_module_t *self);
89
90static gboolean _lib_duplicate_caption_out_callback(GtkWidget *widget, GdkEvent *event, dt_lib_module_t *self)
91{
92 const int32_t imgid = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget),"imgid"));
93
94 // we write the content of the textbox to the caption field
95 dt_metadata_set(imgid, "Xmp.darktable.version_name", gtk_entry_get_text(GTK_ENTRY(widget)), FALSE);
97
98 return FALSE;
99}
100
101static void _lib_duplicate_delete(GtkButton *button, dt_lib_module_t *self)
102{
104 const int32_t imgid = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button), "imgid"));
105
106 if(imgid == darktable.develop->image_storage.id)
107 {
108 // we find the duplicate image to show now
109 for(GList *l = d->thumbs; l; l = g_list_next(l))
110 {
111 dt_thumbnail_t *thumb = (dt_thumbnail_t *)l->data;
112 if(thumb->info.id == imgid)
113 {
114 GList *l2 = g_list_next(l);
115 if(IS_NULL_PTR(l2)) l2 = g_list_previous(l);
116 if(l2)
117 {
118 dt_thumbnail_t *th2 = (dt_thumbnail_t *)l2->data;
120 th2->info.id);
121 break;
122 }
123 }
124 }
125 }
126
127 // and we remove the image
130 g_list_prepend(NULL, GINT_TO_POINTER(imgid)));
131}
132
133static gboolean _lib_duplicate_thumb_press_callback(GtkWidget *widget, GdkEventButton *event, dt_lib_module_t *self)
134{
135 if(event->button == 1 && event->type == GDK_BUTTON_PRESS)
136 {
138 if(IS_NULL_PTR(dev)) return FALSE;
139
141 const int32_t imgid = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "imgid"));
142 if(imgid <= 0) return FALSE;
143
144 // Render once per duplicate and keep it around for the panel's lifetime -- re-pressing the
145 // same thumbnail is then instant. The first press on a given duplicate still pays for a full
146 // pipeline run (same cost as the "take snapshot" button in libs/snapshots.c), so show the
147 // same busy-cursor feedback while it's in flight.
148 if(d->preview_cached_imgid != imgid)
149 {
151 const gboolean ok = dt_dev_snapshot_capture(&d->preview, imgid, 1.0f, NULL, NULL, -1);
153 d->preview_cached_imgid = ok ? imgid : UNKNOWN_IMAGE;
154 }
155
156 d->imgid = (d->preview_cached_imgid == imgid) ? imgid : UNKNOWN_IMAGE;
158 return TRUE;
159 }
160 return FALSE;
161}
162
163// Cancels the hold-to-preview, whether triggered by releasing the button or by the pointer
164// leaving the thumbnail while still held -- see the two signals this is connected to below.
165static gboolean _lib_duplicate_thumb_revert_callback(GtkWidget *widget, GdkEvent *event, dt_lib_module_t *self)
166{
167 // thumb->widget (the event box this is connected to) is not a single window: it contains
168 // several unconditionally-shown child event boxes/drawing areas of its own (w_image,
169 // w_top_eb, w_bottom_eb in dtgtk/thumbnail.c), each with their own GdkWindow. Moving the
170 // pointer between those, while still inside the thumbnail's visible bounds, crosses a child
171 // window boundary and fires a leave-notify on the parent too (detail == GDK_NOTIFY_INFERIOR).
172 // Only a crossing to a window that is NOT a descendant is an actual "left the thumbnail".
173 if(event->type == GDK_LEAVE_NOTIFY && event->crossing.detail == GDK_NOTIFY_INFERIOR) return FALSE;
174
176
177 d->imgid = UNKNOWN_IMAGE;
179
180 return FALSE;
181}
182
183/* while a duplicate thumbnail is held, show it full-frame in the center view instead of the
184 image currently being edited, matching the live pan/zoom -- released on button-up. */
185void gui_post_expose(dt_lib_module_t *self, cairo_t *cri, int32_t width, int32_t height, int32_t pointerx,
186 int32_t pointery)
187{
189 if(IS_NULL_PTR(d) || d->imgid <= 0 || d->preview_cached_imgid != d->imgid) return;
190
192 float image_box[4] = { 0.0f };
194 if(image_box[2] <= 0.0f || image_box[3] <= 0.0f) return;
195
196 dt_dev_snapshot_draw(&d->preview, cri, dev, width, height, image_box[0], image_box[1], image_box[2],
197 image_box[3]);
198}
199
200void view_leave(struct dt_lib_module_t *self, struct dt_view_t *old_view, struct dt_view_t *new_view)
201{
202 // we leave the view. Let's destroy the cached preview if any
204 dt_dev_snapshot_clear(&d->preview);
205 d->preview_cached_imgid = UNKNOWN_IMAGE;
206}
207
208static void _thumb_remove(gpointer user_data)
209{
210 dt_thumbnail_t *thumb = (dt_thumbnail_t *)user_data;
211 if(IS_NULL_PTR(thumb)) return;
212
213 GtkWidget *parent = NULL;
214 if(!IS_NULL_PTR(thumb->w_main)) parent = gtk_widget_get_parent(thumb->w_main);
215 if(!IS_NULL_PTR(parent) && GTK_IS_CONTAINER(parent) && !IS_NULL_PTR(thumb->w_main))
216 gtk_container_remove(GTK_CONTAINER(parent), thumb->w_main);
217
219}
220
221static void _lib_duplicate_init_callback(gpointer instance, dt_lib_module_t *self)
222{
223 //block signals to avoid concurrent calls
225
227
228 d->imgid = UNKNOWN_IMAGE;
229 // we drop the cached preview if any -- it belongs to a thumb the list rebuild below is about
230 // to tear down, and stays keyed to a specific imgid that may no longer even be a duplicate of
231 // whatever image this panel now describes
232 dt_dev_snapshot_clear(&d->preview);
233 d->preview_cached_imgid = UNKNOWN_IMAGE;
234 // we drop all the thumbs
235 g_list_free_full(d->thumbs, _thumb_remove);
236 d->thumbs = NULL;
237 // and the other widgets too
238 dt_gui_container_destroy_children(GTK_CONTAINER(d->duplicate_box));
239 // retrieve all the versions of the image
240 sqlite3_stmt *stmt;
242
243 int count = 0;
244
245 // we get a summarize of all versions of the image
246 // clang-format off
248 {
250 "SELECT i.version, i.id, m.value"
251 " FROM images AS i"
252 " LEFT JOIN meta_data AS m ON m.id = i.id AND m.key = ?3"
253 " WHERE film_id = ?1 AND filename = ?2"
254 " ORDER BY i.version",
255 -1, &_duplicate_versions_stmt, NULL);
256 }
258 sqlite3_reset(stmt);
259 sqlite3_clear_bindings(stmt);
260 // clang-format on
262 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, dev->image_storage.filename, -1, SQLITE_TRANSIENT);
264
265 GtkWidget *bt = NULL;
266
267 while(sqlite3_step(stmt) == SQLITE_ROW)
268 {
269 GtkWidget *hb = gtk_grid_new();
270 const int32_t imgid = sqlite3_column_int(stmt, 1);
271 dt_image_t info = { 0 };
272 info.id = imgid;
274
275 thumb->disable_mouseover = TRUE;
276 thumb->disable_actions = TRUE;
278 dt_thumbnail_set_mouseover(thumb, imgid == dev->image_storage.id);
279 dt_thumbnail_update_selection(thumb, imgid == dev->image_storage.id);
280 gtk_widget_queue_draw(thumb->widget);
281
282 if(imgid != dev->image_storage.id)
283 {
284 g_object_set_data(G_OBJECT(thumb->widget), "imgid", GINT_TO_POINTER(imgid));
285 g_signal_connect(G_OBJECT(thumb->widget), "button-press-event",
286 G_CALLBACK(_lib_duplicate_thumb_press_callback), self);
287 g_signal_connect(G_OBJECT(thumb->widget), "button-release-event",
288 G_CALLBACK(_lib_duplicate_thumb_revert_callback), self);
289 // GTK keeps delivering crossing events to the widget that holds the implicit pointer
290 // grab, so dragging off the thumbnail without releasing is caught here the same way.
291 gtk_widget_add_events(thumb->widget, GDK_LEAVE_NOTIFY_MASK);
292 g_signal_connect(G_OBJECT(thumb->widget), "leave-notify-event",
293 G_CALLBACK(_lib_duplicate_thumb_revert_callback), self);
294 }
295
296 gchar chl[256];
297 gchar *path = (gchar *)sqlite3_column_text(stmt, 2);
298 g_snprintf(chl, sizeof(chl), "%d", sqlite3_column_int(stmt, 0));
299
300 GtkWidget *tb = gtk_entry_new();
302 if(path) gtk_entry_set_text(GTK_ENTRY(tb), path);
303 gtk_entry_set_width_chars(GTK_ENTRY(tb), 0);
304 gtk_widget_set_hexpand(tb, TRUE);
305 g_object_set_data (G_OBJECT(tb), "imgid", GINT_TO_POINTER(imgid));
306 gtk_widget_add_events(tb, GDK_FOCUS_CHANGE_MASK);
307 g_signal_connect(G_OBJECT(tb), "focus-out-event", G_CALLBACK(_lib_duplicate_caption_out_callback), self);
308 GtkWidget *lb = gtk_label_new(chl);
309 gtk_widget_set_hexpand(lb, TRUE);
311 // gtk_widget_set_halign(bt, GTK_ALIGN_END);
312 g_object_set_data(G_OBJECT(bt), "imgid", GINT_TO_POINTER(imgid));
313 g_signal_connect(G_OBJECT(bt), "clicked", G_CALLBACK(_lib_duplicate_delete), self);
314
315 gtk_grid_attach(GTK_GRID(hb), thumb->widget, 0, 0, 1, 2);
316 gtk_grid_attach(GTK_GRID(hb), bt, 2, 0, 1, 1);
317 gtk_grid_attach(GTK_GRID(hb), lb, 1, 0, 1, 1);
318 gtk_grid_attach(GTK_GRID(hb), tb, 1, 1, 2, 1);
319
320 // Can't use gtk_widget_show_all here or the buttons of the thumbnail will show too
321 gtk_widget_show(thumb->widget);
322 gtk_widget_show(hb);
323 gtk_widget_show(lb);
324 gtk_widget_show(tb);
325 gtk_box_pack_start(GTK_BOX(d->duplicate_box), hb, FALSE, FALSE, 0);
326 d->thumbs = g_list_append(d->thumbs, thumb);
327 count++;
328 }
329 sqlite3_reset(stmt);
330
331 gtk_widget_show(d->duplicate_box);
332
333 // we have a single image, do not allow it to be removed so hide last bt
334 if(count==1)
335 {
336 gtk_widget_set_sensitive(bt, FALSE);
337 gtk_widget_set_visible(bt, FALSE);
338 }
339
341}
342
343static void _lib_duplicate_collection_changed(gpointer instance, dt_collection_change_t query_change,
344 dt_collection_properties_t changed_property, gpointer imgs, int next,
345 dt_lib_module_t *self)
346{
347 _lib_duplicate_init_callback(instance, self);
348}
349
350static void _lib_duplicate_preview_updated_callback(gpointer instance, dt_lib_module_t *self)
351{
353 gtk_widget_queue_draw (d->duplicate_box);
355}
356
357
359{
360 /* initialize ui widgets */
362 self->data = (void *)d;
363
364 d->imgid = UNKNOWN_IMAGE;
365 d->preview_cached_imgid = UNKNOWN_IMAGE;
366
367 self->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING);
368 dt_gui_add_class(self->widget, "dt_duplicate_ui");
369
370 d->duplicate_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING);
371
372 GtkWidget *hb = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, DT_GUI_BOX_SPACING);
373
374 /* add duplicate list and buttonbox to widget */
375 gtk_box_pack_start(GTK_BOX(self->widget),
376 dt_ui_scroll_wrap(d->duplicate_box, 1, "plugins/darkroom/duplicate/windowheight",
378 gtk_box_pack_start(GTK_BOX(self->widget), hb, TRUE, TRUE, 0);
379
380 gtk_widget_show_all(self->widget);
381
385 G_CALLBACK(_lib_duplicate_collection_changed), self);
388}
389
391{
392 if(IS_NULL_PTR(self->data)) return;
394
398
399 if(!IS_NULL_PTR(d))
400 {
401 dt_dev_snapshot_clear(&d->preview);
402
403 g_list_free_full(d->thumbs, _thumb_remove);
404 d->thumbs = NULL;
405 dt_gui_container_destroy_children(GTK_CONTAINER(d->duplicate_box));
406 }
407
409 {
410 sqlite3_finalize(_duplicate_versions_stmt);
412 }
413
414 dt_free(self->data);
415}
416
417// clang-format off
418// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
419// vim: shiftwidth=2 expandtab tabstop=2 cindent
420// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
421// clang-format on
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
int width
Definition bilateral.h:1
int height
Definition bilateral.h:1
GtkWidget * dtgtk_button_new(DTGTKCairoPaintIconFunc paint, gint paintflags, void *paintdata)
Definition button.c:134
void dt_collection_update_query(const dt_collection_t *collection, dt_collection_change_t query_change, dt_collection_properties_t changed_property, GList *list)
dt_collection_properties_t
Definition collection.h:107
@ DT_COLLECTION_PROP_UNDEF
Definition collection.h:142
dt_collection_change_t
Definition collection.h:147
@ DT_COLLECTION_CHANGE_RELOAD
Definition collection.h:151
void dt_metadata_set(const int32_t imgid, const char *key, const char *value, const gboolean undo_on)
char * name
void dt_control_queue_redraw_center()
request redraw of center window. This redraws the center view within a gdk critical section to preven...
Definition control.c:877
void dt_control_change_cursor_by_name_and_flush(const char *curs_str)
Apply a named cursor immediatelly and flush display updates for immediate feedback.
Definition control.c:326
void dt_control_commit_cursor()
Definition control.c:334
void dt_control_save_xmp(const int32_t imgid)
void dt_control_delete_image(int32_t imgid)
darktable_t darktable
Definition darktable.c:183
#define UNKNOWN_IMAGE
Definition darktable.h:194
#define DT_MODULE(MODVER)
Definition darktable.h:140
#define dt_free(ptr)
Definition darktable.h:478
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition darktable.h:293
sqlite3 * dt_database_get(const dt_database_t *db)
Definition database.c:3653
#define DT_DEBUG_SQLITE3_PREPARE_V2(a, b, c, d, e)
Definition debug.h:107
#define DT_DEBUG_SQLITE3_BIND_TEXT(a, b, c, d, e)
Definition debug.h:118
#define DT_DEBUG_SQLITE3_BIND_INT(a, b, c)
Definition debug.h:115
void dt_dev_snapshot_draw(dt_dev_snapshot_t *snap, cairo_t *cri, struct dt_develop_t *dev, int32_t width, int32_t height, double clip_x, double clip_y, double clip_w, double clip_h)
void dt_dev_snapshot_clear(dt_dev_snapshot_t *snap)
gboolean dt_dev_snapshot_capture(dt_dev_snapshot_t *snap, int32_t imgid, float scale, GList *history_override, GList *iop_order_override, int32_t history_end_override)
void dt_dev_get_image_box_in_widget(const dt_develop_t *dev, const int32_t width, const int32_t height, float *box)
Get the displayed image rectangle in darkroom widget coordinates.
Definition develop.c:1801
void dtgtk_cairo_paint_remove(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
static sqlite3_stmt * _duplicate_versions_stmt
Definition duplicate.c:55
static void _lib_duplicate_preview_updated_callback(gpointer instance, dt_lib_module_t *self)
Definition duplicate.c:350
static void _lib_duplicate_collection_changed(gpointer instance, dt_collection_change_t query_change, dt_collection_properties_t changed_property, gpointer imgs, int next, dt_lib_module_t *self)
Definition duplicate.c:343
static gboolean _lib_duplicate_thumb_revert_callback(GtkWidget *widget, GdkEvent *event, dt_lib_module_t *self)
Definition duplicate.c:165
static void _lib_duplicate_init_callback(gpointer instance, dt_lib_module_t *self)
Definition duplicate.c:221
void gui_cleanup(dt_lib_module_t *self)
Definition duplicate.c:390
static void _lib_duplicate_delete(GtkButton *button, dt_lib_module_t *self)
Definition duplicate.c:101
static void _thumb_remove(gpointer user_data)
Definition duplicate.c:208
uint32_t container(dt_lib_module_t *self)
Definition duplicate.c:78
void view_leave(struct dt_lib_module_t *self, struct dt_view_t *old_view, struct dt_view_t *new_view)
Definition duplicate.c:200
void gui_init(dt_lib_module_t *self)
Definition duplicate.c:358
int position()
Definition duplicate.c:83
const char ** views(dt_lib_module_t *self)
Definition duplicate.c:72
static gboolean _lib_duplicate_thumb_press_callback(GtkWidget *widget, GdkEventButton *event, dt_lib_module_t *self)
Definition duplicate.c:133
void gui_post_expose(dt_lib_module_t *self, cairo_t *cri, int32_t width, int32_t height, int32_t pointerx, int32_t pointery)
Definition duplicate.c:185
static gboolean _lib_duplicate_caption_out_callback(GtkWidget *widget, GdkEvent *event, dt_lib_module_t *self)
Definition duplicate.c:90
void dt_gui_container_destroy_children(GtkContainer *container)
Definition gtk.c:3151
GtkWidget * dt_ui_scroll_wrap(GtkWidget *w, gint min_size, char *config_str, dt_ui_resize_mode_t mode)
Wrap a scrollable content widget in a recessed, vertically resizable scrolled window.
Definition gtk.c:2945
void dt_accels_disconnect_on_text_input(GtkWidget *widget)
Disconnects accels when a text or search entry gets the focus, and reconnects them when it looses it....
Definition gtk.c:3473
void dt_gui_add_class(GtkWidget *widget, const gchar *class_name)
Definition gtk.c:133
@ DT_UI_RESIZE_DYNAMIC
Definition gtk.h:266
#define DT_GUI_BOX_SPACING
Definition gtk.h:109
#define DT_PIXEL_APPLY_DPI(value)
Definition gtk.h:90
const float l2
const float v
@ DT_METADATA_XMP_VERSION_NAME
Definition metadata.h:50
void dt_control_signal_unblock_by_func(const struct dt_control_signal_t *ctlsig, GCallback cb, gpointer user_data)
Definition signal.c:502
void dt_control_signal_block_by_func(const struct dt_control_signal_t *ctlsig, GCallback cb, gpointer user_data)
Definition signal.c:497
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
Definition signal.h:387
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
Definition signal.h:366
@ DT_SIGNAL_DEVELOP_INITIALIZE
This signal is raised when darktable.develop is initialized.
Definition signal.h:169
@ DT_SIGNAL_VIEWMANAGER_THUMBTABLE_ACTIVATE
Definition signal.h:95
@ DT_SIGNAL_DEVELOP_IMAGE_CHANGED
This signal is raised when image is changed in darkroom.
Definition signal.h:221
@ DT_SIGNAL_DEVELOP_PREVIEW_PIPE_FINISHED
This signal is raised when develop preview pipe process is finished no param, no returned value.
Definition signal.h:174
@ DT_SIGNAL_COLLECTION_CHANGED
This signal is raised when collection changed. To avoid leaking the list, dt_collection_t is connecte...
Definition signal.h:122
#define DT_DEBUG_CONTROL_SIGNAL_CONNECT(ctlsig, signal, cb, user_data)
Definition signal.h:376
struct _GtkWidget GtkWidget
Definition splash.h:29
struct dt_collection_t * collection
Definition darktable.h:809
const struct dt_database_t * db
Definition darktable.h:807
struct dt_control_signal_t * signals
Definition darktable.h:802
struct dt_develop_t * develop
Definition darktable.h:798
dt_image_t image_storage
Definition develop.h:259
int32_t film_id
Definition image.h:319
char filename[DT_MAX_FILENAME_LEN]
Definition image.h:304
int32_t id
Definition image.h:319
int32_t preview_cached_imgid
Definition duplicate.c:62
dt_dev_snapshot_t preview
Definition duplicate.c:61
GtkWidget * duplicate_box
Definition duplicate.c:59
GModule *void * data
Definition lib.h:80
GtkWidget * widget
Definition lib.h:84
gboolean disable_actions
Definition thumbnail.h:104
dt_image_t info
Definition thumbnail.h:76
GtkWidget * w_main
Definition thumbnail.h:80
GtkWidget * widget
Definition thumbnail.h:79
gboolean disable_mouseover
Definition thumbnail.h:103
dt_thumbnail_t * dt_thumbnail_new(int rowid, dt_thumbnail_overlay_t over, dt_thumbtable_t *table, dt_image_t *info)
Definition thumbnail.c:1346
void dt_thumbnail_set_mouseover(dt_thumbnail_t *thumb, gboolean over)
Definition thumbnail.c:1631
int dt_thumbnail_destroy(dt_thumbnail_t *thumb)
Definition thumbnail.c:1374
void dt_thumbnail_update_selection(dt_thumbnail_t *thumb, gboolean selected)
Definition thumbnail.c:878
void dt_thumbnail_resize(dt_thumbnail_t *thumb, int width, int height)
Definition thumbnail.c:1561
@ DT_THUMBNAIL_OVERLAYS_NONE
Definition thumbnail.h:59
@ DT_UI_CONTAINER_PANEL_LEFT_CENTER