Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
gui/presets.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2010 Bruce Guenter.
4 Copyright (C) 2010-2012 Henrik Andersson.
5 Copyright (C) 2010-2014, 2018 johannes hanika.
6 Copyright (C) 2010 Stuart Henderson.
7 Copyright (C) 2011 Antony Dovgal.
8 Copyright (C) 2011 Brian Teague.
9 Copyright (C) 2011-2012 Jérémy Rosen.
10 Copyright (C) 2011 Robert Bieber.
11 Copyright (C) 2011-2016, 2018-2019 Tobias Ellinghaus.
12 Copyright (C) 2011-2013 Ulrich Pegelow.
13 Copyright (C) 2012, 2020-2021 Aldric Renaudin.
14 Copyright (C) 2012 Ivan Tarozzi.
15 Copyright (C) 2012 José Carlos García Sogo.
16 Copyright (C) 2012, 2017-2018, 2020 parafin.
17 Copyright (C) 2012 Richard Wonka.
18 Copyright (C) 2013, 2018-2021 Pascal Obry.
19 Copyright (C) 2013-2017 Roman Lebedev.
20 Copyright (C) 2013 Simon Spannagel.
21 Copyright (C) 2013 Thomas Pryds.
22 Copyright (C) 2014 Pascal de Bruijn.
23 Copyright (C) 2015 Pedro Côrte-Real.
24 Copyright (C) 2017-2018, 2021 Heiko Bauke.
25 Copyright (C) 2019, 2022-2026 Aurélien PIERRE.
26 Copyright (C) 2019 Jakub Filipowicz.
27 Copyright (C) 2019 Sam Smith.
28 Copyright (C) 2020-2022 Chris Elston.
29 Copyright (C) 2020 darkelectron.
30 Copyright (C) 2020-2021 Diederik Ter Rahe.
31 Copyright (C) 2020 Hanno Schwalm.
32 Copyright (C) 2020 Harold le Clément de Saint-Marcq.
33 Copyright (C) 2020-2021 Hubert Kowalski.
34 Copyright (C) 2020 Tomasz Golinski.
35 Copyright (C) 2021 luzpaz.
36 Copyright (C) 2021 Marco.
37 Copyright (C) 2021 Marco Carrarini.
38 Copyright (C) 2021-2022 Nicolas Auffray.
39 Copyright (C) 2021 Ralf Brown.
40 Copyright (C) 2022 Martin Bařinka.
41 Copyright (C) 2022 Miloš Komarčević.
42
43 darktable is free software: you can redistribute it and/or modify
44 it under the terms of the GNU General Public License as published by
45 the Free Software Foundation, either version 3 of the License, or
46 (at your option) any later version.
47
48 darktable is distributed in the hope that it will be useful,
49 but WITHOUT ANY WARRANTY; without even the implied warranty of
50 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51 GNU General Public License for more details.
52
53 You should have received a copy of the GNU General Public License
54 along with darktable. If not, see <http://www.gnu.org/licenses/>.
55*/
56
57#ifdef HAVE_CONFIG_H
58#include "config.h"
59#endif
60#include "bauhaus/bauhaus.h"
61#include "common/darktable.h"
62#include "common/debug.h"
64#include "common/presets.h"
65#include "control/control.h"
66#include "develop/blend.h"
67#include "develop/develop.h"
68
69#include "gui/gtk.h"
70#include "gui/guides.h"
71#include "gui/presets.h"
72#ifdef GDK_WINDOWING_QUARTZ
73#include "osx/osx.h"
74#endif
75#include <assert.h>
76#include <stdlib.h>
77
80 = { 0., 1. / 8000, 1. / 4000, 1. / 2000, 1. / 1000, 1. / 1000, 1. / 500, 1. / 250,
81 1. / 125, 1. / 60, 1. / 30, 1. / 15, 1. / 15, 1. / 8, 1. / 4, 1. / 2,
82 1, 2, 4, 8, 15, 30, 60, FLT_MAX };
84 = { "0", "1/8000", "1/4000", "1/2000", "1/1000", "1/1000", "1/500", "1/250",
85 "1/125", "1/60", "1/30", "1/15", "1/15", "1/8", "1/4", "1/2",
86 "1\"", "2\"", "4\"", "8\"", "15\"", "30\"", "60\"", "+" };
89 = { 0, 0.5, 0.7, 1.0, 1.4, 2.0, 2.8, 4.0, 5.6, 8.0, 11.0, 16.0, 22.0, 32.0, 45.0, 64.0, 90.0, 128.0, FLT_MAX };
91 = { "f/0", "f/0.5", "f/0.7", "f/1.0", "f/1.4", "f/2", "f/2.8", "f/4", "f/5.6", "f/8",
92 "f/11", "f/16", "f/22", "f/32", "f/45", "f/64", "f/90", "f/128", "f/+" };
93
94static sqlite3_stmt *_gui_presets_add_stmt = NULL;
95static sqlite3_stmt *_gui_presets_update_mml_stmt = NULL;
96static sqlite3_stmt *_gui_presets_update_iso_stmt = NULL;
97static sqlite3_stmt *_gui_presets_update_av_stmt = NULL;
98static sqlite3_stmt *_gui_presets_update_tv_stmt = NULL;
99static sqlite3_stmt *_gui_presets_update_fl_stmt = NULL;
100static sqlite3_stmt *_gui_presets_update_ldr_stmt = NULL;
101static sqlite3_stmt *_gui_presets_update_autoapply_stmt = NULL;
102static sqlite3_stmt *_gui_presets_update_filter_stmt = NULL;
104
105// format string and corresponding flag stored into the database
106static const char *_gui_presets_format_value_str[5]
107 = { N_("non-raw"), N_("raw"), N_("HDR"), N_("monochrome"), N_("color") };
109
110// this is also called for non-gui applications linking to libansel!
111// so beware, don't use any darktable.gui stuff here .. (or change this behaviour in darktable.c)
113{
114 // Avoid regenerating all auto-presets on every startup when the build and UI language are unchanged.
115 // This cuts a large number of INSERTs during module load without altering behavior across upgrades.
116 gchar *lang = dt_conf_get_string("ui_last/gui_language");
117 if(IS_NULL_PTR(lang)) lang = g_strdup("");
118 gchar *sig = g_strdup_printf("%s|%s", darktable_package_version, lang);
119 gchar *prev = dt_conf_get_string("ui_last/presets_autogen_signature");
120 _gui_presets_autogen_enabled = !(prev && !g_strcmp0(prev, sig));
121 dt_conf_set_string("ui_last/presets_autogen_signature", sig);
122 dt_free(prev);
123 dt_free(sig);
124 dt_free(lang);
125
126 // remove auto generated presets from plugins, not the user included ones.
128 {
129 DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "DELETE FROM data.presets WHERE writeprotect = 1", NULL,
130 NULL, NULL);
131 }
132}
133
138
140{
142 {
143 sqlite3_finalize(_gui_presets_add_stmt);
145 }
147 {
148 sqlite3_finalize(_gui_presets_update_mml_stmt);
150 }
152 {
153 sqlite3_finalize(_gui_presets_update_iso_stmt);
155 }
157 {
158 sqlite3_finalize(_gui_presets_update_av_stmt);
160 }
162 {
163 sqlite3_finalize(_gui_presets_update_tv_stmt);
165 }
167 {
168 sqlite3_finalize(_gui_presets_update_fl_stmt);
170 }
172 {
173 sqlite3_finalize(_gui_presets_update_ldr_stmt);
175 }
177 {
178 sqlite3_finalize(_gui_presets_update_autoapply_stmt);
180 }
182 {
183 sqlite3_finalize(_gui_presets_update_filter_stmt);
185 }
186}
187
188void dt_gui_presets_add_generic(const char *name, dt_dev_operation_t op, const int32_t version,
189 const void *params, const int32_t params_size,
190 const int32_t enabled,
191 const dt_develop_blend_colorspace_t blend_cst)
192{
193 dt_develop_blend_params_t default_blendop_params;
194 dt_develop_blend_init_blend_parameters(&default_blendop_params, blend_cst);
196 name, op, version, params, params_size,
197 &default_blendop_params, enabled);
198}
199
201 const char *name, dt_dev_operation_t op, const int32_t version,
202 const void *params, const int32_t params_size,
203 const void *blend_params, const int32_t enabled)
204{
205 sqlite3_stmt *stmt = NULL;
207 {
208 // clang-format off
211 "INSERT OR REPLACE"
212 " INTO data.presets (name, description, operation, op_version, op_params, enabled,"
213 " blendop_params, blendop_version, multi_priority, multi_name,"
214 " model, maker, lens, iso_min, iso_max, exposure_min, exposure_max,"
215 " aperture_min, aperture_max, focal_length_min, focal_length_max,"
216 " writeprotect, autoapply, filter, def, format)"
217 " VALUES (?1, '', ?2, ?3, ?4, ?5, ?6, ?7, 0, '', '%', '%', '%', 0,"
218 " 340282346638528859812000000000000000000, 0, 10000000, 0, 100000000, 0,"
219 " 1000, 1, 0, 0, 0, 0)",
220 -1, &_gui_presets_add_stmt, NULL);
221 // clang-format on
222 }
224 sqlite3_reset(stmt);
225 sqlite3_clear_bindings(stmt);
226
227 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, name, -1, SQLITE_TRANSIENT);
228 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, op, -1, SQLITE_TRANSIENT);
229 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, version);
230 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 4, params, params_size, SQLITE_TRANSIENT);
231 DT_DEBUG_SQLITE3_BIND_INT(stmt, 5, enabled);
232 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 6, blend_params, sizeof(dt_develop_blend_params_t),
233 SQLITE_TRANSIENT);
235 sqlite3_step(stmt);
236}
237
238static gchar *_get_active_preset_name(dt_iop_module_t *module, int *writeprotect)
239{
240 sqlite3_stmt *stmt;
241 // if we sort by writeprotect DESC then in case user copied the writeprotected preset
242 // then the preset name returned will be writeprotected and thus not deletable
243 // sorting ASC prefers user created presets.
244 // clang-format off
247 "SELECT name, op_params, blendop_params, enabled, writeprotect"
248 " FROM data.presets"
249 " WHERE operation=?1 AND op_version=?2"
250 " ORDER BY writeprotect ASC, LOWER(name), rowid",
251 -1, &stmt, NULL);
252 // clang-format on
253 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, module->op, -1, SQLITE_TRANSIENT);
254 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, module->version());
255 gchar *name = NULL;
256
257 // collect all presets for op from db
258 while(sqlite3_step(stmt) == SQLITE_ROW)
259 {
260 const void *op_params = (void *)sqlite3_column_blob(stmt, 1);
261 const int32_t op_params_size = sqlite3_column_bytes(stmt, 1);
262 const void *blendop_params = (void *)sqlite3_column_blob(stmt, 2);
263 const int32_t bl_params_size = sqlite3_column_bytes(stmt, 2);
264 const int enabled = sqlite3_column_int(stmt, 3);
265
266 if(!memcmp(module->params, op_params, MIN(op_params_size, module->params_size))
267 && !memcmp(module->blend_params, blendop_params,
268 MIN(bl_params_size, sizeof(dt_develop_blend_params_t))) && module->enabled == enabled)
269 {
270 name = g_strdup((char *)sqlite3_column_text(stmt, 0));
271 *writeprotect = sqlite3_column_int(stmt, 4);
272 break;
273 }
274 }
275 sqlite3_finalize(stmt);
276 return name;
277}
278
279static void _menuitem_delete_preset(GtkMenuItem *menuitem, dt_iop_module_t *module)
280{
281 int writeprotect = -1;
282 gchar *name = _get_active_preset_name(module, &writeprotect);
283 if(IS_NULL_PTR(name)) return;
284
285 if(writeprotect)
286 {
287 dt_control_log(_("preset `%s' is write-protected, can't delete!"), name);
288 dt_free(name);
289 return;
290 }
291
292 gint res = GTK_RESPONSE_YES;
293
294 if(dt_conf_get_bool("plugins/lighttable/preset/ask_before_delete_preset"))
295 {
297 GtkWidget *dialog
298 = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION,
299 GTK_BUTTONS_YES_NO, _("do you really want to delete the preset `%s'?"), name);
300#ifdef GDK_WINDOWING_QUARTZ
302#endif
303 gtk_window_set_title(GTK_WINDOW(dialog), _("delete preset?"));
304 res = gtk_dialog_run(GTK_DIALOG(dialog));
305 GtkWindow *dialog_parent = gtk_window_get_transient_for(GTK_WINDOW(dialog));
306 gtk_widget_destroy(dialog);
307 dt_gui_refocus_parent(dialog_parent);
308 }
309
310 if(res == GTK_RESPONSE_YES)
311 dt_lib_presets_remove(name, module->op, module->version());
312
313 dt_free(name);
314}
316{
317 dt_gui_store_last_preset(gtk_entry_get_text(g->name));
318}
319
320static void _edit_preset_response(GtkDialog *dialog, gint response_id, dt_gui_presets_edit_dialog_t *g)
321{
322 if(response_id == GTK_RESPONSE_OK)
323 {
324 // we want to save the preset in the database
325 sqlite3_stmt *stmt;
326
327 // we verify eventual name collisions
328 const gchar *name = gtk_entry_get_text(g->name);
329 if(((g->old_id >= 0) && (strcmp(g->original_name, name) != 0)) || (g->old_id < 0))
330 {
331 if(IS_NULL_PTR(name) || *name == '\0' || strcmp(_("new preset"), name) == 0)
332 {
333 // show error dialog
334 GtkWidget *dlg_changename
335 = gtk_message_dialog_new(GTK_WINDOW(dialog), GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
336 GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("please give preset a name"));
337#ifdef GDK_WINDOWING_QUARTZ
338 dt_osx_disallow_fullscreen(dlg_changename);
339#endif
340
341 gtk_window_set_title(GTK_WINDOW(dlg_changename), _("unnamed preset"));
342
343 gtk_dialog_run(GTK_DIALOG(dlg_changename));
344 gtk_widget_destroy(dlg_changename);
345 return;
346 }
347
348 // editing existing preset with different name or store new preset -> check for a preset with the same
349 // name:
350 // clang-format off
353 "SELECT name"
354 " FROM data.presets"
355 " WHERE name = ?1 AND operation=?2 AND op_version=?3"
356 " LIMIT 1",
357 -1, &stmt, NULL);
358 // clang-format on
359 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, name, -1, SQLITE_TRANSIENT);
360 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, g->operation, -1, SQLITE_TRANSIENT);
361 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, g->op_version);
362
363 if(sqlite3_step(stmt) == SQLITE_ROW)
364 {
365 sqlite3_finalize(stmt);
366
367 // show overwrite question dialog
368 GtkWidget *dlg_overwrite = gtk_message_dialog_new(
369 GTK_WINDOW(dialog), GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING,
370 GTK_BUTTONS_YES_NO, _("preset `%s' already exists.\ndo you want to overwrite?"), name);
371#ifdef GDK_WINDOWING_QUARTZ
372 dt_osx_disallow_fullscreen(dlg_overwrite);
373#endif
374
375 gtk_window_set_title(GTK_WINDOW(dlg_overwrite), _("overwrite preset?"));
376
377 const gint dlg_ret = gtk_dialog_run(GTK_DIALOG(dlg_overwrite));
378 gtk_widget_destroy(dlg_overwrite);
379
380 // if result is BUTTON_NO or ESCAPE keypress exit without destroying dialog, to permit other name
381 if(dlg_ret == GTK_RESPONSE_YES)
382 {
383 // we remove the preset that will be overwrite
384 dt_lib_presets_remove(name, g->operation, g->op_version);
385 }
386 else
387 return;
388 }
389 else
390 {
391 sqlite3_finalize(stmt);
392 }
393 }
394
395 gchar *query = NULL;
396 if(g->old_id >= 0)
397 {
398 // we update presets values
399 // clang-format off
400 query = g_strdup_printf("UPDATE data.presets "
401 "SET"
402 " name=?1, description=?2,"
403 " model=?3, maker=?4, lens=?5, iso_min=?6, iso_max=?7, exposure_min=?8,"
404 " exposure_max=?9, aperture_min=?10,"
405 " aperture_max=?11, focal_length_min=?12, focal_length_max=?13, autoapply=?14,"
406 " filter=?15, format=?16 "
407 "WHERE rowid=%d",
408 g->old_id);
409 // clang-format on
410 }
411 else
412 {
413 // we create a new preset
414 // clang-format off
415 query = g_strdup_printf("INSERT INTO data.presets"
416 " (name, description, "
417 " model, maker, lens, iso_min, iso_max, exposure_min, exposure_max, aperture_min,"
418 " aperture_max, focal_length_min, focal_length_max, autoapply,"
419 " filter, format, def, writeprotect, operation, op_version, op_params, enabled,"
420 " blendop_params, blendop_version, multi_priority, multi_name) "
421 "VALUES"
422 " (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, 0, 0, ?17,"
423 " ?18, ?19, ?20, ?21, ?22, 0, '')");
424 // clang-format on
425 }
426
427 // commit all the user input fields
429 dt_free(query);
430 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, name, -1, SQLITE_TRANSIENT);
431 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, gtk_entry_get_text(g->description), -1, SQLITE_TRANSIENT);
432
433 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, gtk_entry_get_text(GTK_ENTRY(g->model)), -1, SQLITE_TRANSIENT);
434 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, gtk_entry_get_text(GTK_ENTRY(g->maker)), -1, SQLITE_TRANSIENT);
435 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 5, gtk_entry_get_text(GTK_ENTRY(g->lens)), -1, SQLITE_TRANSIENT);
436 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 6, gtk_spin_button_get_value(GTK_SPIN_BUTTON(g->iso_min)));
437 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 7, gtk_spin_button_get_value(GTK_SPIN_BUTTON(g->iso_max)));
444 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 12, gtk_spin_button_get_value(GTK_SPIN_BUTTON(g->focal_length_min)));
445 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 13, gtk_spin_button_get_value(GTK_SPIN_BUTTON(g->focal_length_max)));
446 DT_DEBUG_SQLITE3_BIND_INT(stmt, 14, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g->autoapply)));
447 DT_DEBUG_SQLITE3_BIND_INT(stmt, 15, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g->filter)));
448 int format = 0;
449 for(int k = 0; k < 5; k++)
450 format += gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g->format_btn[k])) * _gui_presets_format_flag[k];
451 format ^= DT_PRESETS_FOR_NOT;
452
453 DT_DEBUG_SQLITE3_BIND_INT(stmt, 16, format);
454
455 // commit specific field in case of newly crearted preset
456 if(g->old_id < 0)
457 {
458 if(g->iop)
459 {
460 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 17, g->operation, -1, SQLITE_TRANSIENT);
461 DT_DEBUG_SQLITE3_BIND_INT(stmt, 18, g->op_version);
462 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 19, g->iop->params, g->iop->params_size, SQLITE_TRANSIENT);
463 DT_DEBUG_SQLITE3_BIND_INT(stmt, 20, g->iop->enabled);
464 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 21, g->iop->blend_params, sizeof(dt_develop_blend_params_t),
465 SQLITE_TRANSIENT);
467 }
468 else
469 {
470 // we are in the lib case currently we set set all params to 0
471 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 17, g->operation, -1, SQLITE_TRANSIENT);
472 DT_DEBUG_SQLITE3_BIND_INT(stmt, 18, g->op_version);
473 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 19, NULL, 0, SQLITE_TRANSIENT);
474 DT_DEBUG_SQLITE3_BIND_INT(stmt, 20, 0);
475 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 21, NULL, 0, SQLITE_TRANSIENT);
476 DT_DEBUG_SQLITE3_BIND_INT(stmt, 22, 0);
477 }
478 }
479
480 sqlite3_step(stmt);
481 sqlite3_finalize(stmt);
482
483 if(g->callback) ((void (*)(dt_gui_presets_edit_dialog_t *))g->callback)(g);
484 }
485 else if(response_id == GTK_RESPONSE_YES && g->old_id)
486 {
487 const gchar *name = gtk_entry_get_text(g->name);
488
489 // ask for destination directory
490 GtkFileChooserNative *filechooser = gtk_file_chooser_native_new(
491 _("select directory"), GTK_WINDOW(dialog), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
492 _("_select as output destination"), _("_cancel"));
493 dt_conf_get_folder_to_file_chooser("ui_last/export_path", GTK_FILE_CHOOSER(filechooser));
494
495 // save if accepted
496 if(gtk_native_dialog_run(GTK_NATIVE_DIALOG(filechooser)) == GTK_RESPONSE_ACCEPT)
497 {
498 char *filedir = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filechooser));
499 dt_presets_save_to_file(g->old_id, name, filedir);
500 dt_control_log(_("preset %s was successfully exported"), name);
501 dt_free(filedir);
502 dt_conf_set_folder_from_file_chooser("ui_last/export_path", GTK_FILE_CHOOSER(filechooser));
503 }
504
505 g_object_unref(GTK_WIDGET(filechooser));
506 return; // we don't close the window so other actions can be performed if needed
507 }
508 else if(response_id == GTK_RESPONSE_REJECT && g->old_id)
509 {
510 dt_gui_presets_confirm_and_delete(GTK_WIDGET(dialog), g->original_name, g->operation, g->old_id);
511
512 if(g->callback) ((void (*)(dt_gui_presets_edit_dialog_t *))g->callback)(g);
513 }
514
515 GtkWindow *dialog_parent = gtk_window_get_transient_for(GTK_WINDOW(dialog));
516 gtk_widget_destroy(GTK_WIDGET(dialog));
517 dt_gui_refocus_parent(dialog_parent);
518 dt_free(g->original_name);
519 dt_free(g->module_name);
520 dt_free(g->operation);
521 dt_free(g);
522}
523
524void dt_gui_presets_confirm_and_delete(GtkWidget *parent_dialog, const char *name, const char *module_name, int rowid)
525{
526 if(IS_NULL_PTR(module_name)) return;
527
528 // This means with want to remove the preset
529 GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(parent_dialog), GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
530 GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
531 _("do you really want to delete the preset `%s'?"), name);
532#ifdef GDK_WINDOWING_QUARTZ
534#endif
535
536 gtk_window_set_title(GTK_WINDOW(dialog), _("delete preset?"));
537 if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_YES)
538 {
539 // remove the preset from the database
540 sqlite3_stmt *stmt;
542 "DELETE FROM data.presets WHERE rowid=?1 AND writeprotect=0", -1, &stmt, NULL);
543 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, rowid);
544 sqlite3_step(stmt);
545 sqlite3_finalize(stmt);
546 }
547 gtk_widget_destroy(dialog);
548}
549
550static void _check_buttons_activated(GtkCheckButton *button, dt_gui_presets_edit_dialog_t *g)
551{
552 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g->autoapply))
553 || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g->filter)))
554 {
555 gtk_widget_set_visible(GTK_WIDGET(g->details), TRUE);
556 gtk_widget_set_no_show_all(GTK_WIDGET(g->details), FALSE);
557 gtk_widget_show_all(GTK_WIDGET(g->details));
558 gtk_widget_set_no_show_all(GTK_WIDGET(g->details), TRUE);
559 }
560 else
561 gtk_widget_set_visible(GTK_WIDGET(g->details), FALSE);
562}
563
564static void _presets_show_edit_dialog(dt_gui_presets_edit_dialog_t *g, gboolean allow_name_change,
565 gboolean allow_desc_change, gboolean allow_remove)
566{
567 /* Create the widgets */
568 char title[1024];
569 snprintf(title, sizeof(title), _("edit `%s' for module `%s'"), g->original_name, g->module_name);
570 GtkWidget *dialog = gtk_dialog_new_with_buttons
571 (title, g->parent, GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
572 _("_cancel"), GTK_RESPONSE_CANCEL, _("_export..."), GTK_RESPONSE_YES,
573 _("delete"), GTK_RESPONSE_REJECT, _("_ok"), GTK_RESPONSE_OK, NULL);
574 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
575
576#ifdef GDK_WINDOWING_QUARTZ
578#endif
579 GtkContainer *content_area = GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog)));
580 GtkBox *box = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING));
581 gtk_container_add(content_area, GTK_WIDGET(box));
582
583 g->name = GTK_ENTRY(gtk_entry_new());
584 dt_accels_disconnect_on_text_input(GTK_WIDGET(g->name));
585 gtk_entry_set_text(g->name, g->original_name);
586 if(allow_name_change)
587 gtk_entry_set_activates_default(g->name, TRUE);
588 else
589 gtk_widget_set_sensitive(GTK_WIDGET(g->name), FALSE);
590 gtk_box_pack_start(box, GTK_WIDGET(g->name), FALSE, FALSE, 0);
591 gtk_widget_set_tooltip_text(GTK_WIDGET(g->name), _("name of the preset"));
592
593 g->description = GTK_ENTRY(gtk_entry_new());
594 dt_accels_disconnect_on_text_input(GTK_WIDGET(g->description));
595 if(allow_desc_change)
596 gtk_entry_set_activates_default(g->description, TRUE);
597 else
598 gtk_widget_set_sensitive(GTK_WIDGET(g->description), FALSE);
599 gtk_box_pack_start(box, GTK_WIDGET(g->description), FALSE, FALSE, 0);
600 gtk_widget_set_tooltip_text(GTK_WIDGET(g->description), _("description or further information"));
601
602 g->autoapply
603 = GTK_CHECK_BUTTON(gtk_check_button_new_with_label(_("auto apply this preset to matching images")));
604 gtk_box_pack_start(box, GTK_WIDGET(g->autoapply), FALSE, FALSE, 0);
605 g->filter
606 = GTK_CHECK_BUTTON(gtk_check_button_new_with_label(_("only show this preset for matching images")));
607 gtk_widget_set_tooltip_text(GTK_WIDGET(g->filter), _("be very careful with this option. "
608 "this might be the last time you see your preset."));
609 gtk_box_pack_start(box, GTK_WIDGET(g->filter), FALSE, FALSE, 0);
610 if(IS_NULL_PTR(g->iop))
611 {
612 // lib usually don't support autoapply
613 gtk_widget_set_no_show_all(GTK_WIDGET(g->autoapply), !dt_presets_module_can_autoapply(g->module_name));
614 // for libs, we don't want the filtering option as it's not implemented...
615 gtk_widget_set_no_show_all(GTK_WIDGET(g->filter), TRUE);
616 }
617 g_signal_connect(G_OBJECT(g->autoapply), "toggled", G_CALLBACK(_check_buttons_activated), g);
618 g_signal_connect(G_OBJECT(g->filter), "toggled", G_CALLBACK(_check_buttons_activated), g);
619
620 int line = 0;
621 g->details = gtk_grid_new();
622 gtk_grid_set_row_spacing(GTK_GRID(g->details), DT_GUI_BOX_SPACING);
623 gtk_grid_set_column_spacing(GTK_GRID(g->details), DT_GUI_BOX_SPACING);
624 gtk_box_pack_start(box, GTK_WIDGET(g->details), TRUE, TRUE, 0);
625
626 GtkWidget *label = NULL;
627
628 // model, maker, lens
629 g->model = gtk_entry_new();
631 gtk_widget_set_hexpand(GTK_WIDGET(g->model), TRUE);
632 /* xgettext:no-c-format */
633 gtk_widget_set_tooltip_text(g->model, _("string to match model (use % as wildcard)"));
634 label = gtk_label_new(_("model"));
635 gtk_widget_set_halign(label, GTK_ALIGN_START);
636 gtk_grid_attach(GTK_GRID(g->details), label, 0, line++, 1, 1);
637 gtk_grid_attach_next_to(GTK_GRID(g->details), g->model, label, GTK_POS_RIGHT, 2, 1);
638
639 g->maker = gtk_entry_new();
641 /* xgettext:no-c-format */
642 gtk_widget_set_tooltip_text(g->maker, _("string to match maker (use % as wildcard)"));
643 label = gtk_label_new(_("maker"));
644 gtk_widget_set_halign(label, GTK_ALIGN_START);
645 gtk_grid_attach(GTK_GRID(g->details), label, 0, line++, 1, 1);
646 gtk_grid_attach_next_to(GTK_GRID(g->details), g->maker, label, GTK_POS_RIGHT, 2, 1);
647
648 g->lens = gtk_entry_new();
650 /* xgettext:no-c-format */
651 gtk_widget_set_tooltip_text(g->lens, _("string to match lens (use % as wildcard)"));
652 label = gtk_label_new(_("lens"));
653 gtk_widget_set_halign(label, GTK_ALIGN_START);
654 gtk_grid_attach(GTK_GRID(g->details), label, 0, line++, 1, 1);
655 gtk_grid_attach_next_to(GTK_GRID(g->details), g->lens, label, GTK_POS_RIGHT, 2, 1);
656
657 // iso
658 label = gtk_label_new(_("ISO"));
659 gtk_widget_set_halign(label, GTK_ALIGN_START);
660 g->iso_min = gtk_spin_button_new_with_range(0, FLT_MAX, 100);
661 gtk_widget_set_tooltip_text(g->iso_min, _("minimum ISO value"));
662 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(g->iso_min), 0);
663 g->iso_max = gtk_spin_button_new_with_range(0, FLT_MAX, 100);
664 gtk_widget_set_tooltip_text(g->iso_max, _("maximum ISO value"));
665 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(g->iso_max), 0);
666 gtk_grid_attach(GTK_GRID(g->details), label, 0, line++, 1, 1);
667 gtk_grid_attach_next_to(GTK_GRID(g->details), g->iso_min, label, GTK_POS_RIGHT, 1, 1);
668 gtk_grid_attach_next_to(GTK_GRID(g->details), g->iso_max, g->iso_min, GTK_POS_RIGHT, 1, 1);
669
670 // exposure
671 label = gtk_label_new(_("exposure"));
672 gtk_widget_set_halign(label, GTK_ALIGN_START);
675 gtk_widget_set_tooltip_text(g->exposure_min, _("minimum exposure time"));
676 gtk_widget_set_tooltip_text(g->exposure_max, _("maximum exposure time"));
677 for(int k = 0; k < dt_gui_presets_exposure_value_cnt; k++)
679 for(int k = 0; k < dt_gui_presets_exposure_value_cnt; k++)
681 gtk_grid_attach(GTK_GRID(g->details), label, 0, line++, 1, 1);
682 gtk_grid_attach_next_to(GTK_GRID(g->details), g->exposure_min, label, GTK_POS_RIGHT, 1, 1);
683 gtk_grid_attach_next_to(GTK_GRID(g->details), g->exposure_max, g->exposure_min, GTK_POS_RIGHT, 1, 1);
684
685 // aperture
686 label = gtk_label_new(_("aperture"));
687 gtk_widget_set_halign(label, GTK_ALIGN_START);
690 gtk_widget_set_tooltip_text(g->aperture_min, _("minimum aperture value"));
691 gtk_widget_set_tooltip_text(g->aperture_max, _("maximum aperture value"));
692 for(int k = 0; k < dt_gui_presets_aperture_value_cnt; k++)
694 for(int k = 0; k < dt_gui_presets_aperture_value_cnt; k++)
696 gtk_grid_attach(GTK_GRID(g->details), label, 0, line++, 1, 1);
697 gtk_grid_attach_next_to(GTK_GRID(g->details), g->aperture_min, label, GTK_POS_RIGHT, 1, 1);
698 gtk_grid_attach_next_to(GTK_GRID(g->details), g->aperture_max, g->aperture_min, GTK_POS_RIGHT, 1, 1);
699
700 // focal length
701 label = gtk_label_new(_("focal length"));
702 gtk_widget_set_halign(label, GTK_ALIGN_START);
703 g->focal_length_min = gtk_spin_button_new_with_range(0, 1000, 10);
704 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(g->focal_length_min), 0);
705 g->focal_length_max = gtk_spin_button_new_with_range(0, 1000, 10);
706 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(g->focal_length_max), 0);
707 gtk_widget_set_tooltip_text(g->focal_length_min, _("minimum focal length"));
708 gtk_widget_set_tooltip_text(g->focal_length_max, _("maximum focal length"));
709 gtk_grid_attach(GTK_GRID(g->details), label, 0, line++, 1, 1);
710 gtk_grid_attach_next_to(GTK_GRID(g->details), g->focal_length_min, label, GTK_POS_RIGHT, 1, 1);
711 gtk_grid_attach_next_to(GTK_GRID(g->details), g->focal_length_max, g->focal_length_min, GTK_POS_RIGHT, 1, 1);
712
713 // raw/hdr/ldr/mono/color
714 label = gtk_label_new(_("format"));
715 gtk_widget_set_halign(label, GTK_ALIGN_START);
716 gtk_grid_attach(GTK_GRID(g->details), label, 0, line, 1, 1);
717 gtk_widget_set_tooltip_text(label, _("select image types you want this preset to be available for"));
718
719 for(int i = 0; i < 5; i++)
720 {
721 g->format_btn[i] = gtk_check_button_new_with_label(_(_gui_presets_format_value_str[i]));
722 gtk_grid_attach(GTK_GRID(g->details), g->format_btn[i], 1, line + i, 2, 1);
723 }
724
725 gtk_widget_set_no_show_all(GTK_WIDGET(g->details), TRUE);
726
727 sqlite3_stmt *stmt;
728 // clang-format off
731 "SELECT rowid, description, model, maker, lens, iso_min, iso_max, "
732 " exposure_min, exposure_max, aperture_min, aperture_max, focal_length_min, "
733 " focal_length_max, autoapply, filter, format"
734 " FROM data.presets"
735 " WHERE name = ?1 AND operation = ?2 AND op_version = ?3",
736 -1, &stmt, NULL);
737 // clang-format on
738 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, g->original_name, -1, SQLITE_TRANSIENT);
739 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, g->operation, -1, SQLITE_TRANSIENT);
740 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, g->op_version);
741 if(sqlite3_step(stmt) == SQLITE_ROW)
742 {
743 g->old_id = sqlite3_column_int(stmt, 0);
744 gtk_entry_set_text(GTK_ENTRY(g->description), (const char *)sqlite3_column_text(stmt, 1));
745 gtk_entry_set_text(GTK_ENTRY(g->model), (const char *)sqlite3_column_text(stmt, 2));
746 gtk_entry_set_text(GTK_ENTRY(g->maker), (const char *)sqlite3_column_text(stmt, 3));
747 gtk_entry_set_text(GTK_ENTRY(g->lens), (const char *)sqlite3_column_text(stmt, 4));
748 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->iso_min), sqlite3_column_double(stmt, 5));
749 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->iso_max), sqlite3_column_double(stmt, 6));
750
751 float val = sqlite3_column_double(stmt, 7);
752 int k = 0;
753 for(; k < dt_gui_presets_exposure_value_cnt && val > dt_gui_presets_exposure_value[k]; k++)
754 ;
755 dt_bauhaus_combobox_set(g->exposure_min, k);
756 val = sqlite3_column_double(stmt, 8);
757 for(k = 0; k < dt_gui_presets_exposure_value_cnt && val > dt_gui_presets_exposure_value[k]; k++)
758 ;
759 dt_bauhaus_combobox_set(g->exposure_max, k);
760 val = sqlite3_column_double(stmt, 9);
761 for(k = 0; k < dt_gui_presets_aperture_value_cnt && val > dt_gui_presets_aperture_value[k]; k++)
762 ;
763 dt_bauhaus_combobox_set(g->aperture_min, k);
764 val = sqlite3_column_double(stmt, 10);
765 for(k = 0; k < dt_gui_presets_aperture_value_cnt && val > dt_gui_presets_aperture_value[k]; k++)
766 ;
767 dt_bauhaus_combobox_set(g->aperture_max, k);
768 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->focal_length_min), sqlite3_column_double(stmt, 11));
769 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->focal_length_max), sqlite3_column_double(stmt, 12));
770 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->autoapply), sqlite3_column_int(stmt, 13));
771 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->filter), sqlite3_column_int(stmt, 14));
772 const int format = (sqlite3_column_int(stmt, 15)) ^ DT_PRESETS_FOR_NOT;
773 for(k = 0; k < 5; k++)
774 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->format_btn[k]), format & (_gui_presets_format_flag[k]));
775 }
776 else
777 {
778 gtk_entry_set_text(GTK_ENTRY(g->description), "");
779 gtk_entry_set_text(GTK_ENTRY(g->model), "%");
780 gtk_entry_set_text(GTK_ENTRY(g->maker), "%");
781 gtk_entry_set_text(GTK_ENTRY(g->lens), "%");
782 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->iso_min), 0);
783 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->iso_max), FLT_MAX);
784
785 float val = 0;
786 int k = 0;
787 for(; k < dt_gui_presets_exposure_value_cnt && val > dt_gui_presets_exposure_value[k]; k++)
788 ;
789 dt_bauhaus_combobox_set(g->exposure_min, k);
790 val = 100000000;
791 for(k = 0; k < dt_gui_presets_exposure_value_cnt && val > dt_gui_presets_exposure_value[k]; k++)
792 ;
793 dt_bauhaus_combobox_set(g->exposure_max, k);
794 val = 0;
795 for(k = 0; k < dt_gui_presets_aperture_value_cnt && val > dt_gui_presets_aperture_value[k]; k++)
796 ;
797 dt_bauhaus_combobox_set(g->aperture_min, k);
798 val = 100000000;
799 for(k = 0; k < dt_gui_presets_aperture_value_cnt && val > dt_gui_presets_aperture_value[k]; k++)
800 ;
801 dt_bauhaus_combobox_set(g->aperture_max, k);
802 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->focal_length_min), 0);
803 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->focal_length_max), 1000);
804 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->autoapply), 0);
805 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->filter), 0);
806 for(k = 0; k < 5; k++) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->format_btn[k]), TRUE);
807 }
808 sqlite3_finalize(stmt);
809
810 // disable remove button if needed
811 if(!allow_remove || g->old_id < 0)
812 {
813 GtkWidget *w = gtk_dialog_get_widget_for_response(GTK_DIALOG(dialog), GTK_RESPONSE_REJECT);
814 if(w) gtk_widget_set_sensitive(w, FALSE);
815 }
816 // disable export button if the preset is not already in the database
817 if(g->old_id < 0)
818 {
819 GtkWidget *w = gtk_dialog_get_widget_for_response(GTK_DIALOG(dialog), GTK_RESPONSE_YES);
820 if(w) gtk_widget_set_sensitive(w, FALSE);
821 }
822
823 // put focus on cancel button if 2 first entries deactivated
824 if(!allow_desc_change && !allow_name_change)
825 {
826 GtkWidget *w = gtk_dialog_get_widget_for_response(GTK_DIALOG(dialog), GTK_RESPONSE_CANCEL);
827 if(w) gtk_widget_grab_focus(w);
828 }
829
830 g_signal_connect(dialog, "response", G_CALLBACK(_edit_preset_response), g);
831 gtk_widget_show_all(dialog);
832}
833
834void dt_gui_presets_show_iop_edit_dialog(const char *name_in, dt_iop_module_t *module, GCallback final_callback,
835 gpointer data, gboolean allow_name_change, gboolean allow_desc_change,
836 gboolean allow_remove, GtkWindow *parent)
837{
840 g->old_id = -1;
841 g->original_name = g_strdup(name_in);
842 g->iop = module;
843 g->operation = g_strdup(module->op);
844 g->op_version = module->version();
845 g->module_name = g_strdup(module->name());
846 g->callback = final_callback;
847 g->data = data;
848 g->parent = parent;
849
850 _presets_show_edit_dialog(g, allow_name_change, allow_desc_change, allow_remove);
851}
852
853void dt_gui_presets_show_edit_dialog(const char *name_in, const char *module_name, int rowid,
854 GCallback final_callback, gpointer data, gboolean allow_name_change,
855 gboolean allow_desc_change, gboolean allow_remove, GtkWindow *parent)
856{
857 sqlite3_stmt *stmt;
859 "SELECT operation, op_version FROM data.presets WHERE rowid = ?1", -1, &stmt, NULL);
860 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, rowid);
861 if(sqlite3_step(stmt) == SQLITE_ROW)
862 {
865 g->old_id = rowid;
866 g->original_name = g_strdup(name_in);
867 g->operation = g_strdup((char *)sqlite3_column_text(stmt, 0));
868 g->op_version = sqlite3_column_int(stmt, 1);
869 g->module_name = g_strdup(module_name);
870 g->callback = final_callback;
871 g->data = data;
872 g->parent = parent;
873
874 sqlite3_finalize(stmt);
875
876 _presets_show_edit_dialog(g, allow_name_change, allow_desc_change, allow_remove);
877 }
878 else
879 sqlite3_finalize(stmt);
880}
881
882static void _edit_preset(const char *name_in, dt_iop_module_t *module)
883{
884 gchar *name = NULL;
885 if(IS_NULL_PTR(name_in))
886 {
887 int writeprotect = -1;
888 name = _get_active_preset_name(module, &writeprotect);
889 if(IS_NULL_PTR(name)) return;
890 if(writeprotect)
891 {
892 dt_control_log(_("preset `%s' is write-protected! can't edit it!"), name);
893 dt_free(name);
894 return;
895 }
896 }
897 else
898 name = g_strdup(name_in);
899
901 FALSE, GTK_WINDOW(dt_ui_main_window(darktable.gui->ui)));
902 dt_free(name);
903}
904
905static void _menuitem_edit_preset(GtkMenuItem *menuitem, dt_iop_module_t *module)
906{
907 _edit_preset(NULL, module);
908}
909
910static void _menuitem_update_preset(GtkMenuItem *menuitem, dt_iop_module_t *module)
911{
912 gchar *name = g_object_get_data(G_OBJECT(menuitem), "dt-preset-name");
913
914 gint res = GTK_RESPONSE_YES;
915
916 if(dt_conf_get_bool("plugins/lighttable/preset/ask_before_delete_preset"))
917 {
919 GtkWidget *dialog
920 = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION,
921 GTK_BUTTONS_YES_NO, _("do you really want to update the preset `%s'?"), name);
922#ifdef GDK_WINDOWING_QUARTZ
924#endif
925 gtk_window_set_title(GTK_WINDOW(dialog), _("update preset?"));
926 res = gtk_dialog_run(GTK_DIALOG(dialog));
927 GtkWindow *dialog_parent = gtk_window_get_transient_for(GTK_WINDOW(dialog));
928 gtk_widget_destroy(dialog);
929 dt_gui_refocus_parent(dialog_parent);
930 }
931
932 if(res == GTK_RESPONSE_YES)
933 {
934 // commit all the module fields
935 sqlite3_stmt *stmt;
937 "UPDATE data.presets"
938 " SET op_version=?2, op_params=?3, enabled=?4, "
939 " blendop_params=?5, blendop_version=?6"
940 " WHERE name=?7 AND operation=?1",
941 -1, &stmt, NULL);
942
943 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, module->op, -1, SQLITE_TRANSIENT);
944 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, module->version());
945 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 3, module->params, module->params_size, SQLITE_TRANSIENT);
946 DT_DEBUG_SQLITE3_BIND_INT(stmt, 4, module->enabled);
948 SQLITE_TRANSIENT);
950 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 7, name, -1, SQLITE_TRANSIENT);
951 sqlite3_step(stmt);
952 sqlite3_finalize(stmt);
953 }
954}
955
956static void _menuitem_new_preset(GtkMenuItem *menuitem, dt_iop_module_t *module)
957{
958 // add new preset
959 dt_lib_presets_remove(_("new preset"), module->op, module->version());
960
961 // then show edit dialog
962 _edit_preset(_("new preset"), module);
963}
964
966{
967 sqlite3_stmt *stmt;
968 // clang-format off
971 "SELECT op_params, enabled, blendop_params, blendop_version, writeprotect"
972 " FROM data.presets"
973 " WHERE operation = ?1 AND op_version = ?2 AND name = ?3",
974 -1, &stmt, NULL);
975 // clang-format on
976 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, module->op, -1, SQLITE_TRANSIENT);
977 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, module->version());
978 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, name, -1, SQLITE_TRANSIENT);
979
980 if(sqlite3_step(stmt) == SQLITE_ROW)
981 {
982 const void *op_params = sqlite3_column_blob(stmt, 0);
983 const int op_length = sqlite3_column_bytes(stmt, 0);
984 const int enabled = sqlite3_column_int(stmt, 1);
985 const void *blendop_params = sqlite3_column_blob(stmt, 2);
986 const int bl_length = sqlite3_column_bytes(stmt, 2);
987 const int blendop_version = sqlite3_column_int(stmt, 3);
988 const int writeprotect = sqlite3_column_int(stmt, 4);
989 if(op_params && (op_length == module->params_size))
990 {
991 memcpy(module->params, op_params, op_length);
992 module->enabled = enabled;
993 }
994 if(blendop_params && (blendop_version == dt_develop_blend_version())
995 && (bl_length == sizeof(dt_develop_blend_params_t)))
996 {
997 dt_iop_commit_blend_params(module, blendop_params);
998 }
999 else if(blendop_params
1000 && dt_develop_blend_legacy_params(module, blendop_params, blendop_version, module->blend_params,
1001 dt_develop_blend_version(), bl_length) == 0)
1002 {
1003 // do nothing
1004 }
1005 else
1006 {
1008 }
1009
1010 if(!writeprotect) dt_gui_store_last_preset(name);
1011 }
1012 sqlite3_finalize(stmt);
1013 dt_iop_gui_update(module);
1015 gtk_widget_queue_draw(module->widget);
1016}
1017
1018static void _menuitem_pick_preset(GtkMenuItem *menuitem, dt_iop_module_t *module)
1019{
1020 gchar *name = g_object_get_data(G_OBJECT(menuitem), "dt-preset-name");
1022}
1023
1025{
1026 dt_image_t *image = &module->dev->image_storage;
1027 const gboolean has_matrix = dt_image_is_matrix_correction_supported(image);
1028
1029 char query[2024];
1030 // clang-format off
1031 snprintf(query, sizeof(query),
1032 "SELECT name"
1033 " FROM data.presets"
1034 " WHERE operation = ?1"
1035 " AND ((autoapply=1"
1036 " AND ((?2 LIKE model AND ?3 LIKE maker) OR (?4 LIKE model AND ?5 LIKE maker))"
1037 " AND ?6 LIKE lens AND ?7 BETWEEN iso_min AND iso_max"
1038 " AND ?8 BETWEEN exposure_min AND exposure_max"
1039 " AND ?9 BETWEEN aperture_min AND aperture_max"
1040 " AND ?10 BETWEEN focal_length_min AND focal_length_max"
1041 " AND (format = 0 OR (format&?11 != 0 AND ~format&?12 != 0))"
1042 " AND operation NOT IN"
1043 " ('ioporder', 'metadata', 'export', 'tagging', 'collect', 'basecurve'))"
1044 " OR (name = ?13)) AND op_version = ?14");
1045 // clang-format on
1046
1047 sqlite3_stmt *stmt;
1048 const char *workflow_preset = (has_matrix) ? _("scene-referred default") : "\t\n";
1049 int iformat = 0;
1050 if(dt_image_needs_rawprepare(image)) iformat |= FOR_RAW;
1051 else iformat |= FOR_LDR;
1052 if(dt_image_is_hdr(image)) iformat |= FOR_HDR;
1053
1054 int excluded = 0;
1055 if(dt_image_monochrome_flags(image)) excluded |= FOR_NOT_MONO;
1056 else excluded |= FOR_NOT_COLOR;
1057
1058 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
1059 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, module->op, -1, SQLITE_TRANSIENT);
1060 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, image->exif_model, -1, SQLITE_TRANSIENT);
1061 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, image->exif_maker, -1, SQLITE_TRANSIENT);
1062 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, image->camera_alias, -1, SQLITE_TRANSIENT);
1063 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 5, image->camera_maker, -1, SQLITE_TRANSIENT);
1064 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 6, image->exif_lens, -1, SQLITE_TRANSIENT);
1065 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 7, fmaxf(0.0f, fminf(FLT_MAX, image->exif_iso)));
1066 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 8, fmaxf(0.0f, fminf(1000000, image->exif_exposure)));
1067 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 9, fmaxf(0.0f, fminf(1000000, image->exif_aperture)));
1068 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 10, fmaxf(0.0f, fminf(1000000, image->exif_focal_length)));
1069 // 0: dontcare, 1: ldr, 2: raw plus monochrome & color
1070 DT_DEBUG_SQLITE3_BIND_INT(stmt, 11, iformat);
1071 DT_DEBUG_SQLITE3_BIND_INT(stmt, 12, excluded);
1072 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 13, workflow_preset, -1, SQLITE_TRANSIENT);
1073 DT_DEBUG_SQLITE3_BIND_INT(stmt, 14, module->version());
1074
1075 gboolean applied = FALSE;
1076 while(sqlite3_step(stmt) == SQLITE_ROW)
1077 {
1078 const char *name = (const char *)sqlite3_column_text(stmt, 0);
1080 applied = TRUE;
1081 }
1082 sqlite3_finalize(stmt);
1083
1084 return applied;
1085}
1086
1087static gboolean _menuitem_button_released_preset(GtkMenuItem *menuitem, GdkEventButton *event,
1088 dt_iop_module_t *module)
1089{
1090 if (event->button == 1 || (module->flags() & IOP_FLAGS_ONE_INSTANCE))
1091 {
1092 _menuitem_pick_preset(menuitem, module);
1093 }
1094 else if (event->button == 3)
1095 {
1096 dt_iop_module_t *new_module = dt_iop_gui_duplicate(module, FALSE);
1097 if(new_module) _menuitem_pick_preset(menuitem, new_module);
1098 dt_iop_gui_rename_module(new_module);
1099 }
1100
1101 return FALSE;
1102}
1103
1104#ifdef HAVE_OPENCL
1105static void _opencl_disable_callback(GtkButton *button, dt_iop_module_t *module)
1106{
1107 gboolean active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(button));
1108 gchar *string = g_strdup_printf("/plugins/%s/opencl", module->op);
1109 dt_conf_set_bool(string, active);
1110 dt_free(string);
1111}
1112
1113static void _cache_disable_callback(GtkButton *button, dt_iop_module_t *module)
1114{
1115 gboolean active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(button));
1116 gchar *string = g_strdup_printf("/plugins/%s/cache", module->op);
1117 dt_conf_set_bool(string, active);
1118 dt_free(string);
1119}
1120#endif
1121
1122// preset names containing '|' are split into a nested submenu hierarchy, the same way
1123// style names (src/libs/styles.c, src/gui/actions/styles.c) and tag names
1124// (src/libs/tagging.c) are grouped into a tree: every non-empty '|'-separated segment but
1125// the last becomes an intermediate submenu, the last segment is the leaf entry. `path` is
1126// the '|'-joined prefix built so far and is used as the cache key so a shared prefix reuses
1127// the same submenu instead of creating a duplicate.
1128static GtkWidget *_presets_get_submenu(GtkWidget *parent, GHashTable *submenus, const gchar *path,
1129 const gchar *label)
1130{
1131 GtkWidget *submenu = g_hash_table_lookup(submenus, path);
1132 if(submenu) return submenu;
1133
1134 GtkWidget *item = gtk_menu_item_new_with_label(label);
1135 submenu = gtk_menu_new();
1136 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
1137 gtk_menu_shell_append(GTK_MENU_SHELL(parent), item);
1138
1139 g_hash_table_insert(submenus, g_strdup(path), submenu);
1140 return submenu;
1141}
1142
1144 dt_iop_params_t *params, int32_t params_size,
1145 dt_develop_blend_params_t *bl_params, dt_iop_module_t *module,
1146 const dt_image_t *image,
1147 void (*pick_callback)(GtkMenuItem *, void *),
1148 void *callback_data)
1149{
1150 GtkMenu *menu = darktable.gui->presets_popup_menu;
1151 if(menu) gtk_widget_destroy(GTK_WIDGET(menu));
1152 darktable.gui->presets_popup_menu = GTK_MENU(gtk_menu_new());
1154 const gboolean hide_default = dt_conf_get_bool("plugins/darkroom/hide_default_presets");
1155 const gboolean default_first = dt_conf_get_bool("modules/default_presets_first");
1156
1157 gchar *query = NULL;
1158
1159 GtkWidget *mi;
1160 int active_preset = -1, cnt = 0, writeprotect = 0; //, selected_default = 0;
1161 sqlite3_stmt *stmt;
1162 // order: get shipped defaults first
1163 if(image)
1164 {
1165 // only matching if filter is on:
1166 int iformat = 0;
1167 if(dt_image_needs_rawprepare(image))
1168 iformat |= FOR_RAW;
1169 else
1170 iformat |= FOR_LDR;
1171
1172 if(dt_image_is_hdr(image))
1173 iformat |= FOR_HDR;
1174
1175 int excluded = 0;
1176 if(dt_image_monochrome_flags(image))
1177 excluded |= FOR_NOT_MONO;
1178 else
1179 excluded |= FOR_NOT_COLOR;
1180
1181 // clang-format off
1182 query = g_strdup_printf
1183 ("SELECT name, op_params, writeprotect, description, blendop_params, "
1184 " op_version, enabled"
1185 " FROM data.presets"
1186 " WHERE operation=?1"
1187 " AND (filter=0"
1188 " OR"
1189 " (((?2 LIKE model AND ?3 LIKE maker) OR (?4 LIKE model AND ?5 LIKE maker))"
1190 " AND ?6 LIKE lens"
1191 " AND ?7 BETWEEN iso_min AND iso_max"
1192 " AND ?8 BETWEEN exposure_min AND exposure_max"
1193 " AND ?9 BETWEEN aperture_min AND aperture_max"
1194 " AND ?10 BETWEEN focal_length_min AND focal_length_max"
1195 " AND (format = 0 OR (format&?11 != 0 AND ~format&?12 != 0))))"
1196 " ORDER BY writeprotect %s, LOWER(name), rowid",
1197 default_first ? "DESC":"ASC");
1198 // clang-format on
1199
1200 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
1201 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, op, -1, SQLITE_TRANSIENT);
1202 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, image->exif_model, -1, SQLITE_TRANSIENT);
1203 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, image->exif_maker, -1, SQLITE_TRANSIENT);
1204 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, image->camera_alias, -1, SQLITE_TRANSIENT);
1205 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 5, image->camera_maker, -1, SQLITE_TRANSIENT);
1206 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 6, image->exif_lens, -1, SQLITE_TRANSIENT);
1207 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 7, image->exif_iso);
1211 DT_DEBUG_SQLITE3_BIND_INT(stmt, 11, iformat);
1212 DT_DEBUG_SQLITE3_BIND_INT(stmt, 12, excluded);
1213 }
1214 else
1215 {
1216 // don't know for which image. show all we got:
1217
1218 query = g_strdup_printf("SELECT name, op_params, writeprotect, "
1219 " description, blendop_params, op_version, enabled"
1220 " FROM data.presets"
1221 " WHERE operation=?1"
1222 " ORDER BY writeprotect %s, LOWER(name), rowid",
1223 default_first ? "DESC":"ASC"
1224 );
1225
1226 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
1227 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, op, -1, SQLITE_TRANSIENT);
1228 }
1229 dt_free(query);
1230 // collect all presets for op from db
1231 gboolean found = 0;
1232 int last_wp = -1;
1233 GHashTable *submenus = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
1234 while(sqlite3_step(stmt) == SQLITE_ROW)
1235 {
1236 const int chk_writeprotect = sqlite3_column_int(stmt, 2);
1237 if(hide_default && chk_writeprotect)
1238 {
1239 //skip default module if set to hide them.
1240 continue;
1241 }
1242 if(last_wp == -1)
1243 {
1244 last_wp = chk_writeprotect;
1245 }
1246 else if(last_wp != chk_writeprotect)
1247 {
1248 last_wp = chk_writeprotect;
1249 gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
1250 }
1251 const void *op_params = (void *)sqlite3_column_blob(stmt, 1);
1252 const int32_t op_params_size = sqlite3_column_bytes(stmt, 1);
1253 const void *blendop_params = (void *)sqlite3_column_blob(stmt, 4);
1254 const int32_t bl_params_size = sqlite3_column_bytes(stmt, 4);
1255 const int32_t preset_version = sqlite3_column_int(stmt, 5);
1256 const int32_t enabled = sqlite3_column_int(stmt, 6);
1257 const int32_t isdisabled = (preset_version == version ? 0 : 1);
1258 const char *name = (char *)sqlite3_column_text(stmt, 0);
1259 gboolean isdefault = FALSE;
1260
1261 if(darktable.gui->last_preset && strcmp(darktable.gui->last_preset, name) == 0)
1262 found = TRUE;
1263
1264 if(module
1265 && !memcmp(module->default_params, op_params,
1266 MIN(op_params_size, module->params_size))
1267 && !memcmp(module->default_blendop_params, blendop_params,
1268 MIN(bl_params_size, sizeof(dt_develop_blend_params_t))))
1269 isdefault = TRUE;
1270
1271 gchar **split = g_strsplit(name, "|", -1);
1272 int leaf = -1;
1273 for(int i = 0; split[i]; i++)
1274 if(split[i][0] != '\0') leaf = i;
1275
1276 GtkWidget *parent_menu = GTK_WIDGET(menu);
1277 if(leaf > 0)
1278 {
1279 GString *path = g_string_new(NULL);
1280 for(int i = 0; i < leaf; i++)
1281 {
1282 if(split[i][0] == '\0') continue;
1283 if(path->len > 0) g_string_append_c(path, '|');
1284 g_string_append(path, split[i]);
1285 parent_menu = _presets_get_submenu(parent_menu, submenus, path->str, split[i]);
1286 }
1287 g_string_free(path, TRUE);
1288 }
1289 const gchar *leaf_name = leaf >= 0 ? split[leaf] : name;
1290
1291 gchar *label;
1292 if(isdefault)
1293 label = g_strdup_printf("%s %s", leaf_name, _("(default)"));
1294 else
1295 label = g_strdup(leaf_name);
1296 mi = gtk_menu_item_new_with_label(label);
1297
1298 dt_free(label);
1299 g_strfreev(split);
1300
1301 if(module
1302 && !memcmp(params, op_params, MIN(op_params_size, params_size))
1303 && !memcmp(bl_params, blendop_params, MIN(bl_params_size, sizeof(dt_develop_blend_params_t)))
1304 && module->enabled == enabled)
1305 {
1306 active_preset = cnt;
1307 writeprotect = sqlite3_column_int(stmt, 2);
1308 dt_gui_add_class(mi, "menu-active");
1309 }
1310
1311 if(isdisabled)
1312 {
1313 gtk_widget_set_sensitive(mi, 0);
1314 gtk_widget_set_tooltip_text(mi, _("disabled: wrong module version"));
1315 }
1316 else
1317 {
1318 g_object_set_data_full(G_OBJECT(mi), "dt-preset-name", g_strdup(name), g_free);
1319 if(module)
1320 {
1321 g_signal_connect(G_OBJECT(mi), "button-release-event", G_CALLBACK(_menuitem_button_released_preset),
1322 module);
1323 }
1324 else if(pick_callback)
1325 g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(pick_callback), callback_data);
1326 gtk_widget_set_tooltip_text(mi, (const char *)sqlite3_column_text(stmt, 3));
1327 }
1328 gtk_menu_shell_append(GTK_MENU_SHELL(parent_menu), mi);
1329 cnt++;
1330 }
1331 sqlite3_finalize(stmt);
1332 g_hash_table_destroy(submenus);
1333
1334 if(cnt > 0) gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
1335
1336 if(module)
1337 {
1338 if(active_preset >= 0 && !writeprotect)
1339 {
1340 mi = gtk_menu_item_new_with_label(_("edit this preset.."));
1341 g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(_menuitem_edit_preset), module);
1342 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1343
1344 mi = gtk_menu_item_new_with_label(_("delete this preset"));
1345 g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(_menuitem_delete_preset), module);
1346 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1347 }
1348 else
1349 {
1350 mi = gtk_menu_item_new_with_label(_("store new preset.."));
1351 g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(_menuitem_new_preset), module);
1352 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1353
1354 if(darktable.gui->last_preset && found)
1355 {
1356 char *markup = g_markup_printf_escaped("%s <span weight='bold'>%s</span>", _("update preset"),
1358 mi = gtk_menu_item_new_with_label("");
1359 gtk_label_set_markup(GTK_LABEL(gtk_bin_get_child(GTK_BIN(mi))), markup);
1360 g_object_set_data_full(G_OBJECT(mi), "dt-preset-name", g_strdup(darktable.gui->last_preset), g_free);
1361 g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(_menuitem_update_preset), module);
1362 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1363 dt_free(markup);
1364 }
1365 }
1366 }
1367
1368 // and the parameters entry if needed
1369 if(module && (module->set_preferences))
1370 {
1371 gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
1372 if(module->set_preferences) module->set_preferences(GTK_MENU_SHELL(menu), module);
1373 }
1374
1375#ifdef HAVE_OPENCL
1376 // OpenCL prefs
1377 if(module && module->process_cl)
1378 {
1379 gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
1380
1381 GtkWidget *item = gtk_check_menu_item_new_with_label(_("Use OpenCL (GPU computing)"));
1382 gtk_widget_set_tooltip_text(item, _("Run this module on GPU if possible.\n"
1383 "Disable if you face recurring issues on GPU with this module.\n"
1384 "Does not require a restart."));
1385 gchar *string = g_strdup_printf("/plugins/%s/opencl", module->op);
1386
1387 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), dt_conf_get_bool(string));
1388 dt_free(string);
1389
1390 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(_opencl_disable_callback), module);
1391 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1392
1393 item = gtk_check_menu_item_new_with_label(_("Cache the GPU output"));
1394 gtk_widget_set_tooltip_text(item, _("Store the output of this module in cache when running on GPU.\n"
1395 "This may prevent some recomputations, at the cost of more memory I/O.\n"
1396 "The trade-off is worth it only for slow modules."));
1397 string = g_strdup_printf("/plugins/%s/cache", module->op);
1398
1399 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), dt_conf_get_bool(string));
1400 dt_free(string);
1401
1402 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(_cache_disable_callback), module);
1403 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1404 }
1405#endif
1406}
1407
1409 int32_t params_size, void *blendop_params,
1410 const dt_image_t *image,
1411 void (*pick_callback)(GtkMenuItem *, void *),
1412 void *callback_data)
1413{
1414 _gui_presets_popup_menu_show_internal(op, version, params, params_size, blendop_params, NULL, image,
1415 pick_callback, callback_data);
1416}
1417
1419{
1420 _gui_presets_popup_menu_show_internal(module->op, module->version(), module->params, module->params_size,
1421 module->blend_params, module, &module->dev->image_storage, NULL, NULL);
1422}
1423
1424void dt_gui_presets_update_mml(const char *name, dt_dev_operation_t op, const int32_t version,
1425 const char *maker, const char *model, const char *lens)
1426{
1428 {
1429 // clang-format off¨
1432 "UPDATE data.presets"
1433 " SET maker='%' || ?1 || '%', model=?2, lens=?3"
1434 " WHERE operation=?4 AND op_version=?5 AND name=?6", -1,
1436 // clang-format on
1437 }
1438 sqlite3_stmt *stmt = _gui_presets_update_mml_stmt;
1439 sqlite3_reset(stmt);
1440 sqlite3_clear_bindings(stmt);
1441 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, maker, -1, SQLITE_TRANSIENT);
1442 if (*model)
1443 {
1444 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, model, -1, SQLITE_TRANSIENT);
1445 }
1446 else
1447 {
1448 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, "%", -1, SQLITE_TRANSIENT);
1449 }
1450 if (*lens)
1451 {
1452 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, lens, -1, SQLITE_TRANSIENT);
1453 }
1454 else
1455 {
1456 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, "%", -1, SQLITE_TRANSIENT);
1457 }
1458 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, op, -1, SQLITE_TRANSIENT);
1459 DT_DEBUG_SQLITE3_BIND_INT(stmt, 5, version);
1460 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 6, name, -1, SQLITE_TRANSIENT);
1461 sqlite3_step(stmt);
1462}
1463
1464void dt_gui_presets_update_iso(const char *name, dt_dev_operation_t op, const int32_t version,
1465 const float min, const float max)
1466{
1468 {
1469 // clang-format off
1472 "UPDATE data.presets"
1473 " SET iso_min=?1, iso_max=?2"
1474 " WHERE operation=?3 AND op_version=?4 AND name=?5", -1, &_gui_presets_update_iso_stmt,
1475 NULL);
1476 // clang-format on
1477 }
1478 sqlite3_stmt *stmt = _gui_presets_update_iso_stmt;
1479 sqlite3_reset(stmt);
1480 sqlite3_clear_bindings(stmt);
1483 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, op, -1, SQLITE_TRANSIENT);
1484 DT_DEBUG_SQLITE3_BIND_INT(stmt, 4, version);
1485 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 5, name, -1, SQLITE_TRANSIENT);
1486 sqlite3_step(stmt);
1487}
1488
1489void dt_gui_presets_update_av(const char *name, dt_dev_operation_t op, const int32_t version, const float min,
1490 const float max)
1491{
1493 {
1494 // clang-format off
1497 "UPDATE data.presets"
1498 " SET aperture_min=?1, aperture_max=?2"
1499 " WHERE operation=?3 AND op_version=?4 AND name=?5",
1500 -1, &_gui_presets_update_av_stmt, NULL);
1501 // clang-format on
1502 }
1503 sqlite3_stmt *stmt = _gui_presets_update_av_stmt;
1504 sqlite3_reset(stmt);
1505 sqlite3_clear_bindings(stmt);
1508 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, op, -1, SQLITE_TRANSIENT);
1509 DT_DEBUG_SQLITE3_BIND_INT(stmt, 4, version);
1510 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 5, name, -1, SQLITE_TRANSIENT);
1511 sqlite3_step(stmt);
1512}
1513
1514void dt_gui_presets_update_tv(const char *name, dt_dev_operation_t op, const int32_t version, const float min,
1515 const float max)
1516{
1518 {
1521 "UPDATE data.presets SET exposure_min=?1, exposure_max=?2 WHERE operation=?3 AND op_version=?4 AND name=?5",
1522 -1, &_gui_presets_update_tv_stmt, NULL);
1523 }
1524 sqlite3_stmt *stmt = _gui_presets_update_tv_stmt;
1525 sqlite3_reset(stmt);
1526 sqlite3_clear_bindings(stmt);
1529 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, op, -1, SQLITE_TRANSIENT);
1530 DT_DEBUG_SQLITE3_BIND_INT(stmt, 4, version);
1531 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 5, name, -1, SQLITE_TRANSIENT);
1532 sqlite3_step(stmt);
1533}
1534
1535void dt_gui_presets_update_fl(const char *name, dt_dev_operation_t op, const int32_t version, const float min,
1536 const float max)
1537{
1539 {
1540 // clang-format off
1542 "UPDATE data.presets"
1543 " SET focal_length_min=?1, focal_length_max=?2"
1544 " WHERE operation=?3 AND op_version=?4 AND name=?5",
1545 -1, &_gui_presets_update_fl_stmt, NULL);
1546 // clang-format on
1547 }
1548 sqlite3_stmt *stmt = _gui_presets_update_fl_stmt;
1549 sqlite3_reset(stmt);
1550 sqlite3_clear_bindings(stmt);
1553 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, op, -1, SQLITE_TRANSIENT);
1554 DT_DEBUG_SQLITE3_BIND_INT(stmt, 4, version);
1555 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 5, name, -1, SQLITE_TRANSIENT);
1556 sqlite3_step(stmt);
1557}
1558
1559void dt_gui_presets_update_ldr(const char *name, dt_dev_operation_t op, const int32_t version,
1560 const int ldrflag)
1561{
1563 {
1564 // clang-format off
1566 "UPDATE data.presets"
1567 " SET format=?1"
1568 " WHERE operation=?2 AND op_version=?3 AND name=?4",
1569 -1, &_gui_presets_update_ldr_stmt, NULL);
1570 // clang-format on
1571 }
1572 sqlite3_stmt *stmt = _gui_presets_update_ldr_stmt;
1573 sqlite3_reset(stmt);
1574 sqlite3_clear_bindings(stmt);
1575 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, ldrflag);
1576 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, op, -1, SQLITE_TRANSIENT);
1577 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, version);
1578 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, name, -1, SQLITE_TRANSIENT);
1579 sqlite3_step(stmt);
1580}
1581
1582void dt_gui_presets_update_autoapply(const char *name, dt_dev_operation_t op, const int32_t version,
1583 const int autoapply)
1584{
1586 {
1587 // clang-format off
1590 "UPDATE data.presets"
1591 " SET autoapply=?1"
1592 " WHERE operation=?2 AND op_version=?3 AND name=?4", -1, &_gui_presets_update_autoapply_stmt, NULL);
1593 // clang-format on
1594 }
1595 sqlite3_stmt *stmt = _gui_presets_update_autoapply_stmt;
1596 sqlite3_reset(stmt);
1597 sqlite3_clear_bindings(stmt);
1598 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, autoapply);
1599 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, op, -1, SQLITE_TRANSIENT);
1600 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, version);
1601 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, name, -1, SQLITE_TRANSIENT);
1602 sqlite3_step(stmt);
1603}
1604
1605void dt_gui_presets_update_filter(const char *name, dt_dev_operation_t op, const int32_t version,
1606 const int filter)
1607{
1609 {
1610 // clang-format off
1612 "UPDATE data.presets"
1613 " SET filter=?1"
1614 " WHERE operation=?2 AND op_version=?3 AND name=?4",
1616 // clang-format on
1617 }
1618 sqlite3_stmt *stmt = _gui_presets_update_filter_stmt;
1619 sqlite3_reset(stmt);
1620 sqlite3_clear_bindings(stmt);
1621 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, filter);
1622 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, op, -1, SQLITE_TRANSIENT);
1623 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, version);
1624 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, name, -1, SQLITE_TRANSIENT);
1625 sqlite3_step(stmt);
1626}
1627
1628// clang-format off
1629// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
1630// vim: shiftwidth=2 expandtab tabstop=2 cindent
1631// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
1632// clang-format on
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
size_t params_size(dt_imageio_module_format_t *self)
Definition avif.c:565
int dt_bauhaus_combobox_get(GtkWidget *widget)
Definition bauhaus.c:2350
void dt_bauhaus_combobox_set(GtkWidget *widget, const int pos)
Definition bauhaus.c:2304
GtkWidget * dt_bauhaus_combobox_new(dt_bauhaus_t *bh, dt_gui_module_t *self)
Definition bauhaus.c:1845
void dt_bauhaus_combobox_add(GtkWidget *widget, const char *text)
Definition bauhaus.c:2019
void dt_develop_blend_init_blend_parameters(dt_develop_blend_params_t *blend_params, dt_develop_blend_colorspace_t cst)
Definition blend.c:158
int dt_develop_blend_version(void)
Definition blend.c:1651
int dt_develop_blend_legacy_params(dt_iop_module_t *module, const void *const old_params, const int old_version, void *new_params, const int new_version, const int length)
Definition blend.c:1715
dt_develop_blend_colorspace_t
Definition blend.h:55
static const float const float const float min
const float max
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
gboolean dt_image_is_matrix_correction_supported(const dt_image_t *img)
int dt_image_monochrome_flags(const dt_image_t *img)
gboolean dt_image_is_hdr(const dt_image_t *img)
gboolean dt_image_needs_rawprepare(const dt_image_t *img)
char * name
void dt_presets_save_to_file(const int rowid, const char *preset_name, const char *filedir)
gboolean dt_presets_module_can_autoapply(const gchar *operation)
const char darktable_package_version[]
void dt_conf_set_bool(const char *name, int val)
int dt_conf_get_bool(const char *name)
gchar * dt_conf_get_string(const char *name)
void dt_conf_set_string(const char *name, const char *val)
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
darktable_t darktable
Definition darktable.c:183
#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_EXEC(a, b, c, d, e)
Definition debug.h:99
#define DT_DEBUG_SQLITE3_BIND_BLOB(a, b, c, d, e)
Definition debug.h:119
#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
#define DT_DEBUG_SQLITE3_BIND_DOUBLE(a, b, c)
Definition debug.h:117
#define dt_dev_add_history_item(dev, module, enable, redraw)
void dt_iop_params_t
Definition dev_history.h:42
void dt_gui_store_last_preset(const char *name)
Definition gtk.c:556
void dt_gui_refocus_parent(GtkWindow *parent)
Definition gtk.c:1936
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
GtkWidget * dt_ui_main_window(dt_ui_t *ui)
get the main window widget
#define DT_GUI_BOX_SPACING
Definition gtk.h:109
static sqlite3_stmt * _gui_presets_update_autoapply_stmt
gboolean dt_gui_presets_autoapply_for_module(dt_iop_module_t *module)
void dt_gui_presets_show_edit_dialog(const char *name_in, const char *module_name, int rowid, GCallback final_callback, gpointer data, gboolean allow_name_change, gboolean allow_desc_change, gboolean allow_remove, GtkWindow *parent)
static void _opencl_disable_callback(GtkButton *button, dt_iop_module_t *module)
static void _edit_preset_final_callback(dt_gui_presets_edit_dialog_t *g)
void dt_gui_presets_show_iop_edit_dialog(const char *name_in, dt_iop_module_t *module, GCallback final_callback, gpointer data, gboolean allow_name_change, gboolean allow_desc_change, gboolean allow_remove, GtkWindow *parent)
void dt_gui_presets_popup_menu_show_for_params(dt_dev_operation_t op, int32_t version, void *params, int32_t params_size, void *blendop_params, const dt_image_t *image, void(*pick_callback)(GtkMenuItem *, void *), void *callback_data)
const int dt_gui_presets_exposure_value_cnt
Definition gui/presets.c:78
static void _menuitem_update_preset(GtkMenuItem *menuitem, dt_iop_module_t *module)
void dt_gui_presets_update_filter(const char *name, dt_dev_operation_t op, const int32_t version, const int filter)
void dt_gui_presets_confirm_and_delete(GtkWidget *parent_dialog, const char *name, const char *module_name, int rowid)
static void _presets_show_edit_dialog(dt_gui_presets_edit_dialog_t *g, gboolean allow_name_change, gboolean allow_desc_change, gboolean allow_remove)
void dt_gui_presets_update_ldr(const char *name, dt_dev_operation_t op, const int32_t version, const int ldrflag)
const float dt_gui_presets_aperture_value[]
Definition gui/presets.c:89
const int dt_gui_presets_aperture_value_cnt
Definition gui/presets.c:87
void dt_gui_presets_update_av(const char *name, dt_dev_operation_t op, const int32_t version, const float min, const float max)
static void _menuitem_new_preset(GtkMenuItem *menuitem, dt_iop_module_t *module)
void dt_gui_presets_update_fl(const char *name, dt_dev_operation_t op, const int32_t version, const float min, const float max)
static void _cache_disable_callback(GtkButton *button, dt_iop_module_t *module)
static sqlite3_stmt * _gui_presets_update_ldr_stmt
static void _menuitem_edit_preset(GtkMenuItem *menuitem, dt_iop_module_t *module)
void dt_gui_presets_popup_menu_show_for_module(dt_iop_module_t *module)
void dt_gui_presets_update_iso(const char *name, dt_dev_operation_t op, const int32_t version, const float min, const float max)
void dt_gui_presets_init()
void dt_gui_presets_update_mml(const char *name, dt_dev_operation_t op, const int32_t version, const char *maker, const char *model, const char *lens)
static void _edit_preset_response(GtkDialog *dialog, gint response_id, dt_gui_presets_edit_dialog_t *g)
const char * dt_gui_presets_exposure_value_str[]
Definition gui/presets.c:84
static GtkWidget * _presets_get_submenu(GtkWidget *parent, GHashTable *submenus, const gchar *path, const gchar *label)
void dt_gui_presets_add_with_blendop(const char *name, dt_dev_operation_t op, const int32_t version, const void *params, const int32_t params_size, const void *blend_params, const int32_t enabled)
static void _check_buttons_activated(GtkCheckButton *button, dt_gui_presets_edit_dialog_t *g)
void dt_gui_presets_cleanup()
static void _menuitem_pick_preset(GtkMenuItem *menuitem, dt_iop_module_t *module)
static void _gui_presets_popup_menu_show_internal(dt_dev_operation_t op, int32_t version, dt_iop_params_t *params, int32_t params_size, dt_develop_blend_params_t *bl_params, dt_iop_module_t *module, const dt_image_t *image, void(*pick_callback)(GtkMenuItem *, void *), void *callback_data)
static gchar * _get_active_preset_name(dt_iop_module_t *module, int *writeprotect)
static void _menuitem_delete_preset(GtkMenuItem *menuitem, dt_iop_module_t *module)
static gboolean _menuitem_button_released_preset(GtkMenuItem *menuitem, GdkEventButton *event, dt_iop_module_t *module)
static void _edit_preset(const char *name_in, dt_iop_module_t *module)
const char * dt_gui_presets_aperture_value_str[]
Definition gui/presets.c:91
static gboolean _gui_presets_autogen_enabled
static sqlite3_stmt * _gui_presets_update_fl_stmt
Definition gui/presets.c:99
const float dt_gui_presets_exposure_value[]
Definition gui/presets.c:80
static sqlite3_stmt * _gui_presets_add_stmt
Definition gui/presets.c:94
void dt_gui_presets_apply_preset(const gchar *name, dt_iop_module_t *module)
static sqlite3_stmt * _gui_presets_update_tv_stmt
Definition gui/presets.c:98
static const int _gui_presets_format_flag[5]
static sqlite3_stmt * _gui_presets_update_filter_stmt
static sqlite3_stmt * _gui_presets_update_mml_stmt
Definition gui/presets.c:95
static sqlite3_stmt * _gui_presets_update_av_stmt
Definition gui/presets.c:97
gboolean dt_gui_presets_autogen_enabled()
void dt_gui_presets_update_tv(const char *name, dt_dev_operation_t op, const int32_t version, const float min, const float max)
static sqlite3_stmt * _gui_presets_update_iso_stmt
Definition gui/presets.c:96
void dt_gui_presets_update_autoapply(const char *name, dt_dev_operation_t op, const int32_t version, const int autoapply)
static const char * _gui_presets_format_value_str[5]
void dt_gui_presets_add_generic(const char *name, dt_dev_operation_t op, const int32_t version, const void *params, const int32_t params_size, const int32_t enabled, const dt_develop_blend_colorspace_t blend_cst)
@ FOR_RAW
Definition gui/presets.h:41
@ FOR_NOT_MONO
Definition gui/presets.h:43
@ FOR_LDR
Definition gui/presets.h:40
@ FOR_HDR
Definition gui/presets.h:42
@ FOR_NOT_COLOR
Definition gui/presets.h:44
#define DT_PRESETS_FOR_NOT
Definition gui/presets.h:72
#define DT_GUI_MODULE(x)
void dt_iop_commit_blend_params(dt_iop_module_t *module, const dt_develop_blend_params_t *blendop_params)
Definition imageop.c:1705
void dt_iop_gui_update(dt_iop_module_t *module)
Definition imageop.c:2133
void dt_iop_gui_rename_module(dt_iop_module_t *module)
Definition imageop.c:959
dt_iop_module_t * dt_iop_gui_duplicate(dt_iop_module_t *base, gboolean copy_params)
Definition imageop.c:802
@ IOP_FLAGS_ONE_INSTANCE
Definition imageop.h:202
const char * maker
const char * model
void dt_lib_presets_remove(const gchar *preset, const gchar *module_name, int module_version)
Definition lib.c:394
static void pick_callback(GtkMenuItem *menuitem, dt_lib_module_info_t *minfo)
Definition lib.c:487
float *const restrict const size_t k
void dt_osx_disallow_fullscreen(GtkWidget *widget)
Definition osx.mm:104
char dt_dev_operation_t[20]
Definition settings.h:38
struct _GtkWidget GtkWidget
Definition splash.h:29
struct dt_gui_gtk_t * gui
Definition darktable.h:803
const struct dt_database_t * db
Definition darktable.h:807
struct dt_bauhaus_t * bauhaus
Definition darktable.h:806
struct dt_develop_t * develop
Definition darktable.h:798
dt_image_t image_storage
Definition develop.h:259
GtkMenu * presets_popup_menu
Definition gtk.h:170
dt_ui_t * ui
Definition gtk.h:165
char * last_preset
Definition gtk.h:171
float exif_exposure
Definition image.h:285
float exif_iso
Definition image.h:288
char camera_maker[64]
Definition image.h:297
float exif_aperture
Definition image.h:287
float exif_focal_length
Definition image.h:289
char exif_maker[64]
Definition image.h:292
char camera_alias[64]
Definition image.h:299
char exif_lens[128]
Definition image.h:294
char exif_model[64]
Definition image.h:293
dt_iop_params_t * default_params
Definition imageop.h:344
struct dt_develop_blend_params_t * blend_params
Definition imageop.h:353
GtkWidget * widget
Definition imageop.h:374
struct dt_develop_t * dev
Definition imageop.h:333
GModule *dt_dev_operation_t op
Definition imageop.h:286
gboolean enabled
Definition imageop.h:335
struct dt_develop_blend_params_t * default_blendop_params
Definition imageop.h:353
int32_t params_size
Definition imageop.h:346
dt_iop_params_t * params
Definition imageop.h:344
GtkWidget * window
#define MIN(a, b)
Definition thinplate.c:32