Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
edit.c
Go to the documentation of this file.
1/*
2 This file is part of the Ansel project.
3 Copyright (C) 2023-2025 Aurélien PIERRE.
4 Copyright (C) 2023 Luca Zulberti.
5
6 Ansel is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 Ansel is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Ansel. If not, see <http://www.gnu.org/licenses/>.
18*/
19#include "common/darktable.h"
20#include "gui/actions/menu.h"
21#include "gui/preferences.h"
22#include "common/undo.h"
23#include "common/selection.h"
24#include "common/collection.h"
25#include "common/image_cache.h"
26#include "common/history.h"
29#include "develop/dev_history.h"
30#include "develop/develop.h"
31#include "control/control.h"
32
33
35
36static gboolean undo_sensitive_callback()
37{
40 if(IS_NULL_PTR(cv)) return FALSE;
41
42 gboolean sensitive = FALSE;
43
44 if(!strcmp(cv->module_name, "lighttable"))
46 else if(!strcmp(cv->module_name, "darkroom"))
48 else if(!strcmp(cv->module_name, "darkroom"))
50
51 return sensitive;
52}
53
54static gboolean undo_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
55{
58 if(IS_NULL_PTR(cv)) return FALSE;
59
60 if(!strcmp(cv->module_name, "lighttable"))
62 else if(!strcmp(cv->module_name, "darkroom"))
64 else if(!strcmp(cv->module_name, "map"))
66 // Beware: it needs to block callbacks declared in view, which may not be loaded.
67 // Another piece of shitty peculiar design that doesn't comply with the logic of the rest of the soft.
68 // That's what you get from ignoring modularity principles.
69 // For now we just ignore the peculiar stuff, no idea how annoying it is, seems it's only GUI candy.
70
71 return TRUE;
72}
73
74
75static gboolean redo_sensitive_callback()
76{
79 if(IS_NULL_PTR(cv)) return FALSE;
80
81 gboolean sensitive = FALSE;
82
83 if(!strcmp(cv->module_name, "lighttable"))
85 else if(!strcmp(cv->module_name, "darkroom"))
87 else if(!strcmp(cv->module_name, "darkroom"))
89
90 return sensitive;
91}
92
93
94static gboolean redo_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
95{
98 if(IS_NULL_PTR(cv)) return FALSE;
99
100 if(!strcmp(cv->module_name, "lighttable"))
102 else if(!strcmp(cv->module_name, "darkroom"))
104 else if(!strcmp(cv->module_name, "map"))
106 // see undo_callback()
107
108 return TRUE;
109}
110
111static gboolean compress_history_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
112{
113 GList *imgs = dt_act_on_get_images();
114 if(IS_NULL_PTR(imgs)) return FALSE;
115
116 gboolean is_darkroom_image_in_list = dt_dev_history_is_image_in_dev(imgs);
117
118 if(is_darkroom_image_in_list)
119 {
125
126 // Avoid running a headless compression for the current darkroom image: the history module
127 // (src/libs/history.c) compresses directly from the loaded pipeline.
128 imgs = g_list_remove(imgs, GINT_TO_POINTER(dev->image_storage.id));
129 }
130
131 if(imgs) dt_history_compress_on_list(imgs);
132
133 g_list_free(imgs);
134 imgs = NULL;
135 return TRUE;
136}
137
138// delete_history_callback() now lives in common/history_actions.c: it is shared
139// verbatim with the darkroom history module's reset button (see libs/history.c).
140
141static gboolean copy_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
142{
143 // Allow copy only when exactly one file is selected
145 {
146 dt_control_log(_("Copy is allowed only with exactly one image selected"));
147 return FALSE;
148 }
149
151 gboolean is_darkroom_image_in_list = dt_dev_history_is_image_in_dev(imgs);
152 g_list_free(imgs);
153 imgs = NULL;
154
155 if(is_darkroom_image_in_list)
156 {
157 // Copy/paste reloads the source history from the database right away.
158 // Flush the current darkroom history synchronously here so the copied
159 // source matches the edit stack currently shown in the GUI.
161 }
162
164 return TRUE;
165}
166
167
168static gboolean copy_parts_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
169{
170 // Allow copy only when exactly one file is selected
172 {
173 dt_control_log(_("Copy is allowed only with exactly one image selected"));
174 return FALSE;
175 }
176
178 gboolean is_darkroom_image_in_list = dt_dev_history_is_image_in_dev(imgs);
179 g_list_free(imgs);
180 imgs = NULL;
181
182 if(is_darkroom_image_in_list)
183 {
184 // Selective copy opens the same immediate DB read path as full copy.
185 // Keep the persisted history in sync with the current darkroom stack
186 // before building the copy/paste state from this image.
188 }
189
191 return TRUE;
192}
193
194
196{
198}
199
200static gboolean paste_all_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
201{
203 {
204 dt_control_log(_("Paste needs selected images to work"));
205 return FALSE;
206 }
207
208 if(dt_conf_get_bool("history/paste/ask"))
209 {
210 if(!dt_gui_merge_options_dialog(_("Paste history — merge settings"),
211 "history/paste/mode",
212 "history/paste/copy_iop_order",
213 "history/paste/ask",
214 TRUE))
215 return FALSE;
216 }
217
219
220 // We don't allow pasting on darkroom image
222 imgs = g_list_remove(imgs, GINT_TO_POINTER(darktable.develop->image_storage.id));
223
224 if(imgs) dt_history_paste_on_list(imgs);
225
226 g_list_free(imgs);
227 imgs = NULL;
228 return TRUE;
229}
230
231static gboolean paste_parts_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
232{
234 {
235 dt_control_log(_("Paste needs selected images to work"));
236 return FALSE;
237 }
238
239 if(dt_conf_get_bool("history/paste/ask"))
240 {
241 if(!dt_gui_merge_options_dialog(_("Paste history (parts) — merge settings"),
242 "history/paste/mode",
243 "history/paste/copy_iop_order",
244 "history/paste/ask",
245 TRUE))
246 return FALSE;
247 }
248
250
252 {
253 g_list_free(imgs);
254 imgs = NULL;
255 return FALSE;
256 }
257
258 // We don't allow pasting on darkroom image
260 imgs = g_list_remove(imgs, GINT_TO_POINTER(darktable.develop->image_storage.id));
261
262 if(imgs) dt_history_paste_parts_on_list(imgs);
263
265 g_list_free(imgs);
266 imgs = NULL;
267 return TRUE;
268}
269
270static gboolean load_xmp_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
271{
272 // dt_selection_get_list() only sees the lighttable selection, which is typically empty
273 // while in darkroom (the menu entry's sensitivity check, has_active_images(), already
274 // falls back to the active darkroom image via dt_act_on_get_images_nb() -- fetch the
275 // same way here or this silently no-ops in darkroom).
276 GList *imgs = dt_act_on_get_images();
277 if(IS_NULL_PTR(imgs)) return FALSE;
278
279 const int act_on_one = g_list_is_singleton(imgs); // list length == 1?
281 GtkFileChooserNative *filechooser = gtk_file_chooser_native_new(
282 _("open sidecar file"), GTK_WINDOW(win), GTK_FILE_CHOOSER_ACTION_OPEN,
283 _("_open"), _("_cancel"));
284 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(filechooser), FALSE);
285
286 if(act_on_one)
287 {
288 //single image to load xmp to, assume we want to load from same dir
289 const int32_t imgid = GPOINTER_TO_INT(imgs->data);
290 const dt_image_t *img = dt_image_cache_get(darktable.image_cache, imgid, 'r');
291 if(img && img->film_id != -1)
292 {
293 char pathname[PATH_MAX] = { 0 };
294 dt_image_film_roll_directory(img, pathname, sizeof(pathname));
295 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(filechooser), pathname);
296 }
297 else
298 {
299 // handle situation where there's some problem with cache/film_id
300 // i guess that's impossible, but better safe than sorry ;)
301 dt_conf_get_folder_to_file_chooser("ui_last/import_path", GTK_FILE_CHOOSER(filechooser));
302 }
304 }
305 else
306 {
307 // multiple images, use "last import" preference
308 dt_conf_get_folder_to_file_chooser("ui_last/import_path", GTK_FILE_CHOOSER(filechooser));
309 }
310
311 GtkFileFilter *filter;
312 filter = GTK_FILE_FILTER(gtk_file_filter_new());
313 gtk_file_filter_add_pattern(filter, "*.xmp");
314 gtk_file_filter_add_pattern(filter, "*.XMP");
315 gtk_file_filter_set_name(filter, _("XMP sidecar files"));
316 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filechooser), filter);
317
318 filter = GTK_FILE_FILTER(gtk_file_filter_new());
319 gtk_file_filter_add_pattern(filter, "*");
320 gtk_file_filter_set_name(filter, _("all files"));
321 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filechooser), filter);
322
323 if(gtk_native_dialog_run(GTK_NATIVE_DIALOG(filechooser)) == GTK_RESPONSE_ACCEPT)
324 {
325 gchar *dtfilename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filechooser));
326 if(dt_history_load_and_apply_on_list(dtfilename, imgs) != 0)
327 {
328 GtkWidget *dialog
329 = gtk_message_dialog_new(GTK_WINDOW(win), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR,
330 GTK_BUTTONS_CLOSE, _("error loading file '%s'"), dtfilename);
331#ifdef GDK_WINDOWING_QUARTZ
333#endif
334 gtk_dialog_run(GTK_DIALOG(dialog));
335 gtk_widget_destroy(dialog);
336
337 }
338 else
339 {
341 }
342 if(!act_on_one)
343 {
344 //remember last import path if applying history to multiple images
345 dt_conf_set_folder_from_file_chooser("ui_last/import_path", GTK_FILE_CHOOSER(filechooser));
346 }
347 dt_free(dtfilename);
348 }
349
352
353 g_object_unref(filechooser);
354 g_list_free(imgs);
355 imgs = NULL;
356 return TRUE;
357}
358
359static gboolean duplicate_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
360{
362 {
365 {
366 // Duplication copies history from the source image into the new version.
367 // When the source is the current darkroom image, persist its live history
368 // before the background duplicate job reloads it from the database.
370 }
371 g_list_free(imgs);
372 imgs = NULL;
373
375 return TRUE;
376 }
377
378 dt_control_log(_("Duplication needs selected images to work"));
379 return FALSE;
380}
381
382static gboolean new_history_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
383{
385 {
388 {
389 // Creating a new duplicate version still starts from the current source
390 // image state, so flush the live darkroom history before duplicating it.
392 }
393 g_list_free(imgs);
394 imgs = NULL;
395
397 return TRUE;
398 }
399
400 dt_control_log(_("Creating new historys needs selected images to work"));
401 return TRUE;
402}
403
404
405static gboolean shortcuts_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
406{
408 return TRUE;
409}
410
411static gboolean history_append_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
412{
413 dt_conf_set_int("history/paste/mode", DT_HISTORY_MERGE_APPEND);
414 return TRUE;
415}
416
418{
419 return dt_conf_get_int("history/paste/mode") == DT_HISTORY_MERGE_APPEND;
420}
421
422static gboolean history_prepend_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
423{
424 dt_conf_set_int("history/paste/mode", DT_HISTORY_MERGE_PREPEND);
425 return TRUE;
426}
427
429{
430 return dt_conf_get_int("history/paste/mode") == DT_HISTORY_MERGE_PREPEND;
431}
432
433static gboolean history_replace_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval,
434 GdkModifierType mods, gpointer user_data)
435{
436 dt_conf_set_int("history/paste/mode", DT_HISTORY_MERGE_REPLACE);
437 return TRUE;
438}
439
441{
442 return dt_conf_get_int("history/paste/mode") == DT_HISTORY_MERGE_REPLACE;
443}
444
445static gboolean copy_iop_order_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
446{
447 dt_conf_set_bool("history/paste/copy_iop_order", !dt_conf_get_bool("history/paste/copy_iop_order"));
448 return TRUE;
449}
450
452{
453 return dt_conf_get_bool("history/paste/copy_iop_order");
454}
455
456static gboolean paste_ask_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
457{
458 dt_conf_set_bool("history/paste/ask", !dt_conf_get_bool("history/paste/ask"));
459 return TRUE;
460}
461
462static gboolean paste_ask_checked_callback(GtkWidget *widget)
463{
464 return dt_conf_get_bool("history/paste/ask");
465}
466
467void append_edit(GtkWidget **menus, GList **lists, const dt_menus_t index)
468{
469 add_sub_menu_entry(menus, lists, _("Undo"), index, NULL, undo_callback, NULL, NULL, undo_sensitive_callback, GDK_KEY_z, GDK_CONTROL_MASK);
470
471 add_sub_menu_entry(menus, lists, _("Redo"), index, NULL, redo_callback, NULL, NULL, redo_sensitive_callback, GDK_KEY_y, GDK_CONTROL_MASK);
472
473 add_menu_separator(menus[index]);
474
475 add_sub_menu_entry(menus, lists, _("Copy history (all)"), index, NULL, copy_callback, NULL, NULL, has_selection, GDK_KEY_c, GDK_CONTROL_MASK);
476
477 add_sub_menu_entry(menus, lists, _("Copy history (parts)..."), index, NULL, copy_parts_callback, NULL, NULL, has_selection, GDK_KEY_c, GDK_CONTROL_MASK | GDK_SHIFT_MASK);
478
479 add_sub_menu_entry(menus, lists, _("Paste history (all)"), index, NULL, paste_all_callback, NULL, NULL,
480 paste_sensitive_callback, GDK_KEY_v, GDK_CONTROL_MASK);
481
482 add_sub_menu_entry(menus, lists, _("Paste history (parts)..."), index, NULL, paste_parts_callback, NULL, NULL,
483 paste_sensitive_callback, GDK_KEY_v, GDK_CONTROL_MASK | GDK_SHIFT_MASK);
484
485 add_menu_separator(menus[index]);
486
487 // History merging options
488
489 add_top_submenu_entry(menus, lists, _("History pasting mode"), index);
490 GtkWidget *parent = get_last_widget(lists);
491
492 add_sub_sub_menu_entry(menus, parent, lists, _("Prepend"), index, NULL,
494 gtk_widget_set_tooltip_text(get_last_widget(lists),
495 _("Paste copied history BEFORE the current history.\n"
496 "CURRENT EDITS are applied afterwards and win conflicts."));
497
498 add_sub_sub_menu_entry(menus, parent, lists, _("Append"), index, NULL,
500 gtk_widget_set_tooltip_text(get_last_widget(lists),
501 _("Paste copied history AFTER the current history.\n"
502 "COPIED EDITS are applied afterwards and win conflicts."));
503
504 add_sub_sub_menu_entry(menus, parent, lists, _("Replace"), index, NULL,
506 gtk_widget_set_tooltip_text(get_last_widget(lists),
507 _("Discard the current history and replace it entirely with the copied history."));
508
509 add_top_submenu_entry(menus, lists, _("Nodes pasting mode"), index);
510 parent = get_last_widget(lists);
511
512 add_sub_sub_menu_entry(menus, parent, lists, _("Copy module order"), index, NULL,
514
515 add_sub_menu_entry(menus, lists, _("Ask merge settings before paste"), index, NULL,
517
518 add_menu_separator(menus[index]);
519
520 add_sub_menu_entry(menus, lists, _("Load history from XMP..."), index, NULL,
521 load_xmp_callback, NULL, NULL, has_active_images, 0, 0);
522
523 add_sub_menu_entry(menus, lists, _("Create new history"), index, NULL,
524 new_history_callback, NULL, NULL, has_active_images, GDK_KEY_n, GDK_CONTROL_MASK);
525
526 add_sub_menu_entry(menus, lists, _("Duplicate existing history"), index, NULL,
527 duplicate_callback, NULL, NULL, has_active_images, GDK_KEY_d, GDK_CONTROL_MASK);
528
529 add_sub_menu_entry(menus, lists, _("Compress history"), index, NULL,
531
532 add_sub_menu_entry(menus, lists, _("Delete history"), index, NULL,
533 delete_history_callback, NULL, NULL, has_active_images, 0, 0);
534
535 add_menu_separator(menus[index]);
536
537 add_sub_menu_entry(menus, lists, _("Preferences..."), index, NULL, GET_ACCEL_WRAPPER(dt_gui_preferences_show), NULL, NULL, NULL, 0, 0);
538 add_sub_menu_entry(menus, lists, _("Keyboard shortcuts..."), index, NULL, shortcuts_callback, NULL, NULL, NULL, 0, 0);
539}
void dt_accels_window(dt_accels_t *accels, GtkWindow *main_window)
Show the modal dialog listing all available keyboard shortcuts and letting user to set them.
GList * dt_act_on_get_images()
Definition act_on.c:39
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
void dt_image_film_roll_directory(const dt_image_t *img, char *pathname, size_t pathname_len)
void dt_conf_set_bool(const char *name, int val)
int dt_conf_get_bool(const char *name)
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
void dt_conf_set_folder_from_file_chooser(const char *name, GtkFileChooser *chooser)
gboolean dt_conf_get_folder_to_file_chooser(const char *name, GtkFileChooser *chooser)
void dt_control_log(const char *msg,...)
Definition control.c:777
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_duplicate_images(gboolean virgin)
darktable_t darktable
Definition darktable.c:183
#define g_list_is_singleton(list)
Definition darktable.h:1000
#define dt_free(ptr)
Definition darktable.h:478
#define PATH_MAX
Definition darktable.h:1189
#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
void dt_apply_dev_history_update(dt_develop_t *dev)
Reload the current darkroom history and refresh every dependent GUI.
gboolean dt_dev_history_is_image_in_dev(GList *imgs)
Check whether any image of the list is the one currently loaded in the darkroom.
void dt_dev_write_history(dt_develop_t *dev, gboolean async)
Thread-safe wrapper around dt_dev_write_history_ext() for dev->image_storage.id.
void dt_dev_undo_start_record(dt_develop_t *dev)
Definition develop.c:1678
void dt_dev_undo_end_record(dt_develop_t *dev)
Definition develop.c:1689
static gboolean redo_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition edit.c:94
static gboolean history_prepend_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition edit.c:422
static gboolean paste_sensitive_callback()
Definition edit.c:195
static gboolean new_history_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition edit.c:382
static gboolean history_replace_checked_callback(GtkWidget *widget)
Definition edit.c:440
static gboolean undo_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition edit.c:54
static gboolean compress_history_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition edit.c:111
static gboolean copy_iop_order_checked_callback(GtkWidget *widget)
Definition edit.c:451
static gboolean copy_parts_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition edit.c:168
static gboolean paste_all_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition edit.c:200
static gboolean redo_sensitive_callback()
Definition edit.c:75
static gboolean history_append_checked_callback(GtkWidget *widget)
Definition edit.c:417
static gboolean copy_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition edit.c:141
static gboolean duplicate_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition edit.c:359
static gboolean paste_ask_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition edit.c:456
static gboolean paste_parts_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition edit.c:231
void append_edit(GtkWidget **menus, GList **lists, const dt_menus_t index)
Definition edit.c:467
static gboolean shortcuts_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition edit.c:405
static gboolean history_append_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition edit.c:411
static gboolean copy_iop_order_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition edit.c:445
static gboolean undo_sensitive_callback()
Definition edit.c:36
static gboolean paste_ask_checked_callback(GtkWidget *widget)
Definition edit.c:462
static gboolean load_xmp_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition edit.c:270
static gboolean history_prepend_checked_callback(GtkWidget *widget)
Definition edit.c:428
static gboolean history_replace_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
Definition edit.c:433
GtkWidget * dt_ui_main_window(dt_ui_t *ui)
get the main window widget
gboolean dt_history_paste_on_list(const GList *list)
gboolean dt_history_copy(int32_t imgid)
gboolean dt_history_paste_parts_on_list(const GList *list)
gboolean delete_history_callback(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data)
gboolean dt_history_paste_parts_prepare(void)
int dt_history_load_and_apply_on_list(gchar *filename, const GList *list)
int dt_history_compress_on_list(const GList *imgs)
gboolean dt_history_copy_parts(int32_t imgid)
void dt_history_compress_on_image(const int32_t imgid)
@ DT_HISTORY_MERGE_REPLACE
@ DT_HISTORY_MERGE_PREPEND
@ DT_HISTORY_MERGE_APPEND
gboolean dt_gui_merge_options_dialog(const char *title, const char *mode_key, const char *iop_order_key, const char *ask_key, const gboolean iop_order_available)
Show a modal dialog to pick merge mode and pipeline order before a paste or style apply.
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)
gboolean has_selection()
Definition menu.c:629
void add_sub_sub_menu_entry(GtkWidget **menus, GtkWidget *parent, GList **lists, const gchar *label, const dt_menus_t index, void *data, gboolean(*action_callback)(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data), gboolean(*checked_callback)(GtkWidget *widget), gboolean(*active_callback)(GtkWidget *widget), gboolean(*sensitive_callback)(GtkWidget *widget), guint key_val, GdkModifierType mods)
Definition menu.c:583
GtkWidget * get_last_widget(GList **list)
Definition menu.c:617
void add_sub_menu_entry(GtkWidget **menus, GList **lists, const gchar *label, const dt_menus_t index, void *data, gboolean(*action_callback)(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data), gboolean(*checked_callback)(GtkWidget *widget), gboolean(*active_callback)(GtkWidget *widget), gboolean(*sensitive_callback)(GtkWidget *widget), guint key_val, GdkModifierType mods)
Definition menu.c:541
void add_top_submenu_entry(GtkWidget **menus, GList **lists, const gchar *label, const dt_menus_t index)
Definition menu.c:514
void add_menu_separator(GtkWidget *menu)
Definition menu.c:597
gboolean has_active_images()
Definition menu.c:635
#define GET_ACCEL_WRAPPER(cb)
Definition menu.h:235
#define MAKE_ACCEL_WRAPPER(cb)
Definition menu.h:223
dt_menus_t
Definition menu.h:42
void dt_osx_disallow_fullscreen(GtkWidget *widget)
Definition osx.mm:104
void dt_gui_preferences_show()
int32_t dt_selection_get_first_id(struct dt_selection_t *selection)
Definition selection.c:69
int dt_selection_get_length(struct dt_selection_t *selection)
Definition selection.c:179
GList * dt_selection_get_list(struct dt_selection_t *selection)
Definition selection.c:172
struct _GtkWidget GtkWidget
Definition splash.h:29
struct dt_undo_t * undo
Definition darktable.h:815
struct dt_gui_gtk_t * gui
Definition darktable.h:803
struct dt_selection_t * selection
Definition darktable.h:810
struct dt_image_cache_t * image_cache
Definition darktable.h:805
struct dt_develop_t * develop
Definition darktable.h:798
struct dt_view_manager_t * view_manager
Definition darktable.h:800
dt_image_t image_storage
Definition develop.h:259
dt_accels_t * accels
Definition gtk.h:199
dt_ui_t * ui
Definition gtk.h:165
int32_t film_id
Definition image.h:319
int32_t id
Definition image.h:319
dt_history_copy_item_t copy_paste
Definition view.h:208
char module_name[64]
Definition view.h:154
void dt_undo_do_redo(dt_undo_t *self, uint32_t filter)
Definition undo.c:272
gboolean dt_is_redo_list_populated(dt_undo_t *self, uint32_t filter)
Definition undo.c:311
void dt_undo_do_undo(dt_undo_t *self, uint32_t filter)
Definition undo.c:277
gboolean dt_is_undo_list_populated(dt_undo_t *self, uint32_t filter)
Definition undo.c:306
@ DT_UNDO_LIGHTTABLE
Definition undo.h:54
@ DT_UNDO_MAP
Definition undo.h:57
@ DT_UNDO_DEVELOP
Definition undo.h:52
const dt_view_t * dt_view_manager_get_current_view(dt_view_manager_t *vm)
Definition view.c:141