Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
preset_repository.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2026 Aurélien PIERRE.
4
5 darktable is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 darktable is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with darktable. If not, see <http://www.gnu.org/licenses/>.
17*/
18
20
21#include "database/database.h"
22#include "database/sql_debug.h"
23#include "system/macros.h"
24#include "system/mem_alloc.h"
25
26#include <float.h>
27#include <math.h>
28#include <sqlite3.h>
29#include <string.h>
30
32{
33 if(IS_NULL_PTR(preset)) return;
34
35 dt_free(preset->name);
36 dt_free(preset->description);
37 dt_free(preset->operation);
38 dt_free(preset->model);
39 dt_free(preset->maker);
40 dt_free(preset->lens);
41 dt_free(preset->multi_name);
42 dt_free(preset->op_params);
43 dt_free(preset->blendop_params);
45}
46
47/* Never NULL: the callers format these with "%s" and bind them with strlen(). */
48static gchar *_column_text(sqlite3_stmt *stmt, const int col)
49{
50 const char *v = (const char *)sqlite3_column_text(stmt, col);
51 return g_strdup(v ? v : "");
52}
53
54/* Unlike _column_text(), a NULL column comes back as NULL. For callers that pass the value
55 * on to something which distinguishes "no value" from "the empty string". */
56static gchar *_column_text_or_null(sqlite3_stmt *stmt, const int col)
57{
58 const char *v = (const char *)sqlite3_column_text(stmt, col);
59 return v ? g_strdup(v) : NULL;
60}
61
62static void *_column_blob(sqlite3_stmt *stmt, const int col, int *size)
63{
64 const int n = sqlite3_column_bytes(stmt, col);
65 const void *src = sqlite3_column_blob(stmt, col);
66 *size = 0;
67 if(n <= 0 || IS_NULL_PTR(src)) return NULL;
68
69 void *copy = g_malloc(n);
70 if(IS_NULL_PTR(copy)) return NULL;
71
72 memcpy(copy, src, n);
73 *size = n;
74 return copy;
75}
76
78{
80 // clang-format off
82 "SELECT op_params, blendop_params, name, description, operation,"
83 " autoapply, model, maker, lens, iso_min, iso_max, exposure_min,"
84 " exposure_max, aperture_min, aperture_max, focal_length_min,"
85 " focal_length_max, op_version, blendop_version, enabled,"
86 " multi_priority, multi_name, filter, def, format "
87 " FROM data.presets"
88 " WHERE rowid = ?1",
89 -1, &stmt, NULL);
90 // clang-format on
92
95 {
96 p = (dt_preset_t *)g_malloc0(sizeof(dt_preset_t));
97 if(p)
98 {
99 p->op_params = _column_blob(stmt, 0, &p->op_params_size);
100 p->blendop_params = _column_blob(stmt, 1, &p->blendop_params_size);
101 p->name = _column_text(stmt, 2);
102 p->description = _column_text(stmt, 3);
103 p->operation = _column_text(stmt, 4);
104 p->autoapply = sqlite3_column_int(stmt, 5);
105 p->model = _column_text(stmt, 6);
106 p->maker = _column_text(stmt, 7);
107 p->lens = _column_text(stmt, 8);
108 p->iso_min = sqlite3_column_double(stmt, 9);
109 p->iso_max = sqlite3_column_double(stmt, 10);
110 p->exposure_min = sqlite3_column_double(stmt, 11);
111 p->exposure_max = sqlite3_column_double(stmt, 12);
112 p->aperture_min = sqlite3_column_double(stmt, 13);
113 p->aperture_max = sqlite3_column_double(stmt, 14);
114 /* REAL columns read as int, as they always have been */
115 p->focal_length_min = sqlite3_column_double(stmt, 15);
116 p->focal_length_max = sqlite3_column_double(stmt, 16);
117 p->op_version = sqlite3_column_int(stmt, 17);
118 p->blendop_version = sqlite3_column_int(stmt, 18);
119 p->enabled = sqlite3_column_int(stmt, 19);
120 p->multi_priority = sqlite3_column_int(stmt, 20);
121 p->multi_name = _column_text(stmt, 21);
122 p->filter = sqlite3_column_double(stmt, 22);
123 p->def = sqlite3_column_double(stmt, 23);
124 p->format = sqlite3_column_double(stmt, 24);
125 }
126 }
128 return p;
129}
130
131/* Bind a string that may legitimately be NULL. The previous code called strlen() on these
132 * unguarded, so a preset file missing an element -- which the XML reader answers with NULL
133 * rather than "" -- crashed on import instead of importing an empty field. */
134static void _bind_text(sqlite3_stmt *stmt, const int idx, const char *value)
135{
136 const char *v = value ? value : "";
138}
139
141{
142 if(IS_NULL_PTR(preset)) return FALSE;
143
145 // clang-format off
147 "INSERT OR REPLACE"
148 " INTO data.presets"
149 " (name, description, operation, autoapply,"
150 " model, maker, lens, iso_min, iso_max, exposure_min, exposure_max,"
151 " aperture_min, aperture_max, focal_length_min, focal_length_max,"
152 " op_params, op_version, blendop_params, blendop_version, enabled,"
153 " multi_priority, multi_name, filter, def, format, writeprotect)"
154 " VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, "
155 " ?15, ?16, ?17, ?18, ?19, ?20, ?21, ?22, ?23, ?24, ?25, 0)",
156 -1, &stmt, NULL);
157 // clang-format on
158
159 _bind_text(stmt, 1, preset->name);
160 _bind_text(stmt, 2, preset->description);
161 _bind_text(stmt, 3, preset->operation);
162 DT_DEBUG_SQLITE3_BIND_INT(stmt, 4, preset->autoapply);
163 _bind_text(stmt, 5, preset->model);
164 _bind_text(stmt, 6, preset->maker);
165 _bind_text(stmt, 7, preset->lens);
168 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 10, preset->exposure_min);
169 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 11, preset->exposure_max);
170 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 12, preset->aperture_min);
171 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 13, preset->aperture_max);
172 DT_DEBUG_SQLITE3_BIND_INT(stmt, 14, preset->focal_length_min);
173 DT_DEBUG_SQLITE3_BIND_INT(stmt, 15, preset->focal_length_max);
174 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 16, preset->op_params, preset->op_params_size, SQLITE_TRANSIENT);
175 DT_DEBUG_SQLITE3_BIND_INT(stmt, 17, preset->op_version);
176 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 18, preset->blendop_params, preset->blendop_params_size, SQLITE_TRANSIENT);
177 DT_DEBUG_SQLITE3_BIND_INT(stmt, 19, preset->blendop_version);
179 DT_DEBUG_SQLITE3_BIND_INT(stmt, 21, preset->multi_priority);
180 _bind_text(stmt, 22, preset->multi_name);
184
185 const gboolean ok = (sqlite3_step(stmt) == SQLITE_DONE);
187 return ok;
188}
189
190
191/* ---------------------------------------------------------------------------------------
192 * Module presets
193 * ------------------------------------------------------------------------------------- */
194
195/* Three of these run on every preset-menu popup, so they keep their statements, as
196 * libs/lib.c did before. The rest are one per user action. */
197
198/* The two inserts below differ in ONE digit of exposure_max -- 1e8 for a preset created
199 * from the menu, 1e7 for one registered by a module at startup -- and have since they were
200 * written. Reproduced rather than unified: with autoapply=0 the bound is never consulted,
201 * but the edit dialog opens on a just-created preset and shows it, so unifying them is a
202 * user-visible data change and belongs in its own commit. */
203#define _PRESET_COLUMNS \
204 "(name, description, operation, op_version, op_params, blendop_params, " \
205 " blendop_version, enabled, model, maker, lens, iso_min, iso_max, exposure_min, " \
206 " exposure_max, aperture_min, aperture_max, focal_length_min, focal_length_max, " \
207 " writeprotect, autoapply, filter, def, format)"
208
209void dt_module_preset_free(gpointer data)
210{
212 if(IS_NULL_PTR(p)) return;
213 dt_free(p->name);
214 dt_free(p->description);
215 dt_free(p->op_params);
216 // The IOP readers fill this one; a lib preset leaves it NULL. Missing it leaked the blend
217 // blob of every IOP preset row listed by gui/presets.c and libs/lib.c.
218 dt_free(p->blendop_params);
219 dt_free(p);
220}
221
222GList *dt_preset_repository_list_for_module(const char *operation, const int op_version,
223 const gboolean with_description,
224 const gboolean shipped_first)
225{
227 gchar *query = NULL;
228
230 {
231 // clang-format off
232 query = g_strdup_printf("SELECT name, op_params, writeprotect, description"
233 " FROM data.presets"
234 " WHERE operation=?1 AND op_version=?2"
235 " ORDER BY writeprotect %s, LOWER(name), rowid",
236 shipped_first ? "DESC" : "ASC");
237 // clang-format on
239 }
240 else
241 {
242 // clang-format off
244 "SELECT name, op_params, writeprotect FROM data.presets"
245 " WHERE operation=?1 AND op_version=?2",
246 -1, &stmt, NULL);
247 // clang-format on
248 }
249 if(IS_NULL_PTR(stmt))
250 {
251 dt_free(query);
252 return NULL;
253 }
254
256 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, op_version);
257
258 GList *presets = NULL;
259 while(sqlite3_step(stmt) == SQLITE_ROW)
260 {
262 if(p)
263 {
264 p->name = _column_text(stmt, 0);
265 p->op_params = _column_blob(stmt, 1, &p->op_params_size);
266 p->writeprotect = sqlite3_column_int(stmt, 2) != 0;
267 p->description = with_description ? _column_text(stmt, 3) : g_strdup("");
268 p->op_version = op_version;
269 p->rowid = -1;
270 presets = g_list_prepend(presets, p);
271 }
272 }
273
275 dt_free(query); // NULL in the plain branch; dt_free is NULL-safe
276
277 return g_list_reverse(presets); // the ORDER BY is the point; keep it
278}
279
281{
283 // clang-format off
285 "SELECT rowid, op_version, op_params, name FROM data.presets"
286 " WHERE operation=?1"
287 " ORDER BY writeprotect DESC, LOWER(name), rowid",
288 -1, &stmt, NULL);
289 // clang-format on
291
292 GList *presets = NULL;
293 while(sqlite3_step(stmt) == SQLITE_ROW)
294 {
296 if(p)
297 {
298 p->rowid = sqlite3_column_int(stmt, 0);
299 p->op_version = sqlite3_column_int(stmt, 1);
300 p->op_params = _column_blob(stmt, 2, &p->op_params_size);
301 p->name = _column_text(stmt, 3);
302 p->description = g_strdup("");
303 presets = g_list_prepend(presets, p);
304 }
305 }
307
308 /* Reversed so the caller iterates in the order the rows came back, which is what it did
309 * when it stepped the statement itself. */
310 return g_list_reverse(presets);
311}
312
313GList *dt_preset_repository_list_for_version(const char *operation, const int op_version)
314{
316 // clang-format off
318 "SELECT rowid, op_version, op_params, name FROM data.presets"
319 " WHERE operation=?1 AND op_version=?2"
320 " ORDER BY writeprotect DESC, LOWER(name), rowid",
321 -1, &stmt, NULL);
322 // clang-format on
324 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, op_version);
325
326 GList *presets = NULL;
327 while(sqlite3_step(stmt) == SQLITE_ROW)
328 {
330 if(p)
331 {
332 p->rowid = sqlite3_column_int(stmt, 0);
333 p->op_version = sqlite3_column_int(stmt, 1);
334 p->op_params = _column_blob(stmt, 2, &p->op_params_size);
335 p->name = _column_text(stmt, 3);
336 p->description = g_strdup("");
337 presets = g_list_prepend(presets, p);
338 }
339 }
341
342 /* Reversed so the caller iterates in the order the rows came back, which is what it did
343 * when it stepped the statement itself. */
344 return g_list_reverse(presets);
345}
346
347gboolean dt_preset_repository_module_preset_exists(const char *operation, const int op_version,
348 const char *name)
349{
351 // clang-format off
353 "SELECT name FROM data.presets"
354 " WHERE operation = ?1 AND op_version = ?2 AND name = ?3",
355 -1, &stmt, NULL);
356 // clang-format on
358 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, op_version);
360
361 const gboolean found = (sqlite3_step(stmt) == SQLITE_ROW);
363 return found;
364}
365
366int dt_preset_repository_find_rowid(const char *operation, const int op_version, const char *name)
367{
369 // clang-format off
371 "SELECT rowid FROM data.presets"
372 " WHERE name = ?1 AND operation = ?2 AND op_version = ?3",
373 -1, &stmt, NULL);
374 // clang-format on
377 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, op_version);
378
379 int rowid = -1;
382 return rowid;
383}
384
385dt_module_preset_t *dt_preset_repository_get_module_preset(const char *operation, const int op_version,
386 const char *name)
387{
389 // clang-format off
391 "SELECT op_params, writeprotect FROM data.presets"
392 " WHERE operation = ?1 AND op_version = ?2 AND name = ?3",
393 -1, &stmt, NULL);
394 // clang-format on
396 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, op_version);
398
401 {
402 p = g_malloc0(sizeof(dt_module_preset_t));
403 if(p)
404 {
405 p->op_params = _column_blob(stmt, 0, &p->op_params_size);
406 p->writeprotect = sqlite3_column_int(stmt, 1) != 0;
407 p->name = g_strdup(name);
408 p->description = g_strdup("");
409 p->op_version = op_version;
410 p->rowid = -1;
411 }
412 }
414 return p;
415}
416
417void dt_preset_repository_add_module_preset(const char *name, const char *operation,
418 const int op_version, const void *params,
419 const int params_size)
420{
422 // clang-format off
424 "INSERT INTO data.presets " _PRESET_COLUMNS
425 " VALUES (?1, '', ?2, ?3, ?4, NULL, 0, 1, '%', '%', '%', 0, "
426 " 340282346638528859812000000000000000000, 0, 100000000, 0, 100000000, "
427 " 0, 1000, 0, 0, 0, 0, 0)",
428 -1, &stmt, NULL);
429 // clang-format on
432 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, op_version);
436}
437
438void dt_preset_repository_add_shipped_preset(const char *name, const char *operation,
439 const int op_version, const void *params,
440 const int params_size, const int writeprotect)
441{
443 // clang-format off
445 "INSERT INTO data.presets " _PRESET_COLUMNS
446 " VALUES (?1, '', ?2, ?3, ?4, NULL, 0, 1, '%', '%', '%', 0, "
447 " 340282346638528859812000000000000000000, 0, 10000000, 0, 100000000, "
448 " 0, 1000, ?5, 0, 0, 0, 0)",
449 -1, &stmt, NULL);
450 // clang-format on
451 if(IS_NULL_PTR(stmt)) return;
452
455 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, op_version);
457 DT_DEBUG_SQLITE3_BIND_INT(stmt, 5, writeprotect);
460}
461
462void dt_preset_repository_update_module_params(const char *operation, const char *name,
463 const int op_version, const void *params,
464 const int params_size)
465{
467 // clang-format off
469 "UPDATE data.presets SET op_version=?2, op_params=?3"
470 " WHERE name=?4 AND operation=?1",
471 -1, &stmt, NULL);
472 // clang-format on
474 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, op_version);
479}
480
481void dt_preset_repository_set_module_version(const char *operation, const char *name,
482 const int op_version)
483{
486 "UPDATE data.presets SET op_version=?1 WHERE operation=?2 AND name=?3",
487 -1, &stmt, NULL);
488 if(IS_NULL_PTR(stmt)) return;
489
490 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, op_version);
495}
496
497void dt_preset_repository_set_blend_params(const char *operation, const char *name,
498 const int blendop_version, const void *blend_params,
499 const int blend_params_size)
500{
502 // clang-format off
504 "SET blendop_version=?1, blendop_params=?2 "
505 "WHERE operation=?3 AND name=?4",
506 -1, &stmt, NULL);
507 // clang-format on
508 if(IS_NULL_PTR(stmt)) return;
509
510 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, blendop_version);
516}
517
519{
521 // clang-format off
524 "SELECT name, op_version, op_params, blendop_version, blendop_params FROM data.presets WHERE operation = ?1",
525 -1, &stmt, NULL);
526 // clang-format on
527 if(IS_NULL_PTR(stmt)) return NULL;
528
530
531 GList *presets = NULL;
532 while(sqlite3_step(stmt) == SQLITE_ROW)
533 {
535 if(IS_NULL_PTR(p)) break;
536 p->name = _column_text(stmt, 0);
537 p->op_version = sqlite3_column_int(stmt, 1);
538 p->op_params = _column_blob(stmt, 2, &p->op_params_size);
539 p->blendop_version = sqlite3_column_int(stmt, 3);
540 p->blendop_params = _column_blob(stmt, 4, &p->blendop_params_size);
541 p->description = g_strdup("");
542 presets = g_list_prepend(presets, p);
543 }
545
546 return g_list_reverse(presets); // row order, as the cursor loop this replaced saw it
547}
548
549void dt_preset_repository_rename_module_preset(const char *operation, const int op_version,
550 const char *old_name, const char *new_name,
551 const char *description, const void *params,
552 const int params_size)
553{
555 // clang-format off
557 "UPDATE data.presets SET name = ?1, description = ?2, op_params = ?3"
558 " WHERE operation = ?4 AND op_version = ?5 AND name = ?6",
559 -1, &stmt, NULL);
560 // clang-format on
565 DT_DEBUG_SQLITE3_BIND_INT(stmt, 5, op_version);
569}
570
571void dt_preset_repository_duplicate_module_preset(const char *operation, const int op_version,
572 const char *name, const char *new_name)
573{
575 // clang-format off
577 "INSERT INTO data.presets " _PRESET_COLUMNS
578 " SELECT ?1, description, operation, op_version, op_params, blendop_params,"
579 " blendop_version, enabled, model, maker, lens, iso_min, iso_max,"
580 " exposure_min, exposure_max, aperture_min, aperture_max,"
581 " focal_length_min, focal_length_max, 0, autoapply, filter, def, format"
582 " FROM data.presets"
583 " WHERE operation = ?2 AND op_version = ?3 AND name = ?4",
584 -1, &stmt, NULL);
585 // clang-format on
588 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, op_version);
592}
593
594void dt_preset_repository_delete_module_preset(const char *operation, const int op_version,
595 const char *name)
596{
598 // clang-format off
600 "DELETE FROM data.presets"
601 " WHERE name=?1 AND operation=?2 AND op_version=?3 AND writeprotect=0",
602 -1, &stmt, NULL);
603 // clang-format on
604 if(IS_NULL_PTR(stmt)) return;
605
608 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, op_version);
611}
612
614{
616 // clang-format off
618 "DELETE FROM data.presets WHERE operation=?1",
619 -1, &stmt, NULL);
620 // clang-format on
621 if(IS_NULL_PTR(stmt)) return;
622
626}
627
628void dt_preset_repository_update_params_by_rowid(const int rowid, const int op_version,
629 const void *params, const int params_size)
630{
632 // clang-format off
634 "UPDATE data.presets SET op_version=?1, op_params=?2 WHERE rowid=?3",
635 -1, &stmt, NULL);
636 // clang-format on
637 DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, op_version);
642}
643
645{
647 // clang-format off
649 "DELETE FROM data.presets WHERE rowid=?1", -1, &stmt, NULL);
650 // clang-format on
654}
655
656
657/* ---------------------------------------------------------------------------------------
658 * Auto-apply conditions
659 * ------------------------------------------------------------------------------------- */
660
661/* One literal query per column, indexed by the enum rather than assembled, so
662 * `grep "iso_min" src/database` still finds the one that writes it. Prepared per call:
663 * the cached statements these replaced were unlocked cross-thread shared state. */
664
665static const char *const _range_query[DT_PRESET_RANGE_LAST] = {
666 [DT_PRESET_RANGE_ISO] = "UPDATE data.presets"
667 " SET iso_min=?1, iso_max=?2"
668 " WHERE operation=?3 AND op_version=?4 AND name=?5",
669 [DT_PRESET_RANGE_APERTURE] = "UPDATE data.presets"
670 " SET aperture_min=?1, aperture_max=?2"
671 " WHERE operation=?3 AND op_version=?4 AND name=?5",
672 [DT_PRESET_RANGE_EXPOSURE] = "UPDATE data.presets"
673 " SET exposure_min=?1, exposure_max=?2"
674 " WHERE operation=?3 AND op_version=?4 AND name=?5",
675 [DT_PRESET_RANGE_FOCAL_LENGTH] = "UPDATE data.presets"
676 " SET focal_length_min=?1, focal_length_max=?2"
677 " WHERE operation=?3 AND op_version=?4 AND name=?5",
678};
679
680static const char *const _flag_query[DT_PRESET_FLAG_LAST] = {
681 [DT_PRESET_FLAG_FORMAT] = "UPDATE data.presets"
682 " SET format=?1"
683 " WHERE operation=?2 AND op_version=?3 AND name=?4",
684 [DT_PRESET_FLAG_AUTOAPPLY] = "UPDATE data.presets"
685 " SET autoapply=?1"
686 " WHERE operation=?2 AND op_version=?3 AND name=?4",
687 [DT_PRESET_FLAG_FILTER] = "UPDATE data.presets"
688 " SET filter=?1"
689 " WHERE operation=?2 AND op_version=?3 AND name=?4",
690};
691
692void dt_preset_repository_update_range(const char *operation, const int op_version, const char *name,
693 const dt_preset_range_t range,
694 const double min, const double max)
695{
696 // No `range < 0`: dt_preset_range_t has no negative enumerator, so the compiler gives it an
697 // unsigned type and clang rejects the comparison as always-false under -Werror. Nothing is
698 // lost -- a negative value cast into the enum arrives as a large positive one, which the
699 // upper bound catches.
700 if(range >= DT_PRESET_RANGE_LAST) return;
701
704 -1, &stmt, NULL);
705 if(IS_NULL_PTR(stmt)) return;
706
710 DT_DEBUG_SQLITE3_BIND_INT(stmt, 4, op_version);
714}
715
716void dt_preset_repository_update_flag(const char *operation, const int op_version, const char *name,
717 const dt_preset_flag_t flag, const int value)
718{
719 // Same as dt_preset_repository_update_range() above: the enum is unsigned, so the lower
720 // bound is dead and the upper bound catches a garbage value either way.
721 if(flag >= DT_PRESET_FLAG_LAST) return;
722
725 -1, &stmt, NULL);
726 if(IS_NULL_PTR(stmt)) return;
727
730 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, op_version);
734}
735
736void dt_preset_repository_update_camera(const char *operation, const int op_version, const char *name,
737 const char *maker, const char *model, const char *lens)
738{
740 // clang-format off
742 "UPDATE data.presets"
743 " SET maker='%' || ?1 || '%', model=?2, lens=?3"
744 " WHERE operation=?4 AND op_version=?5 AND name=?6",
745 -1, &stmt, NULL);
746 // clang-format on
747 if(IS_NULL_PTR(stmt)) return;
748
749 /* An empty model or lens means "any", and the auto-apply query matches with LIKE, so it
750 * has to be stored as the wildcard rather than as "". */
753 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, (lens && *lens) ? lens : "%", -1, SQLITE_TRANSIENT);
755 DT_DEBUG_SQLITE3_BIND_INT(stmt, 5, op_version);
759}
760
761
762/* ---------------------------------------------------------------------------------------
763 * IOP presets
764 * ------------------------------------------------------------------------------------- */
765
766/* The predicate shared by the menu and the auto-apply query: does this preset's stored
767 * camera/exposure/format match the image? Bound parameters ?2..?12 throughout, so the
768 * three call sites bind identically. */
769#define _PRESET_MATCH_PREDICATE \
770 "((?2 LIKE model AND ?3 LIKE maker) OR (?4 LIKE model AND ?5 LIKE maker))" \
771 " AND ?6 LIKE lens" \
772 " AND ?7 BETWEEN iso_min AND iso_max" \
773 " AND ?8 BETWEEN exposure_min AND exposure_max" \
774 " AND ?9 BETWEEN aperture_min AND aperture_max" \
775 " AND ?10 BETWEEN focal_length_min AND focal_length_max" \
776 " AND (format = 0 OR (format&?11 != 0 AND ~format&?12 != 0))"
777
778static void _bind_match(sqlite3_stmt *stmt, const dt_preset_match_t *m, const gboolean clamp)
779{
782 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, m->camera_alias, -1, SQLITE_TRANSIENT);
783 DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 5, m->camera_maker, -1, SQLITE_TRANSIENT);
785
786 /* The auto-apply path clamps these and the menu path does not. That difference is
787 * inherited and kept: a NaN or an infinity from a broken EXIF block makes every BETWEEN
788 * false, which silently applies nothing -- so the path that decides an image's initial
789 * history guards against it and the one that only draws a menu never bothered. */
790 if(clamp)
791 {
793 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 8, fmax(0.0, fmin(1000000.0, m->exposure)));
794 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 9, fmax(0.0, fmin(1000000.0, m->aperture)));
795 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 10, fmax(0.0, fmin(1000000.0, m->focal_length)));
796 }
797 else
798 {
800 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 8, m->exposure);
801 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 9, m->aperture);
802 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 10, m->focal_length);
803 }
804
805 DT_DEBUG_SQLITE3_BIND_INT(stmt, 11, m->format);
806 DT_DEBUG_SQLITE3_BIND_INT(stmt, 12, m->excluded);
807}
808
809/* Read the seven-column menu row, or the five-column list row when `description` and the
810 * trailing columns are absent. */
812{
814 if(IS_NULL_PTR(p)) return NULL;
815
816 p->rowid = -1;
817 p->name = _column_text(stmt, 0);
818 p->op_params = _column_blob(stmt, 1, &p->op_params_size);
819 p->writeprotect = sqlite3_column_int(stmt, 2) != 0;
820
822 {
823 p->description = _column_text(stmt, 3);
824 p->blendop_params = _column_blob(stmt, 4, &p->blendop_params_size);
825 p->op_version = sqlite3_column_int(stmt, 5);
826 p->enabled = sqlite3_column_int(stmt, 6);
827 }
828 else
829 {
830 p->description = g_strdup("");
831 p->blendop_params = _column_blob(stmt, 3, &p->blendop_params_size);
832 p->enabled = sqlite3_column_int(stmt, 4);
833 }
834 return p;
835}
836
837void dt_preset_repository_add_iop_preset(const char *name, const char *operation, const int op_version,
838 const void *params, const int params_size,
839 const void *blend_params, const int blend_params_size,
840 const int blendop_version, const int enabled)
841{
843 // clang-format off
845 "INSERT OR REPLACE"
846 " INTO data.presets (name, description, operation, op_version, op_params, enabled,"
847 " blendop_params, blendop_version, multi_priority, multi_name,"
848 " model, maker, lens, iso_min, iso_max, exposure_min, exposure_max,"
849 " aperture_min, aperture_max, focal_length_min, focal_length_max,"
850 " writeprotect, autoapply, filter, def, format)"
851 " VALUES (?1, '', ?2, ?3, ?4, ?5, ?6, ?7, 0, '', '%', '%', '%', 0,"
852 " 340282346638528859812000000000000000000, 0, 10000000, 0, 100000000, 0,"
853 " 1000, 1, 0, 0, 0, 0)",
854 -1, &stmt, NULL);
855 // clang-format on
856 if(IS_NULL_PTR(stmt)) return;
857
860 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, op_version);
864 DT_DEBUG_SQLITE3_BIND_INT(stmt, 7, blendop_version);
867}
868
869GList *dt_preset_repository_list_for_iop(const char *operation, const int op_version)
870{
872 /* writeprotect ASC, not DESC: a user's copy of a shipped preset must resolve to the
873 * copy, otherwise the name that comes back is the write-protected one and the caller
874 * cannot delete it. */
875 // clang-format off
877 "SELECT name, op_params, writeprotect, blendop_params, enabled"
878 " FROM data.presets"
879 " WHERE operation=?1 AND op_version=?2"
880 " ORDER BY writeprotect ASC, LOWER(name), rowid",
881 -1, &stmt, NULL);
882 // clang-format on
884 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, op_version);
885
886 GList *presets = NULL;
887 while(sqlite3_step(stmt) == SQLITE_ROW)
888 {
890 if(p)
891 {
892 p->op_version = op_version;
893 presets = g_list_prepend(presets, p);
894 }
895 }
897 return g_list_reverse(presets);
898}
899
900GList *dt_preset_repository_list_for_menu(const char *operation, const dt_preset_match_t *match,
901 const gboolean shipped_first)
902{
904 gchar *query = NULL;
905
906 if(match)
907 {
908 // clang-format off
910 "SELECT name, op_params, writeprotect, description, blendop_params, "
911 " op_version, enabled"
912 " FROM data.presets"
913 " WHERE operation=?1"
914 " AND (filter=0"
915 " OR"
917 " ORDER BY writeprotect %s, LOWER(name), rowid",
918 shipped_first ? "DESC" : "ASC");
919 // clang-format on
920 }
921 else
922 {
923 // don't know for which image. show all we got:
924 // clang-format off
926 "SELECT name, op_params, writeprotect, "
927 " description, blendop_params, op_version, enabled"
928 " FROM data.presets"
929 " WHERE operation=?1"
930 " ORDER BY writeprotect %s, LOWER(name), rowid",
931 shipped_first ? "DESC" : "ASC");
932 // clang-format on
933 }
934
937 if(match) _bind_match(stmt, match, FALSE);
938 dt_free(query);
939
940 GList *presets = NULL;
941 while(sqlite3_step(stmt) == SQLITE_ROW)
942 {
944 if(p) presets = g_list_prepend(presets, p);
945 }
947 return g_list_reverse(presets);
948}
949
950dt_module_preset_t *dt_preset_repository_get_iop_preset(const char *operation, const int op_version,
951 const char *name)
952{
954 // clang-format off
956 "SELECT op_params, enabled, blendop_params, blendop_version, writeprotect"
957 " FROM data.presets"
958 " WHERE operation = ?1 AND op_version = ?2 AND name = ?3",
959 -1, &stmt, NULL);
960 // clang-format on
962 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, op_version);
964
967 {
968 p = g_malloc0(sizeof(dt_module_preset_t));
969 if(p)
970 {
971 p->rowid = -1;
972 p->name = g_strdup(name);
973 p->description = g_strdup("");
974 p->op_version = op_version;
975 p->op_params = _column_blob(stmt, 0, &p->op_params_size);
976 p->enabled = sqlite3_column_int(stmt, 1);
977 p->blendop_params = _column_blob(stmt, 2, &p->blendop_params_size);
978 p->blendop_version = sqlite3_column_int(stmt, 3);
979 p->writeprotect = sqlite3_column_int(stmt, 4) != 0;
980 }
981 }
983 return p;
984}
985
986GList *dt_preset_repository_find_autoapply(const char *operation, const int op_version,
987 const dt_preset_match_t *match, const char *always_name)
988{
989 if(IS_NULL_PTR(match)) return NULL;
990
992 /* A plain literal. This was assembled with snprintf() into a 2024-byte buffer despite
993 * having no format specifier in it -- a copy that did nothing, and a `%` away from being
994 * a bug. */
995 // clang-format off
997 "SELECT name"
998 " FROM data.presets"
999 " WHERE operation = ?1"
1000 " AND ((autoapply=1"
1002 " AND operation NOT IN"
1003 " ('ioporder', 'metadata', 'export', 'tagging', 'collect', 'basecurve'))"
1004 " OR (name = ?13)) AND op_version = ?14",
1005 -1, &stmt, NULL);
1006 // clang-format on
1008 _bind_match(stmt, match, TRUE);
1010 DT_DEBUG_SQLITE3_BIND_INT(stmt, 14, op_version);
1011
1012 GList *names = NULL;
1013 while(sqlite3_step(stmt) == SQLITE_ROW)
1016 return g_list_reverse(names);
1017}
1018
1019
1020/* ---------------------------------------------------------------------------------------
1021 * The preset edit dialog
1022 * ------------------------------------------------------------------------------------- */
1023
1025{
1026 if(IS_NULL_PTR(c)) return;
1027 dt_free(c->name);
1028 dt_free(c->description);
1029 dt_free(c->model);
1030 dt_free(c->maker);
1031 dt_free(c->lens);
1032}
1033
1034gboolean dt_preset_repository_get_conditions(const char *operation, const int op_version,
1035 const char *name, dt_preset_conditions_t *c, int *rowid)
1036{
1037 if(IS_NULL_PTR(c) || IS_NULL_PTR(rowid)) return FALSE;
1038 *rowid = -1;
1039
1041 // clang-format off
1043 "SELECT rowid, description, model, maker, lens, iso_min, iso_max, "
1044 " exposure_min, exposure_max, aperture_min, aperture_max, focal_length_min, "
1045 " focal_length_max, autoapply, filter, format"
1046 " FROM data.presets"
1047 " WHERE name = ?1 AND operation = ?2 AND op_version = ?3",
1048 -1, &stmt, NULL);
1049 // clang-format on
1052 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, op_version);
1053
1054 gboolean found = FALSE;
1056 {
1057 found = TRUE;
1058 *rowid = sqlite3_column_int(stmt, 0);
1059 c->name = g_strdup(name);
1060 c->description = _column_text(stmt, 1);
1061 c->model = _column_text(stmt, 2);
1062 c->maker = _column_text(stmt, 3);
1063 c->lens = _column_text(stmt, 4);
1064 c->iso_min = sqlite3_column_double(stmt, 5);
1065 c->iso_max = sqlite3_column_double(stmt, 6);
1066 c->exposure_min = sqlite3_column_double(stmt, 7);
1067 c->exposure_max = sqlite3_column_double(stmt, 8);
1068 c->aperture_min = sqlite3_column_double(stmt, 9);
1069 c->aperture_max = sqlite3_column_double(stmt, 10);
1070 c->focal_length_min = sqlite3_column_double(stmt, 11);
1071 c->focal_length_max = sqlite3_column_double(stmt, 12);
1072 c->autoapply = sqlite3_column_int(stmt, 13);
1073 c->filter = sqlite3_column_int(stmt, 14);
1074 c->format = sqlite3_column_int(stmt, 15);
1075 }
1077 return found;
1078}
1079
1080/* Bind the sixteen condition columns, which the update and the insert share in the same
1081 * order. */
1083{
1084 _bind_text(stmt, 1, c->name);
1085 _bind_text(stmt, 2, c->description);
1086 _bind_text(stmt, 3, c->model);
1087 _bind_text(stmt, 4, c->maker);
1088 _bind_text(stmt, 5, c->lens);
1089 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 6, c->iso_min);
1090 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 7, c->iso_max);
1091 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 8, c->exposure_min);
1092 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 9, c->exposure_max);
1093 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 10, c->aperture_min);
1094 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 11, c->aperture_max);
1095 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 12, c->focal_length_min);
1096 DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 13, c->focal_length_max);
1097 DT_DEBUG_SQLITE3_BIND_INT(stmt, 14, c->autoapply);
1098 DT_DEBUG_SQLITE3_BIND_INT(stmt, 15, c->filter);
1099 DT_DEBUG_SQLITE3_BIND_INT(stmt, 16, c->format);
1100}
1101
1103{
1104 if(IS_NULL_PTR(c)) return;
1105
1107 /* rowid is bound as ?17. It used to be pasted in with g_strdup_printf("... rowid=%d"),
1108 * which meant building the query text on every save for a value that is an integer from
1109 * the database. */
1110 // clang-format off
1112 "UPDATE data.presets "
1113 "SET"
1114 " name=?1, description=?2,"
1115 " model=?3, maker=?4, lens=?5, iso_min=?6, iso_max=?7, exposure_min=?8,"
1116 " exposure_max=?9, aperture_min=?10,"
1117 " aperture_max=?11, focal_length_min=?12, focal_length_max=?13, autoapply=?14,"
1118 " filter=?15, format=?16 "
1119 "WHERE rowid=?17",
1120 -1, &stmt, NULL);
1121 // clang-format on
1123 DT_DEBUG_SQLITE3_BIND_INT(stmt, 17, rowid);
1126}
1127
1129 const char *operation, const int op_version,
1130 const void *params, const int params_size,
1131 const int enabled,
1132 const void *blend_params, const int blend_params_size,
1133 const int blendop_version)
1134{
1135 if(IS_NULL_PTR(c)) return;
1136
1138 // clang-format off
1140 "INSERT INTO data.presets"
1141 " (name, description, "
1142 " model, maker, lens, iso_min, iso_max, exposure_min, exposure_max, aperture_min,"
1143 " aperture_max, focal_length_min, focal_length_max, autoapply,"
1144 " filter, format, def, writeprotect, operation, op_version, op_params, enabled,"
1145 " blendop_params, blendop_version, multi_priority, multi_name) "
1146 "VALUES"
1147 " (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, 0, 0, ?17,"
1148 " ?18, ?19, ?20, ?21, ?22, 0, '')",
1149 -1, &stmt, NULL);
1150 // clang-format on
1153 DT_DEBUG_SQLITE3_BIND_INT(stmt, 18, op_version);
1157 DT_DEBUG_SQLITE3_BIND_INT(stmt, 22, blendop_version);
1160}
1161
1162gboolean dt_preset_repository_get_identity(const int rowid, gchar **operation, int *op_version)
1163{
1164 if(IS_NULL_PTR(operation) || IS_NULL_PTR(op_version)) return FALSE;
1165 *operation = NULL;
1166 *op_version = 0;
1167
1169 // clang-format off
1171 "SELECT operation, op_version FROM data.presets WHERE rowid = ?1",
1172 -1, &stmt, NULL);
1173 // clang-format on
1175
1176 gboolean found = FALSE;
1178 {
1179 found = TRUE;
1180 *operation = _column_text(stmt, 0);
1181 *op_version = sqlite3_column_int(stmt, 1);
1182 }
1184 return found;
1185}
1186
1187void dt_preset_repository_update_iop_params(const char *operation, const char *name,
1188 const int op_version,
1189 const void *params, const int params_size,
1190 const int enabled,
1191 const void *blend_params, const int blend_params_size,
1192 const int blendop_version)
1193{
1195 // clang-format off
1197 "UPDATE data.presets"
1198 " SET op_version=?2, op_params=?3, enabled=?4,"
1199 " blendop_params=?5, blendop_version=?6"
1200 " WHERE name=?7 AND operation=?1",
1201 -1, &stmt, NULL);
1202 // clang-format on
1204 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, op_version);
1208 DT_DEBUG_SQLITE3_BIND_INT(stmt, 6, blendop_version);
1212}
1213
1215{
1217 // clang-format off
1219 "DELETE FROM data.presets WHERE rowid=?1 AND writeprotect=0",
1220 -1, &stmt, NULL);
1221 // clang-format on
1225}
1226
1228{
1230 "DELETE FROM data.presets WHERE writeprotect = 1", NULL, NULL, NULL);
1231}
1232
1233void dt_preset_row_free(gpointer data)
1234{
1236 if(IS_NULL_PTR(row)) return;
1237 dt_free(row->name);
1238 dt_free(row->operation);
1239 dt_free(row->model);
1240 dt_free(row->maker);
1241 dt_free(row->lens);
1242 dt_free(row);
1243}
1244
1246{
1247 GList *rows = NULL;
1249 // clang-format off
1251 "SELECT rowid, name, operation, autoapply, model, maker, lens, iso_min, "
1252 "iso_max, exposure_min, exposure_max, aperture_min, aperture_max, "
1253 "focal_length_min, focal_length_max, writeprotect FROM data.presets ORDER BY "
1254 "operation, name",
1255 -1, &stmt, NULL);
1256 // clang-format on
1257 if(IS_NULL_PTR(stmt)) return NULL;
1258
1259 while(sqlite3_step(stmt) == SQLITE_ROW)
1260 {
1262 if(IS_NULL_PTR(row)) break;
1264 // NULL is preserved rather than normalised to "" by _column_text(): the caller passes
1265 // these straight to g_strcmp0()/g_strdup() and into a GtkTreeStore, all of which treat
1266 // the two differently, and the loop this replaced handed them the raw column.
1267 row->name = _column_text_or_null(stmt, 1);
1268 row->operation = _column_text_or_null(stmt, 2);
1269 row->autoapply = (sqlite3_column_int(stmt, 3) == 0 ? FALSE : TRUE);
1270 row->model = _column_text_or_null(stmt, 4);
1271 row->maker = _column_text_or_null(stmt, 5);
1272 row->lens = _column_text_or_null(stmt, 6);
1273 row->iso_min = sqlite3_column_double(stmt, 7);
1274 row->iso_max = sqlite3_column_double(stmt, 8);
1275 row->exposure_min = sqlite3_column_double(stmt, 9);
1276 row->exposure_max = sqlite3_column_double(stmt, 10);
1277 row->aperture_min = sqlite3_column_double(stmt, 11);
1278 row->aperture_max = sqlite3_column_double(stmt, 12);
1279 row->focal_length_min = sqlite3_column_double(stmt, 13);
1280 row->focal_length_max = sqlite3_column_double(stmt, 14);
1281 row->writeprotect = (sqlite3_column_int(stmt, 15) == 0 ? FALSE : TRUE);
1282 rows = g_list_prepend(rows, row);
1283 }
1285
1286 // Row order, not reverse-row: the caller walks it once and starts a new module node every
1287 // time `operation` changes, which only works in the ORDER BY's own order.
1288 return g_list_reverse(rows);
1289}
1290
1291void dt_preset_identity_free(gpointer data)
1292{
1294 if(IS_NULL_PTR(row)) return;
1295 dt_free(row->name);
1296 dt_free(row->operation);
1297 dt_free(row);
1298}
1299
1301{
1302 GList *rows = NULL;
1305 "SELECT rowid, name, operation FROM data.presets WHERE writeprotect = 0",
1306 -1, &stmt, NULL);
1307 if(IS_NULL_PTR(stmt)) return NULL;
1308
1309 while(sqlite3_step(stmt) == SQLITE_ROW)
1310 {
1312 if(IS_NULL_PTR(row)) break;
1314 row->name = _column_text_or_null(stmt, 1);
1315 row->operation = _column_text_or_null(stmt, 2);
1316 rows = g_list_prepend(rows, row);
1317 }
1319
1320 return g_list_reverse(rows); // row order: the caller writes one file per row, in order
1321}
1322
1324{
1325 /* Nothing cached any more: every statement in this file is prepared and finalised per
1326 * call. Kept because the connection's close order calls every repository's cleanup. */
1327}
1328
1329// clang-format off
1330// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
1331// vim: shiftwidth=2 expandtab tabstop=2 cindent
1332// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
1333// clang-format on
const char ** description(struct dt_iop_module_t *self)
Definition ashift.c:168
#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:571
#define m
Definition basecurve.c:283
const float v
static const float const float const float min
const float max
static const int row
sqlite3 * dt_database_get_sqlite3_global(void)
Definition database.c:3790
GHashTable * names
GtkWidget* -> the name the application knows it by.
gboolean enabled
–doc was passed on the command line
const char flag
Definition image.h:311
struct dt_iop_tonecurve_params_t preset
const char * maker
const char * model
static const dt_iop_drawlayer_params_t * params
Definition layers.h:80
#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 macros.h:96
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
Definition mem_alloc.h:171
size_t size
Definition mipmap_cache.c:3
static float clamp(float f, float m, float M)
const char * name
Definition pdf.h:90
gboolean dt_preset_repository_insert(const dt_preset_t *preset)
Insert preset, replacing any row that collides with it.
void dt_preset_repository_delete_module_preset(const char *operation, const int op_version, const char *name)
Delete (operation, op_version, name) unless it is write-protected.
void dt_preset_repository_add_iop_preset(const char *name, const char *operation, const int op_version, const void *params, const int params_size, const void *blend_params, const int blend_params_size, const int blendop_version, const int enabled)
Store an IOP preset, blend parameters included, replacing any of the same name.
void dt_module_preset_free(gpointer data)
Release one dt_module_preset_t. Suits g_list_free_full().
#define _PRESET_COLUMNS
GList * dt_preset_repository_list_all(void)
Every preset, ordered by (operation, name) – the grouping the tree relies on to start a new module no...
GList * dt_preset_repository_list_all_versions(const char *operation)
Every preset of operation at ANY version, with rowid and op_version filled in, SHIPPED FIRST then by ...
static dt_module_preset_t * _iop_row(sqlite3_stmt *stmt, const gboolean with_description)
static gchar * _column_text_or_null(sqlite3_stmt *stmt, const int col)
void dt_preset_row_free(gpointer data)
Free one dt_preset_row_t. Suits g_list_free_full().
static void * _column_blob(sqlite3_stmt *stmt, const int col, int *size)
void dt_preset_repository_update_range(const char *operation, const int op_version, const char *name, const dt_preset_range_t range, const double min, const double max)
Set the <range>_min / <range>_max pair of (operation, op_version, name).
GList * dt_preset_repository_list_for_module(const char *operation, const int op_version, const gboolean with_description, const gboolean shipped_first)
Every preset of (operation, op_version).
void dt_preset_repository_delete_shipped(void)
Delete every write-protected preset – the auto-generated ones, dropped at startup so module code can ...
void dt_preset_repository_cleanup(void)
Finalise the cached statements. See dt_colorlabel_repository_cleanup().
void dt_preset_repository_update_iop_params(const char *operation, const char *name, const int op_version, const void *params, const int params_size, const int enabled, const void *blend_params, const int blend_params_size, const int blendop_version)
Replace the module payload of (operation, name), at any version.
dt_module_preset_t * dt_preset_repository_get_iop_preset(const char *operation, const int op_version, const char *name)
One IOP preset by name, blend parameters included, or NULL.
dt_preset_t * dt_preset_repository_get_by_rowid(const int rowid)
The preset at rowid, or NULL when there is none. Free with dt_preset_free().
dt_module_preset_t * dt_preset_repository_get_module_preset(const char *operation, const int op_version, const char *name)
One preset by name, or NULL. Free with dt_module_preset_free().
void dt_preset_repository_update_conditions(const int rowid, const dt_preset_conditions_t *c)
Overwrite the conditions of the row at rowid.
GList * dt_preset_repository_list_for_menu(const char *operation, const dt_preset_match_t *match, const gboolean shipped_first)
Presets of operation to offer in a menu, in display order.
GList * dt_preset_repository_list_editable(void)
Every preset the user may edit (writeprotect = 0), in row order.
void dt_preset_repository_update_params_by_rowid(const int rowid, const int op_version, const void *params, const int params_size)
Replace the parameters of one row, by rowid.
GList * dt_preset_repository_list_for_upgrade(const char *operation)
Every preset of operation at any version, with both parameter blobs.
int dt_preset_repository_find_rowid(const char *operation, const int op_version, const char *name)
rowid of (operation, op_version, name), or -1.
static gchar * _column_text(sqlite3_stmt *stmt, const int col)
void dt_preset_repository_update_camera(const char *operation, const int op_version, const char *name, const char *maker, const char *model, const char *lens)
Set the camera match of (operation, op_version, name).
void dt_preset_repository_update_module_params(const char *operation, const char *name, const int op_version, const void *params, const int params_size)
Replace the parameters (and version) of (operation, name).
static const char *const _flag_query[DT_PRESET_FLAG_LAST]
void dt_preset_identity_free(gpointer data)
Free one dt_preset_identity_t. Suits g_list_free_full().
void dt_preset_repository_add_module_preset(const char *name, const char *operation, const int op_version, const void *params, const int params_size)
Create an empty user preset holding params, as the "new preset" menu item does.
GList * dt_preset_repository_list_for_version(const char *operation, const int op_version)
As above, restricted to one op_version. Same columns, same order.
void dt_preset_repository_delete_by_rowid(const int rowid)
Delete one row by rowid.
gboolean dt_preset_repository_get_conditions(const char *operation, const int op_version, const char *name, dt_preset_conditions_t *c, int *rowid)
Read the conditions of (operation, op_version, name).
static void _bind_conditions(sqlite3_stmt *stmt, const dt_preset_conditions_t *c)
static void _bind_text(sqlite3_stmt *stmt, const int idx, const char *value)
void dt_preset_repository_delete_all_for_module(const char *operation)
Delete every preset of operation, whatever its version or protection.
void dt_preset_free(dt_preset_t *preset)
Release a dt_preset_t and everything it owns. NULL-safe.
gboolean dt_preset_repository_module_preset_exists(const char *operation, const int op_version, const char *name)
TRUE when (operation, op_version, name) exists.
GList * dt_preset_repository_list_for_iop(const char *operation, const int op_version)
Every preset of (operation, op_version), with blend parameters.
void dt_preset_repository_rename_module_preset(const char *operation, const int op_version, const char *old_name, const char *new_name, const char *description, const void *params, const int params_size)
Replace name, description and parameters of (operation, op_version, old_name).
void dt_preset_repository_set_module_version(const char *operation, const char *name, const int op_version)
Set ONLY the version of (operation, name), leaving the parameters alone.
void dt_preset_repository_set_blend_params(const char *operation, const char *name, const int blendop_version, const void *blend_params, const int blend_params_size)
Replace the blend parameters (and blend version) of (operation, name), at any version....
void dt_preset_repository_delete_by_rowid_unprotected(const int rowid)
Delete the row at rowid unless it is write-protected.
void dt_preset_conditions_free(dt_preset_conditions_t *c)
Release the strings owned by c (not c itself).
gboolean dt_preset_repository_get_identity(const int rowid, gchar **operation, int *op_version)
The (operation, op_version) a rowid belongs to. Returns FALSE if there is none; *operation is newly a...
void dt_preset_repository_add_shipped_preset(const char *name, const char *operation, const int op_version, const void *params, const int params_size, const int writeprotect)
Create a preset from code rather than from the menu – the built-in presets a module registers at star...
void dt_preset_repository_update_flag(const char *operation, const int op_version, const char *name, const dt_preset_flag_t flag, const int value)
Set one integer condition of (operation, op_version, name).
static const char *const _range_query[DT_PRESET_RANGE_LAST]
void dt_preset_repository_insert_with_conditions(const dt_preset_conditions_t *c, const char *operation, const int op_version, const void *params, const int params_size, const int enabled, const void *blend_params, const int blend_params_size, const int blendop_version)
Create a preset from a full condition set plus its module payload.
void dt_preset_repository_duplicate_module_preset(const char *operation, const int op_version, const char *name, const char *new_name)
Copy (operation, op_version, name) to new_name, unprotected.
GList * dt_preset_repository_find_autoapply(const char *operation, const int op_version, const dt_preset_match_t *match, const char *always_name)
Names of the presets that should be applied to this image automatically.
#define _PRESET_MATCH_PREDICATE
static void _bind_match(sqlite3_stmt *stmt, const dt_preset_match_t *m, const gboolean clamp)
data.presets: a module's saved parameters, with the conditions under which it auto-applies.
dt_preset_flag_t
@ DT_PRESET_FLAG_FORMAT
@ DT_PRESET_FLAG_FILTER
@ DT_PRESET_FLAG_LAST
@ DT_PRESET_FLAG_AUTOAPPLY
dt_preset_range_t
@ DT_PRESET_RANGE_FOCAL_LENGTH
@ DT_PRESET_RANGE_ISO
@ DT_PRESET_RANGE_APERTURE
@ DT_PRESET_RANGE_LAST
@ DT_PRESET_RANGE_EXPOSURE
void copy(TYPE *dest, TYPE *source, size_t num_el)
Copy a flat buffer used to initialize test matrices.
static const dt_aligned_pixel_simd_t value
Definition simd.h:144
Checked wrappers around the sqlite3_* calls: trace the statement, assert the return code,...
#define DT_DEBUG_SQLITE3_EXEC(a, b, c, d, e)
Definition sql_debug.h:129
#define DT_DEBUG_SQLITE3_BIND_BLOB(a, b, c, d, e)
Definition sql_debug.h:149
#define DT_DEBUG_SQLITE3_PREPARE_V2(a, b, c, d, e)
Definition sql_debug.h:137
#define DT_DEBUG_SQLITE3_BIND_TEXT(a, b, c, d, e)
Definition sql_debug.h:148
#define DT_DEBUG_SQLITE3_BIND_INT(a, b, c)
Definition sql_debug.h:145
#define DT_DEBUG_SQLITE3_BIND_DOUBLE(a, b, c)
Definition sql_debug.h:147
Identity of one preset, for callers listing rather than loading.
The facts about one image that decide whether a preset matches it.
One row of the Preferences preset tree, with its auto-apply conditions.
One row of data.presets, owned by the caller.