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 gtk_widget_destroy(dialog);
306 }
307
308 if(res == GTK_RESPONSE_YES)
309 dt_lib_presets_remove(name, module->op, module->version());
310
311 dt_free(name);
312}
314{
315 dt_gui_store_last_preset(gtk_entry_get_text(g->name));
316}
317
318static void _edit_preset_response(GtkDialog *dialog, gint response_id, dt_gui_presets_edit_dialog_t *g)
319{
320 if(response_id == GTK_RESPONSE_OK)
321 {
322 // we want to save the preset in the database
323 sqlite3_stmt *stmt;
324
325 // we verify eventual name collisions
326 const gchar *name = gtk_entry_get_text(g->name);
327 if(((g->old_id >= 0) && (strcmp(g->original_name, name) != 0)) || (g->old_id < 0))
328 {
329 if(IS_NULL_PTR(name) || *name == '\0' || strcmp(_("new preset"), name) == 0)
330 {
331 // show error dialog
332 GtkWidget *dlg_changename
333 = gtk_message_dialog_new(GTK_WINDOW(dialog), GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
334 GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("please give preset a name"));
335#ifdef GDK_WINDOWING_QUARTZ
336 dt_osx_disallow_fullscreen(dlg_changename);
337#endif
338
339 gtk_window_set_title(GTK_WINDOW(dlg_changename), _("unnamed preset"));
340
341 gtk_dialog_run(GTK_DIALOG(dlg_changename));
342 gtk_widget_destroy(dlg_changename);
343 return;
344 }
345
346 // editing existing preset with different name or store new preset -> check for a preset with the same
347 // name:
348 // clang-format off
351 "SELECT name"
352 " FROM data.presets"
353 " WHERE name = ?1 AND operation=?2 AND op_version=?3"
354 " LIMIT 1",
355 -1, &stmt, NULL);
356 // clang-format on
357 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, name, -1, SQLITE_TRANSIENT);
358 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, g->operation, -1, SQLITE_TRANSIENT);
359 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, g->op_version);
360
361 if(sqlite3_step(stmt) == SQLITE_ROW)
362 {
363 sqlite3_finalize(stmt);
364
365 // show overwrite question dialog
366 GtkWidget *dlg_overwrite = gtk_message_dialog_new(
367 GTK_WINDOW(dialog), GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING,
368 GTK_BUTTONS_YES_NO, _("preset `%s' already exists.\ndo you want to overwrite?"), name);
369#ifdef GDK_WINDOWING_QUARTZ
370 dt_osx_disallow_fullscreen(dlg_overwrite);
371#endif
372
373 gtk_window_set_title(GTK_WINDOW(dlg_overwrite), _("overwrite preset?"));
374
375 const gint dlg_ret = gtk_dialog_run(GTK_DIALOG(dlg_overwrite));
376 gtk_widget_destroy(dlg_overwrite);
377
378 // if result is BUTTON_NO or ESCAPE keypress exit without destroying dialog, to permit other name
379 if(dlg_ret == GTK_RESPONSE_YES)
380 {
381 // we remove the preset that will be overwrite
382 dt_lib_presets_remove(name, g->operation, g->op_version);
383 }
384 else
385 return;
386 }
387 else
388 {
389 sqlite3_finalize(stmt);
390 }
391 }
392
393 gchar *query = NULL;
394 if(g->old_id >= 0)
395 {
396 // we update presets values
397 // clang-format off
398 query = g_strdup_printf("UPDATE data.presets "
399 "SET"
400 " name=?1, description=?2,"
401 " model=?3, maker=?4, lens=?5, iso_min=?6, iso_max=?7, exposure_min=?8,"
402 " exposure_max=?9, aperture_min=?10,"
403 " aperture_max=?11, focal_length_min=?12, focal_length_max=?13, autoapply=?14,"
404 " filter=?15, format=?16 "
405 "WHERE rowid=%d",
406 g->old_id);
407 // clang-format on
408 }
409 else
410 {
411 // we create a new preset
412 // clang-format off
413 query = g_strdup_printf("INSERT INTO data.presets"
414 " (name, description, "
415 " model, maker, lens, iso_min, iso_max, exposure_min, exposure_max, aperture_min,"
416 " aperture_max, focal_length_min, focal_length_max, autoapply,"
417 " filter, format, def, writeprotect, operation, op_version, op_params, enabled,"
418 " blendop_params, blendop_version, multi_priority, multi_name) "
419 "VALUES"
420 " (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, 0, 0, ?17,"
421 " ?18, ?19, ?20, ?21, ?22, 0, '')");
422 // clang-format on
423 }
424
425 // commit all the user input fields
427 dt_free(query);
428 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, name, -1, SQLITE_TRANSIENT);
429 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, gtk_entry_get_text(g->description), -1, SQLITE_TRANSIENT);
430
431 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, gtk_entry_get_text(GTK_ENTRY(g->model)), -1, SQLITE_TRANSIENT);
432 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, gtk_entry_get_text(GTK_ENTRY(g->maker)), -1, SQLITE_TRANSIENT);
433 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 5, gtk_entry_get_text(GTK_ENTRY(g->lens)), -1, SQLITE_TRANSIENT);
434 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 6, gtk_spin_button_get_value(GTK_SPIN_BUTTON(g->iso_min)));
435 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 7, gtk_spin_button_get_value(GTK_SPIN_BUTTON(g->iso_max)));
442 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 12, gtk_spin_button_get_value(GTK_SPIN_BUTTON(g->focal_length_min)));
443 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 13, gtk_spin_button_get_value(GTK_SPIN_BUTTON(g->focal_length_max)));
444 DT_DEBUG_SQLITE3_BIND_INT(stmt, 14, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g->autoapply)));
445 DT_DEBUG_SQLITE3_BIND_INT(stmt, 15, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g->filter)));
446 int format = 0;
447 for(int k = 0; k < 5; k++)
448 format += gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g->format_btn[k])) * _gui_presets_format_flag[k];
449 format ^= DT_PRESETS_FOR_NOT;
450
451 DT_DEBUG_SQLITE3_BIND_INT(stmt, 16, format);
452
453 // commit specific field in case of newly crearted preset
454 if(g->old_id < 0)
455 {
456 if(g->iop)
457 {
458 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 17, g->operation, -1, SQLITE_TRANSIENT);
459 DT_DEBUG_SQLITE3_BIND_INT(stmt, 18, g->op_version);
460 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 19, g->iop->params, g->iop->params_size, SQLITE_TRANSIENT);
461 DT_DEBUG_SQLITE3_BIND_INT(stmt, 20, g->iop->enabled);
462 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 21, g->iop->blend_params, sizeof(dt_develop_blend_params_t),
463 SQLITE_TRANSIENT);
465 }
466 else
467 {
468 // we are in the lib case currently we set set all params to 0
469 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 17, g->operation, -1, SQLITE_TRANSIENT);
470 DT_DEBUG_SQLITE3_BIND_INT(stmt, 18, g->op_version);
471 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 19, NULL, 0, SQLITE_TRANSIENT);
472 DT_DEBUG_SQLITE3_BIND_INT(stmt, 20, 0);
473 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 21, NULL, 0, SQLITE_TRANSIENT);
474 DT_DEBUG_SQLITE3_BIND_INT(stmt, 22, 0);
475 }
476 }
477
478 sqlite3_step(stmt);
479 sqlite3_finalize(stmt);
480
481 if(g->callback) ((void (*)(dt_gui_presets_edit_dialog_t *))g->callback)(g);
482 }
483 else if(response_id == GTK_RESPONSE_YES && g->old_id)
484 {
485 const gchar *name = gtk_entry_get_text(g->name);
486
487 // ask for destination directory
488 GtkFileChooserNative *filechooser = gtk_file_chooser_native_new(
489 _("select directory"), GTK_WINDOW(dialog), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
490 _("_select as output destination"), _("_cancel"));
491 dt_conf_get_folder_to_file_chooser("ui_last/export_path", GTK_FILE_CHOOSER(filechooser));
492
493 // save if accepted
494 if(gtk_native_dialog_run(GTK_NATIVE_DIALOG(filechooser)) == GTK_RESPONSE_ACCEPT)
495 {
496 char *filedir = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filechooser));
497 dt_presets_save_to_file(g->old_id, name, filedir);
498 dt_control_log(_("preset %s was successfully exported"), name);
499 dt_free(filedir);
500 dt_conf_set_folder_from_file_chooser("ui_last/export_path", GTK_FILE_CHOOSER(filechooser));
501 }
502
503 g_object_unref(GTK_WIDGET(filechooser));
504 return; // we don't close the window so other actions can be performed if needed
505 }
506 else if(response_id == GTK_RESPONSE_REJECT && g->old_id)
507 {
508 dt_gui_presets_confirm_and_delete(GTK_WIDGET(dialog), g->original_name, g->operation, g->old_id);
509
510 if(g->callback) ((void (*)(dt_gui_presets_edit_dialog_t *))g->callback)(g);
511 }
512
513 gtk_widget_destroy(GTK_WIDGET(dialog));
514 dt_free(g->original_name);
515 dt_free(g->module_name);
516 dt_free(g->operation);
517 dt_free(g);
518}
519
520void dt_gui_presets_confirm_and_delete(GtkWidget *parent_dialog, const char *name, const char *module_name, int rowid)
521{
522 if(IS_NULL_PTR(module_name)) return;
523
524 // This means with want to remove the preset
525 GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(parent_dialog), GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
526 GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
527 _("do you really want to delete the preset `%s'?"), name);
528#ifdef GDK_WINDOWING_QUARTZ
530#endif
531
532 gtk_window_set_title(GTK_WINDOW(dialog), _("delete preset?"));
533 if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_YES)
534 {
535 // remove the preset from the database
536 sqlite3_stmt *stmt;
538 "DELETE FROM data.presets WHERE rowid=?1 AND writeprotect=0", -1, &stmt, NULL);
539 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, rowid);
540 sqlite3_step(stmt);
541 sqlite3_finalize(stmt);
542 }
543 gtk_widget_destroy(dialog);
544}
545
546static void _check_buttons_activated(GtkCheckButton *button, dt_gui_presets_edit_dialog_t *g)
547{
548 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g->autoapply))
549 || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g->filter)))
550 {
551 gtk_widget_set_visible(GTK_WIDGET(g->details), TRUE);
552 gtk_widget_set_no_show_all(GTK_WIDGET(g->details), FALSE);
553 gtk_widget_show_all(GTK_WIDGET(g->details));
554 gtk_widget_set_no_show_all(GTK_WIDGET(g->details), TRUE);
555 }
556 else
557 gtk_widget_set_visible(GTK_WIDGET(g->details), FALSE);
558}
559
560static void _presets_show_edit_dialog(dt_gui_presets_edit_dialog_t *g, gboolean allow_name_change,
561 gboolean allow_desc_change, gboolean allow_remove)
562{
563 /* Create the widgets */
564 char title[1024];
565 snprintf(title, sizeof(title), _("edit `%s' for module `%s'"), g->original_name, g->module_name);
566 GtkWidget *dialog = gtk_dialog_new_with_buttons
567 (title, g->parent, GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
568 _("_cancel"), GTK_RESPONSE_CANCEL, _("_export..."), GTK_RESPONSE_YES,
569 _("delete"), GTK_RESPONSE_REJECT, _("_ok"), GTK_RESPONSE_OK, NULL);
570 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
571
572#ifdef GDK_WINDOWING_QUARTZ
574#endif
575 GtkContainer *content_area = GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog)));
576 GtkBox *box = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING));
577 gtk_container_add(content_area, GTK_WIDGET(box));
578
579 g->name = GTK_ENTRY(gtk_entry_new());
580 dt_accels_disconnect_on_text_input(GTK_WIDGET(g->name));
581 gtk_entry_set_text(g->name, g->original_name);
582 if(allow_name_change)
583 gtk_entry_set_activates_default(g->name, TRUE);
584 else
585 gtk_widget_set_sensitive(GTK_WIDGET(g->name), FALSE);
586 gtk_box_pack_start(box, GTK_WIDGET(g->name), FALSE, FALSE, 0);
587 gtk_widget_set_tooltip_text(GTK_WIDGET(g->name), _("name of the preset"));
588
589 g->description = GTK_ENTRY(gtk_entry_new());
590 dt_accels_disconnect_on_text_input(GTK_WIDGET(g->description));
591 if(allow_desc_change)
592 gtk_entry_set_activates_default(g->description, TRUE);
593 else
594 gtk_widget_set_sensitive(GTK_WIDGET(g->description), FALSE);
595 gtk_box_pack_start(box, GTK_WIDGET(g->description), FALSE, FALSE, 0);
596 gtk_widget_set_tooltip_text(GTK_WIDGET(g->description), _("description or further information"));
597
598 g->autoapply
599 = GTK_CHECK_BUTTON(gtk_check_button_new_with_label(_("auto apply this preset to matching images")));
600 gtk_box_pack_start(box, GTK_WIDGET(g->autoapply), FALSE, FALSE, 0);
601 g->filter
602 = GTK_CHECK_BUTTON(gtk_check_button_new_with_label(_("only show this preset for matching images")));
603 gtk_widget_set_tooltip_text(GTK_WIDGET(g->filter), _("be very careful with this option. "
604 "this might be the last time you see your preset."));
605 gtk_box_pack_start(box, GTK_WIDGET(g->filter), FALSE, FALSE, 0);
606 if(IS_NULL_PTR(g->iop))
607 {
608 // lib usually don't support autoapply
609 gtk_widget_set_no_show_all(GTK_WIDGET(g->autoapply), !dt_presets_module_can_autoapply(g->module_name));
610 // for libs, we don't want the filtering option as it's not implemented...
611 gtk_widget_set_no_show_all(GTK_WIDGET(g->filter), TRUE);
612 }
613 g_signal_connect(G_OBJECT(g->autoapply), "toggled", G_CALLBACK(_check_buttons_activated), g);
614 g_signal_connect(G_OBJECT(g->filter), "toggled", G_CALLBACK(_check_buttons_activated), g);
615
616 int line = 0;
617 g->details = gtk_grid_new();
618 gtk_grid_set_row_spacing(GTK_GRID(g->details), DT_GUI_BOX_SPACING);
619 gtk_grid_set_column_spacing(GTK_GRID(g->details), DT_GUI_BOX_SPACING);
620 gtk_box_pack_start(box, GTK_WIDGET(g->details), TRUE, TRUE, 0);
621
622 GtkWidget *label = NULL;
623
624 // model, maker, lens
625 g->model = gtk_entry_new();
627 gtk_widget_set_hexpand(GTK_WIDGET(g->model), TRUE);
628 /* xgettext:no-c-format */
629 gtk_widget_set_tooltip_text(g->model, _("string to match model (use % as wildcard)"));
630 label = gtk_label_new(_("model"));
631 gtk_widget_set_halign(label, GTK_ALIGN_START);
632 gtk_grid_attach(GTK_GRID(g->details), label, 0, line++, 1, 1);
633 gtk_grid_attach_next_to(GTK_GRID(g->details), g->model, label, GTK_POS_RIGHT, 2, 1);
634
635 g->maker = gtk_entry_new();
637 /* xgettext:no-c-format */
638 gtk_widget_set_tooltip_text(g->maker, _("string to match maker (use % as wildcard)"));
639 label = gtk_label_new(_("maker"));
640 gtk_widget_set_halign(label, GTK_ALIGN_START);
641 gtk_grid_attach(GTK_GRID(g->details), label, 0, line++, 1, 1);
642 gtk_grid_attach_next_to(GTK_GRID(g->details), g->maker, label, GTK_POS_RIGHT, 2, 1);
643
644 g->lens = gtk_entry_new();
646 /* xgettext:no-c-format */
647 gtk_widget_set_tooltip_text(g->lens, _("string to match lens (use % as wildcard)"));
648 label = gtk_label_new(_("lens"));
649 gtk_widget_set_halign(label, GTK_ALIGN_START);
650 gtk_grid_attach(GTK_GRID(g->details), label, 0, line++, 1, 1);
651 gtk_grid_attach_next_to(GTK_GRID(g->details), g->lens, label, GTK_POS_RIGHT, 2, 1);
652
653 // iso
654 label = gtk_label_new(_("ISO"));
655 gtk_widget_set_halign(label, GTK_ALIGN_START);
656 g->iso_min = gtk_spin_button_new_with_range(0, FLT_MAX, 100);
657 gtk_widget_set_tooltip_text(g->iso_min, _("minimum ISO value"));
658 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(g->iso_min), 0);
659 g->iso_max = gtk_spin_button_new_with_range(0, FLT_MAX, 100);
660 gtk_widget_set_tooltip_text(g->iso_max, _("maximum ISO value"));
661 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(g->iso_max), 0);
662 gtk_grid_attach(GTK_GRID(g->details), label, 0, line++, 1, 1);
663 gtk_grid_attach_next_to(GTK_GRID(g->details), g->iso_min, label, GTK_POS_RIGHT, 1, 1);
664 gtk_grid_attach_next_to(GTK_GRID(g->details), g->iso_max, g->iso_min, GTK_POS_RIGHT, 1, 1);
665
666 // exposure
667 label = gtk_label_new(_("exposure"));
668 gtk_widget_set_halign(label, GTK_ALIGN_START);
671 gtk_widget_set_tooltip_text(g->exposure_min, _("minimum exposure time"));
672 gtk_widget_set_tooltip_text(g->exposure_max, _("maximum exposure time"));
673 for(int k = 0; k < dt_gui_presets_exposure_value_cnt; k++)
675 for(int k = 0; k < dt_gui_presets_exposure_value_cnt; k++)
677 gtk_grid_attach(GTK_GRID(g->details), label, 0, line++, 1, 1);
678 gtk_grid_attach_next_to(GTK_GRID(g->details), g->exposure_min, label, GTK_POS_RIGHT, 1, 1);
679 gtk_grid_attach_next_to(GTK_GRID(g->details), g->exposure_max, g->exposure_min, GTK_POS_RIGHT, 1, 1);
680
681 // aperture
682 label = gtk_label_new(_("aperture"));
683 gtk_widget_set_halign(label, GTK_ALIGN_START);
686 gtk_widget_set_tooltip_text(g->aperture_min, _("minimum aperture value"));
687 gtk_widget_set_tooltip_text(g->aperture_max, _("maximum aperture value"));
688 for(int k = 0; k < dt_gui_presets_aperture_value_cnt; k++)
690 for(int k = 0; k < dt_gui_presets_aperture_value_cnt; k++)
692 gtk_grid_attach(GTK_GRID(g->details), label, 0, line++, 1, 1);
693 gtk_grid_attach_next_to(GTK_GRID(g->details), g->aperture_min, label, GTK_POS_RIGHT, 1, 1);
694 gtk_grid_attach_next_to(GTK_GRID(g->details), g->aperture_max, g->aperture_min, GTK_POS_RIGHT, 1, 1);
695
696 // focal length
697 label = gtk_label_new(_("focal length"));
698 gtk_widget_set_halign(label, GTK_ALIGN_START);
699 g->focal_length_min = gtk_spin_button_new_with_range(0, 1000, 10);
700 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(g->focal_length_min), 0);
701 g->focal_length_max = gtk_spin_button_new_with_range(0, 1000, 10);
702 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(g->focal_length_max), 0);
703 gtk_widget_set_tooltip_text(g->focal_length_min, _("minimum focal length"));
704 gtk_widget_set_tooltip_text(g->focal_length_max, _("maximum focal length"));
705 gtk_grid_attach(GTK_GRID(g->details), label, 0, line++, 1, 1);
706 gtk_grid_attach_next_to(GTK_GRID(g->details), g->focal_length_min, label, GTK_POS_RIGHT, 1, 1);
707 gtk_grid_attach_next_to(GTK_GRID(g->details), g->focal_length_max, g->focal_length_min, GTK_POS_RIGHT, 1, 1);
708
709 // raw/hdr/ldr/mono/color
710 label = gtk_label_new(_("format"));
711 gtk_widget_set_halign(label, GTK_ALIGN_START);
712 gtk_grid_attach(GTK_GRID(g->details), label, 0, line, 1, 1);
713 gtk_widget_set_tooltip_text(label, _("select image types you want this preset to be available for"));
714
715 for(int i = 0; i < 5; i++)
716 {
717 g->format_btn[i] = gtk_check_button_new_with_label(_(_gui_presets_format_value_str[i]));
718 gtk_grid_attach(GTK_GRID(g->details), g->format_btn[i], 1, line + i, 2, 1);
719 }
720
721 gtk_widget_set_no_show_all(GTK_WIDGET(g->details), TRUE);
722
723 sqlite3_stmt *stmt;
724 // clang-format off
727 "SELECT rowid, description, model, maker, lens, iso_min, iso_max, "
728 " exposure_min, exposure_max, aperture_min, aperture_max, focal_length_min, "
729 " focal_length_max, autoapply, filter, format"
730 " FROM data.presets"
731 " WHERE name = ?1 AND operation = ?2 AND op_version = ?3",
732 -1, &stmt, NULL);
733 // clang-format on
734 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, g->original_name, -1, SQLITE_TRANSIENT);
735 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, g->operation, -1, SQLITE_TRANSIENT);
736 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, g->op_version);
737 if(sqlite3_step(stmt) == SQLITE_ROW)
738 {
739 g->old_id = sqlite3_column_int(stmt, 0);
740 gtk_entry_set_text(GTK_ENTRY(g->description), (const char *)sqlite3_column_text(stmt, 1));
741 gtk_entry_set_text(GTK_ENTRY(g->model), (const char *)sqlite3_column_text(stmt, 2));
742 gtk_entry_set_text(GTK_ENTRY(g->maker), (const char *)sqlite3_column_text(stmt, 3));
743 gtk_entry_set_text(GTK_ENTRY(g->lens), (const char *)sqlite3_column_text(stmt, 4));
744 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->iso_min), sqlite3_column_double(stmt, 5));
745 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->iso_max), sqlite3_column_double(stmt, 6));
746
747 float val = sqlite3_column_double(stmt, 7);
748 int k = 0;
749 for(; k < dt_gui_presets_exposure_value_cnt && val > dt_gui_presets_exposure_value[k]; k++)
750 ;
751 dt_bauhaus_combobox_set(g->exposure_min, k);
752 val = sqlite3_column_double(stmt, 8);
753 for(k = 0; k < dt_gui_presets_exposure_value_cnt && val > dt_gui_presets_exposure_value[k]; k++)
754 ;
755 dt_bauhaus_combobox_set(g->exposure_max, k);
756 val = sqlite3_column_double(stmt, 9);
757 for(k = 0; k < dt_gui_presets_aperture_value_cnt && val > dt_gui_presets_aperture_value[k]; k++)
758 ;
759 dt_bauhaus_combobox_set(g->aperture_min, k);
760 val = sqlite3_column_double(stmt, 10);
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_max, k);
764 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->focal_length_min), sqlite3_column_double(stmt, 11));
765 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->focal_length_max), sqlite3_column_double(stmt, 12));
766 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->autoapply), sqlite3_column_int(stmt, 13));
767 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->filter), sqlite3_column_int(stmt, 14));
768 const int format = (sqlite3_column_int(stmt, 15)) ^ DT_PRESETS_FOR_NOT;
769 for(k = 0; k < 5; k++)
770 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->format_btn[k]), format & (_gui_presets_format_flag[k]));
771 }
772 else
773 {
774 gtk_entry_set_text(GTK_ENTRY(g->description), "");
775 gtk_entry_set_text(GTK_ENTRY(g->model), "%");
776 gtk_entry_set_text(GTK_ENTRY(g->maker), "%");
777 gtk_entry_set_text(GTK_ENTRY(g->lens), "%");
778 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->iso_min), 0);
779 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->iso_max), FLT_MAX);
780
781 float val = 0;
782 int k = 0;
783 for(; k < dt_gui_presets_exposure_value_cnt && val > dt_gui_presets_exposure_value[k]; k++)
784 ;
785 dt_bauhaus_combobox_set(g->exposure_min, k);
786 val = 100000000;
787 for(k = 0; k < dt_gui_presets_exposure_value_cnt && val > dt_gui_presets_exposure_value[k]; k++)
788 ;
789 dt_bauhaus_combobox_set(g->exposure_max, k);
790 val = 0;
791 for(k = 0; k < dt_gui_presets_aperture_value_cnt && val > dt_gui_presets_aperture_value[k]; k++)
792 ;
793 dt_bauhaus_combobox_set(g->aperture_min, k);
794 val = 100000000;
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_max, k);
798 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->focal_length_min), 0);
799 gtk_spin_button_set_value(GTK_SPIN_BUTTON(g->focal_length_max), 1000);
800 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->autoapply), 0);
801 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->filter), 0);
802 for(k = 0; k < 5; k++) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->format_btn[k]), TRUE);
803 }
804 sqlite3_finalize(stmt);
805
806 // disable remove button if needed
807 if(!allow_remove || g->old_id < 0)
808 {
809 GtkWidget *w = gtk_dialog_get_widget_for_response(GTK_DIALOG(dialog), GTK_RESPONSE_REJECT);
810 if(w) gtk_widget_set_sensitive(w, FALSE);
811 }
812 // disable export button if the preset is not already in the database
813 if(g->old_id < 0)
814 {
815 GtkWidget *w = gtk_dialog_get_widget_for_response(GTK_DIALOG(dialog), GTK_RESPONSE_YES);
816 if(w) gtk_widget_set_sensitive(w, FALSE);
817 }
818
819 // put focus on cancel button if 2 first entries deactivated
820 if(!allow_desc_change && !allow_name_change)
821 {
822 GtkWidget *w = gtk_dialog_get_widget_for_response(GTK_DIALOG(dialog), GTK_RESPONSE_CANCEL);
823 if(w) gtk_widget_grab_focus(w);
824 }
825
826 g_signal_connect(dialog, "response", G_CALLBACK(_edit_preset_response), g);
827 gtk_widget_show_all(dialog);
828}
829
830void dt_gui_presets_show_iop_edit_dialog(const char *name_in, dt_iop_module_t *module, GCallback final_callback,
831 gpointer data, gboolean allow_name_change, gboolean allow_desc_change,
832 gboolean allow_remove, GtkWindow *parent)
833{
836 g->old_id = -1;
837 g->original_name = g_strdup(name_in);
838 g->iop = module;
839 g->operation = g_strdup(module->op);
840 g->op_version = module->version();
841 g->module_name = g_strdup(module->name());
842 g->callback = final_callback;
843 g->data = data;
844 g->parent = parent;
845
846 _presets_show_edit_dialog(g, allow_name_change, allow_desc_change, allow_remove);
847}
848
849void dt_gui_presets_show_edit_dialog(const char *name_in, const char *module_name, int rowid,
850 GCallback final_callback, gpointer data, gboolean allow_name_change,
851 gboolean allow_desc_change, gboolean allow_remove, GtkWindow *parent)
852{
853 sqlite3_stmt *stmt;
855 "SELECT operation, op_version FROM data.presets WHERE rowid = ?1", -1, &stmt, NULL);
856 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, rowid);
857 if(sqlite3_step(stmt) == SQLITE_ROW)
858 {
861 g->old_id = rowid;
862 g->original_name = g_strdup(name_in);
863 g->operation = g_strdup((char *)sqlite3_column_text(stmt, 0));
864 g->op_version = sqlite3_column_int(stmt, 1);
865 g->module_name = g_strdup(module_name);
866 g->callback = final_callback;
867 g->data = data;
868 g->parent = parent;
869
870 sqlite3_finalize(stmt);
871
872 _presets_show_edit_dialog(g, allow_name_change, allow_desc_change, allow_remove);
873 }
874 else
875 sqlite3_finalize(stmt);
876}
877
878static void _edit_preset(const char *name_in, dt_iop_module_t *module)
879{
880 gchar *name = NULL;
881 if(IS_NULL_PTR(name_in))
882 {
883 int writeprotect = -1;
884 name = _get_active_preset_name(module, &writeprotect);
885 if(IS_NULL_PTR(name)) return;
886 if(writeprotect)
887 {
888 dt_control_log(_("preset `%s' is write-protected! can't edit it!"), name);
889 dt_free(name);
890 return;
891 }
892 }
893 else
894 name = g_strdup(name_in);
895
897 FALSE, GTK_WINDOW(dt_ui_main_window(darktable.gui->ui)));
898 dt_free(name);
899}
900
901static void _menuitem_edit_preset(GtkMenuItem *menuitem, dt_iop_module_t *module)
902{
903 _edit_preset(NULL, module);
904}
905
906static void _menuitem_update_preset(GtkMenuItem *menuitem, dt_iop_module_t *module)
907{
908 gchar *name = g_object_get_data(G_OBJECT(menuitem), "dt-preset-name");
909
910 gint res = GTK_RESPONSE_YES;
911
912 if(dt_conf_get_bool("plugins/lighttable/preset/ask_before_delete_preset"))
913 {
915 GtkWidget *dialog
916 = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION,
917 GTK_BUTTONS_YES_NO, _("do you really want to update the preset `%s'?"), name);
918#ifdef GDK_WINDOWING_QUARTZ
920#endif
921 gtk_window_set_title(GTK_WINDOW(dialog), _("update preset?"));
922 res = gtk_dialog_run(GTK_DIALOG(dialog));
923 gtk_widget_destroy(dialog);
924 }
925
926 if(res == GTK_RESPONSE_YES)
927 {
928 // commit all the module fields
929 sqlite3_stmt *stmt;
931 "UPDATE data.presets"
932 " SET op_version=?2, op_params=?3, enabled=?4, "
933 " blendop_params=?5, blendop_version=?6"
934 " WHERE name=?7 AND operation=?1",
935 -1, &stmt, NULL);
936
937 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, module->op, -1, SQLITE_TRANSIENT);
938 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, module->version());
939 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 3, module->params, module->params_size, SQLITE_TRANSIENT);
940 DT_DEBUG_SQLITE3_BIND_INT(stmt, 4, module->enabled);
942 SQLITE_TRANSIENT);
944 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 7, name, -1, SQLITE_TRANSIENT);
945 sqlite3_step(stmt);
946 sqlite3_finalize(stmt);
947 }
948}
949
950static void _menuitem_new_preset(GtkMenuItem *menuitem, dt_iop_module_t *module)
951{
952 // add new preset
953 dt_lib_presets_remove(_("new preset"), module->op, module->version());
954
955 // then show edit dialog
956 _edit_preset(_("new preset"), module);
957}
958
960{
961 sqlite3_stmt *stmt;
962 // clang-format off
965 "SELECT op_params, enabled, blendop_params, blendop_version, writeprotect"
966 " FROM data.presets"
967 " WHERE operation = ?1 AND op_version = ?2 AND name = ?3",
968 -1, &stmt, NULL);
969 // clang-format on
970 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, module->op, -1, SQLITE_TRANSIENT);
971 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, module->version());
972 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, name, -1, SQLITE_TRANSIENT);
973
974 if(sqlite3_step(stmt) == SQLITE_ROW)
975 {
976 const void *op_params = sqlite3_column_blob(stmt, 0);
977 const int op_length = sqlite3_column_bytes(stmt, 0);
978 const int enabled = sqlite3_column_int(stmt, 1);
979 const void *blendop_params = sqlite3_column_blob(stmt, 2);
980 const int bl_length = sqlite3_column_bytes(stmt, 2);
981 const int blendop_version = sqlite3_column_int(stmt, 3);
982 const int writeprotect = sqlite3_column_int(stmt, 4);
983 if(op_params && (op_length == module->params_size))
984 {
985 memcpy(module->params, op_params, op_length);
986 module->enabled = enabled;
987 }
988 if(blendop_params && (blendop_version == dt_develop_blend_version())
989 && (bl_length == sizeof(dt_develop_blend_params_t)))
990 {
991 dt_iop_commit_blend_params(module, blendop_params);
992 }
993 else if(blendop_params
994 && dt_develop_blend_legacy_params(module, blendop_params, blendop_version, module->blend_params,
995 dt_develop_blend_version(), bl_length) == 0)
996 {
997 // do nothing
998 }
999 else
1000 {
1002 }
1003
1004 if(!writeprotect) dt_gui_store_last_preset(name);
1005 }
1006 sqlite3_finalize(stmt);
1007 dt_iop_gui_update(module);
1009 gtk_widget_queue_draw(module->widget);
1010}
1011
1012static void _menuitem_pick_preset(GtkMenuItem *menuitem, dt_iop_module_t *module)
1013{
1014 gchar *name = g_object_get_data(G_OBJECT(menuitem), "dt-preset-name");
1016}
1017
1019{
1020 dt_image_t *image = &module->dev->image_storage;
1021 const gboolean has_matrix = dt_image_is_matrix_correction_supported(image);
1022
1023 char query[2024];
1024 // clang-format off
1025 snprintf(query, sizeof(query),
1026 "SELECT name"
1027 " FROM data.presets"
1028 " WHERE operation = ?1"
1029 " AND ((autoapply=1"
1030 " AND ((?2 LIKE model AND ?3 LIKE maker) OR (?4 LIKE model AND ?5 LIKE maker))"
1031 " AND ?6 LIKE lens AND ?7 BETWEEN iso_min AND iso_max"
1032 " AND ?8 BETWEEN exposure_min AND exposure_max"
1033 " AND ?9 BETWEEN aperture_min AND aperture_max"
1034 " AND ?10 BETWEEN focal_length_min AND focal_length_max"
1035 " AND (format = 0 OR (format&?11 != 0 AND ~format&?12 != 0))"
1036 " AND operation NOT IN"
1037 " ('ioporder', 'metadata', 'export', 'tagging', 'collect', 'basecurve'))"
1038 " OR (name = ?13)) AND op_version = ?14");
1039 // clang-format on
1040
1041 sqlite3_stmt *stmt;
1042 const char *workflow_preset = (has_matrix) ? _("scene-referred default") : "\t\n";
1043 int iformat = 0;
1044 if(dt_image_needs_rawprepare(image)) iformat |= FOR_RAW;
1045 else iformat |= FOR_LDR;
1046 if(dt_image_is_hdr(image)) iformat |= FOR_HDR;
1047
1048 int excluded = 0;
1049 if(dt_image_monochrome_flags(image)) excluded |= FOR_NOT_MONO;
1050 else excluded |= FOR_NOT_COLOR;
1051
1052 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
1053 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, module->op, -1, SQLITE_TRANSIENT);
1054 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, image->exif_model, -1, SQLITE_TRANSIENT);
1055 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, image->exif_maker, -1, SQLITE_TRANSIENT);
1056 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, image->camera_alias, -1, SQLITE_TRANSIENT);
1057 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 5, image->camera_maker, -1, SQLITE_TRANSIENT);
1058 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 6, image->exif_lens, -1, SQLITE_TRANSIENT);
1059 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 7, fmaxf(0.0f, fminf(FLT_MAX, image->exif_iso)));
1060 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 8, fmaxf(0.0f, fminf(1000000, image->exif_exposure)));
1061 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 9, fmaxf(0.0f, fminf(1000000, image->exif_aperture)));
1062 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 10, fmaxf(0.0f, fminf(1000000, image->exif_focal_length)));
1063 // 0: dontcare, 1: ldr, 2: raw plus monochrome & color
1064 DT_DEBUG_SQLITE3_BIND_INT(stmt, 11, iformat);
1065 DT_DEBUG_SQLITE3_BIND_INT(stmt, 12, excluded);
1066 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 13, workflow_preset, -1, SQLITE_TRANSIENT);
1067 DT_DEBUG_SQLITE3_BIND_INT(stmt, 14, module->version());
1068
1069 gboolean applied = FALSE;
1070 while(sqlite3_step(stmt) == SQLITE_ROW)
1071 {
1072 const char *name = (const char *)sqlite3_column_text(stmt, 0);
1074 applied = TRUE;
1075 }
1076 sqlite3_finalize(stmt);
1077
1078 return applied;
1079}
1080
1081static gboolean _menuitem_button_released_preset(GtkMenuItem *menuitem, GdkEventButton *event,
1082 dt_iop_module_t *module)
1083{
1084 if (event->button == 1 || (module->flags() & IOP_FLAGS_ONE_INSTANCE))
1085 {
1086 _menuitem_pick_preset(menuitem, module);
1087 }
1088 else if (event->button == 3)
1089 {
1090 dt_iop_module_t *new_module = dt_iop_gui_duplicate(module, FALSE);
1091 if(new_module) _menuitem_pick_preset(menuitem, new_module);
1092 dt_iop_gui_rename_module(new_module);
1093 }
1094
1095 return FALSE;
1096}
1097
1098#ifdef HAVE_OPENCL
1099static void _opencl_disable_callback(GtkButton *button, dt_iop_module_t *module)
1100{
1101 gboolean active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(button));
1102 gchar *string = g_strdup_printf("/plugins/%s/opencl", module->op);
1103 dt_conf_set_bool(string, active);
1104 dt_free(string);
1105}
1106
1107static void _cache_disable_callback(GtkButton *button, dt_iop_module_t *module)
1108{
1109 gboolean active = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(button));
1110 gchar *string = g_strdup_printf("/plugins/%s/cache", module->op);
1111 dt_conf_set_bool(string, active);
1112 dt_free(string);
1113}
1114#endif
1115
1117 dt_iop_params_t *params, int32_t params_size,
1118 dt_develop_blend_params_t *bl_params, dt_iop_module_t *module,
1119 const dt_image_t *image,
1120 void (*pick_callback)(GtkMenuItem *, void *),
1121 void *callback_data)
1122{
1123 GtkMenu *menu = darktable.gui->presets_popup_menu;
1124 if(menu) gtk_widget_destroy(GTK_WIDGET(menu));
1125 darktable.gui->presets_popup_menu = GTK_MENU(gtk_menu_new());
1127 const gboolean hide_default = dt_conf_get_bool("plugins/darkroom/hide_default_presets");
1128 const gboolean default_first = dt_conf_get_bool("modules/default_presets_first");
1129
1130 gchar *query = NULL;
1131
1132 GtkWidget *mi;
1133 int active_preset = -1, cnt = 0, writeprotect = 0; //, selected_default = 0;
1134 sqlite3_stmt *stmt;
1135 // order: get shipped defaults first
1136 if(image)
1137 {
1138 // only matching if filter is on:
1139 int iformat = 0;
1140 if(dt_image_needs_rawprepare(image))
1141 iformat |= FOR_RAW;
1142 else
1143 iformat |= FOR_LDR;
1144
1145 if(dt_image_is_hdr(image))
1146 iformat |= FOR_HDR;
1147
1148 int excluded = 0;
1149 if(dt_image_monochrome_flags(image))
1150 excluded |= FOR_NOT_MONO;
1151 else
1152 excluded |= FOR_NOT_COLOR;
1153
1154 // clang-format off
1155 query = g_strdup_printf
1156 ("SELECT name, op_params, writeprotect, description, blendop_params, "
1157 " op_version, enabled"
1158 " FROM data.presets"
1159 " WHERE operation=?1"
1160 " AND (filter=0"
1161 " OR"
1162 " (((?2 LIKE model AND ?3 LIKE maker) OR (?4 LIKE model AND ?5 LIKE maker))"
1163 " AND ?6 LIKE lens"
1164 " AND ?7 BETWEEN iso_min AND iso_max"
1165 " AND ?8 BETWEEN exposure_min AND exposure_max"
1166 " AND ?9 BETWEEN aperture_min AND aperture_max"
1167 " AND ?10 BETWEEN focal_length_min AND focal_length_max"
1168 " AND (format = 0 OR (format&?11 != 0 AND ~format&?12 != 0))))"
1169 " ORDER BY writeprotect %s, LOWER(name), rowid",
1170 default_first ? "DESC":"ASC");
1171 // clang-format on
1172
1173 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
1174 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, op, -1, SQLITE_TRANSIENT);
1175 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, image->exif_model, -1, SQLITE_TRANSIENT);
1176 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, image->exif_maker, -1, SQLITE_TRANSIENT);
1177 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, image->camera_alias, -1, SQLITE_TRANSIENT);
1178 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 5, image->camera_maker, -1, SQLITE_TRANSIENT);
1179 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 6, image->exif_lens, -1, SQLITE_TRANSIENT);
1180 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 7, image->exif_iso);
1184 DT_DEBUG_SQLITE3_BIND_INT(stmt, 11, iformat);
1185 DT_DEBUG_SQLITE3_BIND_INT(stmt, 12, excluded);
1186 }
1187 else
1188 {
1189 // don't know for which image. show all we got:
1190
1191 query = g_strdup_printf("SELECT name, op_params, writeprotect, "
1192 " description, blendop_params, op_version, enabled"
1193 " FROM data.presets"
1194 " WHERE operation=?1"
1195 " ORDER BY writeprotect %s, LOWER(name), rowid",
1196 default_first ? "DESC":"ASC"
1197 );
1198
1199 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL);
1200 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, op, -1, SQLITE_TRANSIENT);
1201 }
1202 dt_free(query);
1203 // collect all presets for op from db
1204 gboolean found = 0;
1205 int last_wp = -1;
1206 while(sqlite3_step(stmt) == SQLITE_ROW)
1207 {
1208 const int chk_writeprotect = sqlite3_column_int(stmt, 2);
1209 if(hide_default && chk_writeprotect)
1210 {
1211 //skip default module if set to hide them.
1212 continue;
1213 }
1214 if(last_wp == -1)
1215 {
1216 last_wp = chk_writeprotect;
1217 }
1218 else if(last_wp != chk_writeprotect)
1219 {
1220 last_wp = chk_writeprotect;
1221 gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
1222 }
1223 const void *op_params = (void *)sqlite3_column_blob(stmt, 1);
1224 const int32_t op_params_size = sqlite3_column_bytes(stmt, 1);
1225 const void *blendop_params = (void *)sqlite3_column_blob(stmt, 4);
1226 const int32_t bl_params_size = sqlite3_column_bytes(stmt, 4);
1227 const int32_t preset_version = sqlite3_column_int(stmt, 5);
1228 const int32_t enabled = sqlite3_column_int(stmt, 6);
1229 const int32_t isdisabled = (preset_version == version ? 0 : 1);
1230 const char *name = (char *)sqlite3_column_text(stmt, 0);
1231 gboolean isdefault = FALSE;
1232
1233 if(darktable.gui->last_preset && strcmp(darktable.gui->last_preset, name) == 0)
1234 found = TRUE;
1235
1236 if(module
1237 && !memcmp(module->default_params, op_params,
1238 MIN(op_params_size, module->params_size))
1239 && !memcmp(module->default_blendop_params, blendop_params,
1240 MIN(bl_params_size, sizeof(dt_develop_blend_params_t))))
1241 isdefault = TRUE;
1242
1243 gchar *label;
1244 if(isdefault)
1245 label = g_strdup_printf("%s %s", name, _("(default)"));
1246 else
1247 label = g_strdup(name);
1248 mi = gtk_menu_item_new_with_label(label);
1249
1250 dt_free(label);
1251
1252 if(module
1253 && !memcmp(params, op_params, MIN(op_params_size, params_size))
1254 && !memcmp(bl_params, blendop_params, MIN(bl_params_size, sizeof(dt_develop_blend_params_t)))
1255 && module->enabled == enabled)
1256 {
1257 active_preset = cnt;
1258 writeprotect = sqlite3_column_int(stmt, 2);
1259 dt_gui_add_class(mi, "menu-active");
1260 }
1261
1262 if(isdisabled)
1263 {
1264 gtk_widget_set_sensitive(mi, 0);
1265 gtk_widget_set_tooltip_text(mi, _("disabled: wrong module version"));
1266 }
1267 else
1268 {
1269 g_object_set_data_full(G_OBJECT(mi), "dt-preset-name", g_strdup(name), g_free);
1270 if(module)
1271 {
1272 g_signal_connect(G_OBJECT(mi), "button-release-event", G_CALLBACK(_menuitem_button_released_preset),
1273 module);
1274 }
1275 else if(pick_callback)
1276 g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(pick_callback), callback_data);
1277 gtk_widget_set_tooltip_text(mi, (const char *)sqlite3_column_text(stmt, 3));
1278 }
1279 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1280 cnt++;
1281 }
1282 sqlite3_finalize(stmt);
1283
1284 if(cnt > 0) gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
1285
1286 if(module)
1287 {
1288 if(active_preset >= 0 && !writeprotect)
1289 {
1290 mi = gtk_menu_item_new_with_label(_("edit this preset.."));
1291 g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(_menuitem_edit_preset), module);
1292 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1293
1294 mi = gtk_menu_item_new_with_label(_("delete this preset"));
1295 g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(_menuitem_delete_preset), module);
1296 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1297 }
1298 else
1299 {
1300 mi = gtk_menu_item_new_with_label(_("store new preset.."));
1301 g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(_menuitem_new_preset), module);
1302 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1303
1304 if(darktable.gui->last_preset && found)
1305 {
1306 char *markup = g_markup_printf_escaped("%s <span weight='bold'>%s</span>", _("update preset"),
1308 mi = gtk_menu_item_new_with_label("");
1309 gtk_label_set_markup(GTK_LABEL(gtk_bin_get_child(GTK_BIN(mi))), markup);
1310 g_object_set_data_full(G_OBJECT(mi), "dt-preset-name", g_strdup(darktable.gui->last_preset), g_free);
1311 g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(_menuitem_update_preset), module);
1312 gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
1313 dt_free(markup);
1314 }
1315 }
1316 }
1317
1318 // and the parameters entry if needed
1319 if(module && (module->set_preferences))
1320 {
1321 gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
1322 if(module->set_preferences) module->set_preferences(GTK_MENU_SHELL(menu), module);
1323 }
1324
1325#ifdef HAVE_OPENCL
1326 // OpenCL prefs
1327 if(module && module->process_cl)
1328 {
1329 gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
1330
1331 GtkWidget *item = gtk_check_menu_item_new_with_label(_("Use OpenCL (GPU computing)"));
1332 gtk_widget_set_tooltip_text(item, _("Run this module on GPU if possible.\n"
1333 "Disable if you face recurring issues on GPU with this module.\n"
1334 "Does not require a restart."));
1335 gchar *string = g_strdup_printf("/plugins/%s/opencl", module->op);
1336
1337 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), dt_conf_get_bool(string));
1338 dt_free(string);
1339
1340 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(_opencl_disable_callback), module);
1341 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1342
1343 item = gtk_check_menu_item_new_with_label(_("Cache the GPU output"));
1344 gtk_widget_set_tooltip_text(item, _("Store the output of this module in cache when running on GPU.\n"
1345 "This may prevent some recomputations, at the cost of more memory I/O.\n"
1346 "The trade-off is worth it only for slow modules."));
1347 string = g_strdup_printf("/plugins/%s/cache", module->op);
1348
1349 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), dt_conf_get_bool(string));
1350 dt_free(string);
1351
1352 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(_cache_disable_callback), module);
1353 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1354 }
1355#endif
1356}
1357
1359 int32_t params_size, void *blendop_params,
1360 const dt_image_t *image,
1361 void (*pick_callback)(GtkMenuItem *, void *),
1362 void *callback_data)
1363{
1364 _gui_presets_popup_menu_show_internal(op, version, params, params_size, blendop_params, NULL, image,
1365 pick_callback, callback_data);
1366}
1367
1369{
1370 _gui_presets_popup_menu_show_internal(module->op, module->version(), module->params, module->params_size,
1371 module->blend_params, module, &module->dev->image_storage, NULL, NULL);
1372}
1373
1374void dt_gui_presets_update_mml(const char *name, dt_dev_operation_t op, const int32_t version,
1375 const char *maker, const char *model, const char *lens)
1376{
1378 {
1379 // clang-format off¨
1382 "UPDATE data.presets"
1383 " SET maker='%' || ?1 || '%', model=?2, lens=?3"
1384 " WHERE operation=?4 AND op_version=?5 AND name=?6", -1,
1386 // clang-format on
1387 }
1388 sqlite3_stmt *stmt = _gui_presets_update_mml_stmt;
1389 sqlite3_reset(stmt);
1390 sqlite3_clear_bindings(stmt);
1391 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, maker, -1, SQLITE_TRANSIENT);
1392 if (*model)
1393 {
1394 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, model, -1, SQLITE_TRANSIENT);
1395 }
1396 else
1397 {
1398 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, "%", -1, SQLITE_TRANSIENT);
1399 }
1400 if (*lens)
1401 {
1402 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, lens, -1, SQLITE_TRANSIENT);
1403 }
1404 else
1405 {
1406 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, "%", -1, SQLITE_TRANSIENT);
1407 }
1408 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, op, -1, SQLITE_TRANSIENT);
1409 DT_DEBUG_SQLITE3_BIND_INT(stmt, 5, version);
1410 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 6, name, -1, SQLITE_TRANSIENT);
1411 sqlite3_step(stmt);
1412}
1413
1414void dt_gui_presets_update_iso(const char *name, dt_dev_operation_t op, const int32_t version,
1415 const float min, const float max)
1416{
1418 {
1419 // clang-format off
1422 "UPDATE data.presets"
1423 " SET iso_min=?1, iso_max=?2"
1424 " WHERE operation=?3 AND op_version=?4 AND name=?5", -1, &_gui_presets_update_iso_stmt,
1425 NULL);
1426 // clang-format on
1427 }
1428 sqlite3_stmt *stmt = _gui_presets_update_iso_stmt;
1429 sqlite3_reset(stmt);
1430 sqlite3_clear_bindings(stmt);
1433 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, op, -1, SQLITE_TRANSIENT);
1434 DT_DEBUG_SQLITE3_BIND_INT(stmt, 4, version);
1435 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 5, name, -1, SQLITE_TRANSIENT);
1436 sqlite3_step(stmt);
1437}
1438
1439void dt_gui_presets_update_av(const char *name, dt_dev_operation_t op, const int32_t version, const float min,
1440 const float max)
1441{
1443 {
1444 // clang-format off
1447 "UPDATE data.presets"
1448 " SET aperture_min=?1, aperture_max=?2"
1449 " WHERE operation=?3 AND op_version=?4 AND name=?5",
1450 -1, &_gui_presets_update_av_stmt, NULL);
1451 // clang-format on
1452 }
1453 sqlite3_stmt *stmt = _gui_presets_update_av_stmt;
1454 sqlite3_reset(stmt);
1455 sqlite3_clear_bindings(stmt);
1458 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, op, -1, SQLITE_TRANSIENT);
1459 DT_DEBUG_SQLITE3_BIND_INT(stmt, 4, version);
1460 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 5, name, -1, SQLITE_TRANSIENT);
1461 sqlite3_step(stmt);
1462}
1463
1464void dt_gui_presets_update_tv(const char *name, dt_dev_operation_t op, const int32_t version, const float min,
1465 const float max)
1466{
1468 {
1471 "UPDATE data.presets SET exposure_min=?1, exposure_max=?2 WHERE operation=?3 AND op_version=?4 AND name=?5",
1472 -1, &_gui_presets_update_tv_stmt, NULL);
1473 }
1474 sqlite3_stmt *stmt = _gui_presets_update_tv_stmt;
1475 sqlite3_reset(stmt);
1476 sqlite3_clear_bindings(stmt);
1479 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, op, -1, SQLITE_TRANSIENT);
1480 DT_DEBUG_SQLITE3_BIND_INT(stmt, 4, version);
1481 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 5, name, -1, SQLITE_TRANSIENT);
1482 sqlite3_step(stmt);
1483}
1484
1485void dt_gui_presets_update_fl(const char *name, dt_dev_operation_t op, const int32_t version, const float min,
1486 const float max)
1487{
1489 {
1490 // clang-format off
1492 "UPDATE data.presets"
1493 " SET focal_length_min=?1, focal_length_max=?2"
1494 " WHERE operation=?3 AND op_version=?4 AND name=?5",
1495 -1, &_gui_presets_update_fl_stmt, NULL);
1496 // clang-format on
1497 }
1498 sqlite3_stmt *stmt = _gui_presets_update_fl_stmt;
1499 sqlite3_reset(stmt);
1500 sqlite3_clear_bindings(stmt);
1503 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, op, -1, SQLITE_TRANSIENT);
1504 DT_DEBUG_SQLITE3_BIND_INT(stmt, 4, version);
1505 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 5, name, -1, SQLITE_TRANSIENT);
1506 sqlite3_step(stmt);
1507}
1508
1509void dt_gui_presets_update_ldr(const char *name, dt_dev_operation_t op, const int32_t version,
1510 const int ldrflag)
1511{
1513 {
1514 // clang-format off
1516 "UPDATE data.presets"
1517 " SET format=?1"
1518 " WHERE operation=?2 AND op_version=?3 AND name=?4",
1519 -1, &_gui_presets_update_ldr_stmt, NULL);
1520 // clang-format on
1521 }
1522 sqlite3_stmt *stmt = _gui_presets_update_ldr_stmt;
1523 sqlite3_reset(stmt);
1524 sqlite3_clear_bindings(stmt);
1525 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, ldrflag);
1526 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, op, -1, SQLITE_TRANSIENT);
1527 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, version);
1528 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, name, -1, SQLITE_TRANSIENT);
1529 sqlite3_step(stmt);
1530}
1531
1532void dt_gui_presets_update_autoapply(const char *name, dt_dev_operation_t op, const int32_t version,
1533 const int autoapply)
1534{
1536 {
1537 // clang-format off
1540 "UPDATE data.presets"
1541 " SET autoapply=?1"
1542 " WHERE operation=?2 AND op_version=?3 AND name=?4", -1, &_gui_presets_update_autoapply_stmt, NULL);
1543 // clang-format on
1544 }
1545 sqlite3_stmt *stmt = _gui_presets_update_autoapply_stmt;
1546 sqlite3_reset(stmt);
1547 sqlite3_clear_bindings(stmt);
1548 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, autoapply);
1549 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, op, -1, SQLITE_TRANSIENT);
1550 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, version);
1551 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, name, -1, SQLITE_TRANSIENT);
1552 sqlite3_step(stmt);
1553}
1554
1555void dt_gui_presets_update_filter(const char *name, dt_dev_operation_t op, const int32_t version,
1556 const int filter)
1557{
1559 {
1560 // clang-format off
1562 "UPDATE data.presets"
1563 " SET filter=?1"
1564 " WHERE operation=?2 AND op_version=?3 AND name=?4",
1566 // clang-format on
1567 }
1568 sqlite3_stmt *stmt = _gui_presets_update_filter_stmt;
1569 sqlite3_reset(stmt);
1570 sqlite3_clear_bindings(stmt);
1571 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, filter);
1572 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, op, -1, SQLITE_TRANSIENT);
1573 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, version);
1574 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, name, -1, SQLITE_TRANSIENT);
1575 sqlite3_step(stmt);
1576}
1577
1578// clang-format off
1579// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
1580// vim: shiftwidth=2 expandtab tabstop=2 cindent
1581// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
1582// 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:2347
void dt_bauhaus_combobox_set(GtkWidget *widget, const int pos)
Definition bauhaus.c:2301
GtkWidget * dt_bauhaus_combobox_new(dt_bauhaus_t *bh, dt_gui_module_t *self)
Definition bauhaus.c:1842
void dt_bauhaus_combobox_add(GtkWidget *widget, const char *text)
Definition bauhaus.c:2016
void dt_develop_blend_init_blend_parameters(dt_develop_blend_params_t *blend_params, dt_develop_blend_colorspace_t cst)
Definition blend.c:157
int dt_develop_blend_version(void)
Definition blend.c:1630
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:1694
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:761
darktable_t darktable
Definition darktable.c:181
#define dt_free(ptr)
Definition darktable.h:456
#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:281
sqlite3 * dt_database_get(const dt_database_t *db)
Definition database.c:3646
#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:41
void dt_gui_store_last_preset(const char *name)
Definition gtk.c:475
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:3225
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
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:1667
void dt_iop_gui_update(dt_iop_module_t *module)
Definition imageop.c:2091
void dt_iop_gui_rename_module(dt_iop_module_t *module)
Definition imageop.c:953
dt_iop_module_t * dt_iop_gui_duplicate(dt_iop_module_t *base, gboolean copy_params)
Definition imageop.c:796
@ IOP_FLAGS_ONE_INSTANCE
Definition imageop.h:172
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:775
const struct dt_database_t * db
Definition darktable.h:779
struct dt_bauhaus_t * bauhaus
Definition darktable.h:778
struct dt_develop_t * develop
Definition darktable.h:770
dt_image_t image_storage
Definition develop.h:259
GtkMenu * presets_popup_menu
Definition gtk.h:169
dt_ui_t * ui
Definition gtk.h:164
char * last_preset
Definition gtk.h:170
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:307
struct dt_develop_blend_params_t * blend_params
Definition imageop.h:316
GtkWidget * widget
Definition imageop.h:337
struct dt_develop_t * dev
Definition imageop.h:296
GModule *dt_dev_operation_t op
Definition imageop.h:256
gboolean enabled
Definition imageop.h:298
struct dt_develop_blend_params_t * default_blendop_params
Definition imageop.h:316
int32_t params_size
Definition imageop.h:309
dt_iop_params_t * params
Definition imageop.h:307
#define MIN(a, b)
Definition thinplate.c:32