Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
style_repository.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2010-2011 Henrik Andersson.
4 Copyright (C) 2011-2016 Tobias Ellinghaus.
5 Copyright (C) 2012, 2019-2022 Pascal Obry.
6 Copyright (C) 2018 Edgardo Hoszowski.
7 Copyright (C) 2025-2026 Aurélien PIERRE.
8
9 darktable is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 darktable is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with darktable. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#include <stdio.h>
24#include <string.h>
25
27#include "database/database.h"
28#include "database/sql_debug.h"
29#include "system/dtpthread.h"
30#include "system/macros.h"
31#include "system/mem_alloc.h"
32
33// Two statements are hot enough to keep prepared: the style list (the styles panel rebuilds it on
34// every collection change) and the apply-items read (once per image in a batch style application).
35// Everything else here runs at most once per user action and is prepared on the spot.
38static dt_pthread_mutex_t _styles_stmt_mutex;
40
49
56static char *_num_set_predicate(GList *nums, const gboolean negate)
57{
58 if(IS_NULL_PTR(nums)) return NULL;
59
60 GString *s = g_string_new(negate ? "num NOT IN (" : "num IN (");
61 for(GList *l = nums; l; l = g_list_next(l))
62 {
63 if(l != nums) g_string_append_c(s, ',');
64 g_string_append_printf(s, "%d", GPOINTER_TO_INT(l->data));
65 }
66 g_string_append_c(s, ')');
67 return g_string_free(s, FALSE);
68}
69
70/* ---------------------------------------------------------------------------------------------
71 * data.styles
72 * ------------------------------------------------------------------------------------------ */
73
75{
76 if(IS_NULL_PTR(name)) return 0;
77
78 int id = 0;
81 "SELECT id FROM data.styles WHERE name=?1 ORDER BY id DESC LIMIT 1", -1, &stmt,
82 NULL);
85 {
86 id = sqlite3_column_int(stmt, 0);
87 }
89 return id;
90}
91
93{
94 if(styleid == 0) return NULL;
95
96 gchar *description = NULL;
98 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get_sqlite3_global(), "SELECT description FROM data.styles WHERE id=?1",
99 -1, &stmt, NULL);
105 return description;
106}
107
109{
110 if(IS_NULL_PTR(name)) return NULL;
111
112 char *iop_list_txt = NULL;
114 // clang-format off
116 "SELECT iop_list"
117 " FROM data.styles"
118 " WHERE name=?1",
119 -1, &stmt, NULL);
120 // clang-format on
123 // No row and a NULL column both report SQLITE_NULL here, which is why a style that does not
124 // exist correctly answers "carries no module order".
126 iop_list_txt = g_strdup((const char *)sqlite3_column_text(stmt, 0));
128 return iop_list_txt;
129}
130
131gboolean dt_style_repository_insert_header(const char *name, const char *description,
132 const char *iop_list_txt)
133{
134 if(IS_NULL_PTR(name)) return FALSE;
135
137 // clang-format off
140 "INSERT INTO data.styles (name, description, id, iop_list)"
141 " VALUES (?1, ?2, (SELECT COALESCE(MAX(id),0)+1 FROM data.styles), ?3)", -1, &stmt, NULL);
142 // clang-format on
145 if(iop_list_txt)
146 {
148 }
149 else
151
152 const gboolean ok = (sqlite3_step(stmt) == SQLITE_DONE);
154 return ok;
155}
156
157gboolean dt_style_repository_set_iop_list(const int32_t styleid, const char *iop_list_txt)
158{
159 if(styleid == 0) return FALSE;
160
162 if(iop_list_txt)
163 {
165 "UPDATE data.styles SET iop_list=?1 WHERE id=?2", -1, &stmt, NULL);
168 }
169 else
170 {
172 "UPDATE data.styles SET iop_list=NULL WHERE id=?1", -1, &stmt, NULL);
174 }
175
176 const gboolean ok = (sqlite3_step(stmt) == SQLITE_DONE);
178 return ok;
179}
180
181gboolean dt_style_repository_update_header(const int32_t styleid, const char *newname,
182 const char *description)
183{
184 if(styleid == 0) return FALSE;
185
188 "UPDATE data.styles SET name=?1, description=?2 WHERE id=?3", -1, &stmt, NULL);
192 const gboolean ok = (sqlite3_step(stmt) == SQLITE_DONE);
194 return ok;
195}
196
197gboolean dt_style_repository_delete(const int32_t styleid)
198{
199 if(styleid == 0) return FALSE;
200
201 gboolean ok = TRUE;
203
204 /* delete the style */
205 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get_sqlite3_global(), "DELETE FROM data.styles WHERE id = ?1", -1, &stmt,
206 NULL);
208 ok &= (sqlite3_step(stmt) == SQLITE_DONE);
210
211 /* delete style_items belonging to style */
212 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get_sqlite3_global(), "DELETE FROM data.style_items WHERE styleid = ?1",
213 -1, &stmt, NULL);
215 ok &= (sqlite3_step(stmt) == SQLITE_DONE);
217
218 return ok;
219}
220
222 void *user_data)
223{
224 if(IS_NULL_PTR(cb)) return;
225
226 char filterstring[512] = { 0 };
227 snprintf(filterstring, sizeof(filterstring), "%%%s%%", filter);
228
232 {
235 "SELECT name, description FROM data.styles WHERE name LIKE ?1 OR description LIKE ?1 ORDER BY name", -1,
237 }
242
243 while(sqlite3_step(stmt) == SQLITE_ROW)
244 cb(user_data, (const char *)sqlite3_column_text(stmt, 0), (const char *)sqlite3_column_text(stmt, 1));
245
247}
248
250 void *user_data)
251{
252 if(IS_NULL_PTR(name) || IS_NULL_PTR(cb)) return FALSE;
253
254 gboolean found = FALSE;
257 "SELECT name, description FROM data.styles WHERE name = ?1", -1, &stmt, NULL);
260 {
261 cb(user_data, (const char *)sqlite3_column_text(stmt, 0), (const char *)sqlite3_column_text(stmt, 1));
262 found = TRUE;
263 }
265 return found;
266}
267
268/* ---------------------------------------------------------------------------------------------
269 * data.style_items
270 * ------------------------------------------------------------------------------------------ */
271
273 dt_style_repository_item_cb cb, void *user_data)
274{
275 if(IS_NULL_PTR(cb)) return;
276
280 {
281 // clang-format off
283 "SELECT num, module, operation, op_params, enabled,"
284 " blendop_params, blendop_version, multi_priority, multi_name"
285 " FROM data.style_items WHERE styleid=?1 "
286 " ORDER BY num, operation, multi_priority",
288 // clang-format on
289 }
290
295
296 while(sqlite3_step(stmt) == SQLITE_ROW)
297 {
298 // selimg_num is 0 here, not -1: this is the one reader that used it as "no image matched"
299 // rather than "not asked", and it wrote 0.
301 (const char *)sqlite3_column_text(stmt, 2), sqlite3_column_int(stmt, 4),
304 sqlite3_column_int(stmt, 6), (const char *)sqlite3_column_text(stmt, 8), 0, 0.0);
305 }
306
309}
310
312 dt_style_repository_item_cb cb, void *user_data)
313{
314 if(IS_NULL_PTR(cb)) return;
315
317 // clang-format off
319 "SELECT num, module, operation, op_params, enabled,"
320 " blendop_params, blendop_version, multi_priority, multi_name"
321 " FROM data.style_items"
322 " WHERE styleid =?1",
323 -1, &stmt, NULL);
324 // clang-format on
326
327 while(sqlite3_step(stmt) == SQLITE_ROW)
328 {
330 (const char *)sqlite3_column_text(stmt, 2), sqlite3_column_int(stmt, 4),
333 sqlite3_column_int(stmt, 6), (const char *)sqlite3_column_text(stmt, 8), -1, 0.0);
334 }
336}
337
339 dt_style_repository_item_cb cb, void *user_data)
340{
341 if(IS_NULL_PTR(cb)) return;
342
344 // clang-format off
346 "SELECT num, multi_priority, module, operation, enabled, op_params, blendop_params, "
347 " multi_name, blendop_version"
348 " FROM data.style_items"
349 " WHERE styleid=?1 ORDER BY num DESC",
350 -1, &stmt, NULL);
351 // clang-format on
353
354 while(sqlite3_step(stmt) == SQLITE_ROW)
355 {
356 const int num = (sqlite3_column_type(stmt, 0) == SQLITE_NULL) ? -1 : sqlite3_column_int(stmt, 0);
357 // column 8 twice, once as int and once as double -- exactly what the original did
358 cb(user_data, num, sqlite3_column_int(stmt, 1), sqlite3_column_int(stmt, 2),
359 (const char *)sqlite3_column_text(stmt, 3), sqlite3_column_int(stmt, 4),
362 sqlite3_column_int(stmt, 8), (const char *)sqlite3_column_text(stmt, 7), -1,
364 }
366}
367
369 void *user_data)
370{
371 if(IS_NULL_PTR(cb)) return;
372
374 // clang-format off
376 "SELECT num, multi_priority, module, operation, enabled, 0, 0, multi_name"
377 " FROM data.style_items"
378 " WHERE styleid=?1 ORDER BY num DESC",
379 -1, &stmt, NULL);
380 // clang-format on
382
383 while(sqlite3_step(stmt) == SQLITE_ROW)
384 {
385 const int num = (sqlite3_column_type(stmt, 0) == SQLITE_NULL) ? -1 : sqlite3_column_int(stmt, 0);
386 // there is no column 8 in this query; the original read one anyway and got 0 for both the
387 // blendop_version and the iop_order. Kept, so the two paths still agree.
388 cb(user_data, num, sqlite3_column_int(stmt, 1), sqlite3_column_int(stmt, 2),
389 (const char *)sqlite3_column_text(stmt, 3), sqlite3_column_int(stmt, 4),
390 NULL, 0, NULL, 0,
391 sqlite3_column_int(stmt, 8), (const char *)sqlite3_column_text(stmt, 7), -1,
393 }
395}
396
397void dt_style_repository_foreach_item_against_image(const int32_t styleid, const int32_t imgid,
399 void *user_data)
400{
401 if(IS_NULL_PTR(cb)) return;
402
404 // get all items from the style
405 // UNION
406 // get all items from history, not in the style : select only the last operation, that is max(num)
407 // clang-format off
410 "SELECT num, multi_priority, module, operation, enabled,"
411 " (SELECT MAX(num)"
412 " FROM main.history"
413 " WHERE imgid=?2 "
414 " AND operation=data.style_items.operation"
415 " AND multi_priority=data.style_items.multi_priority),"
416 " 0, multi_name, blendop_version"
417 " FROM data.style_items"
418 " WHERE styleid=?1"
419 " UNION"
420 " SELECT -1,main.history.multi_priority,main.history.module,main.history.operation,main.history.enabled, "
421 " main.history.num,0,multi_name, blendop_version"
422 " FROM main.history"
423 " WHERE imgid=?2 AND main.history.enabled=1"
424 " AND (main.history.operation NOT IN (SELECT operation FROM data.style_items WHERE styleid=?1))"
425 " GROUP BY operation HAVING MAX(num) ORDER BY num DESC", -1, &stmt, NULL);
426 // clang-format on
429
430 while(sqlite3_step(stmt) == SQLITE_ROW)
431 {
432 const int num = (sqlite3_column_type(stmt, 0) == SQLITE_NULL) ? -1 : sqlite3_column_int(stmt, 0);
433 const int selimg_num = (sqlite3_column_type(stmt, 5) == SQLITE_NULL) ? -1 : sqlite3_column_int(stmt, 5);
434 cb(user_data, num, sqlite3_column_int(stmt, 1), sqlite3_column_int(stmt, 2),
435 (const char *)sqlite3_column_text(stmt, 3), sqlite3_column_int(stmt, 4),
436 NULL, 0, NULL, 0,
437 sqlite3_column_int(stmt, 8), (const char *)sqlite3_column_text(stmt, 7), selimg_num,
439 }
441}
442
443gboolean dt_style_repository_copy_items_from_history(const int32_t styleid, const int32_t imgid,
444 GList *nums)
445{
446 if(styleid == 0) return FALSE;
447
449 char *query = NULL;
451
452 if(predicate)
453 {
454 // clang-format off
456 "INSERT INTO data.style_items"
457 " (styleid,num,module,operation,op_params,enabled,blendop_params,"
458 " blendop_version,multi_priority,multi_name)"
459 " SELECT ?1, num,module,operation,op_params,enabled,blendop_params,blendop_version,"
460 " multi_priority,multi_name"
461 " FROM main.history"
462 " WHERE imgid=?2 AND %s",
463 predicate);
464 // clang-format on
466 }
467 else
468 // clang-format off
470 "INSERT INTO data.style_items"
471 " (styleid,num,module,operation,op_params,enabled,blendop_params,"
472 " blendop_version,multi_priority,multi_name)"
473 " SELECT ?1, num,module,operation,op_params,enabled,blendop_params,blendop_version,"
474 " multi_priority,multi_name"
475 " FROM main.history"
476 " WHERE imgid=?2",
477 -1, &stmt, NULL);
478 // clang-format on
479
482 const gboolean ok = (sqlite3_step(stmt) == SQLITE_DONE);
484
485 dt_free(query);
487 return ok;
488}
489
491 const int32_t source_styleid, GList *nums)
492{
493 if(dest_styleid == 0 || source_styleid == 0) return FALSE;
494
496 char *query = NULL;
498
499 if(predicate)
500 {
501 // clang-format off
503 "INSERT INTO data.style_items "
504 " (styleid,num,module,operation,op_params,enabled,blendop_params,blendop_version,"
505 " multi_priority,multi_name)"
506 " SELECT ?1, num,module,operation,op_params,enabled,blendop_params,blendop_version,"
507 " multi_priority,multi_name"
508 " FROM data.style_items"
509 " WHERE styleid=?2 AND %s",
510 predicate);
511 // clang-format on
513 }
514 else
515 // clang-format off
517 "INSERT INTO data.style_items "
518 " (styleid,num,module,operation,op_params,enabled,blendop_params,"
519 " blendop_version,multi_priority,multi_name)"
520 " SELECT ?1, num,module,operation,op_params,enabled,blendop_params,"
521 " blendop_version,multi_priority,multi_name"
522 " FROM data.style_items"
523 " WHERE styleid=?2",
524 -1, &stmt, NULL);
525 // clang-format on
526
529 const gboolean ok = (sqlite3_step(stmt) == SQLITE_DONE);
531
532 dt_free(query);
534 return ok;
535}
536
538{
539 if(styleid == 0) return FALSE;
540
542 if(IS_NULL_PTR(predicate)) return FALSE;
543
544 char *query = g_strdup_printf("DELETE FROM data.style_items WHERE styleid=?1 AND %s", predicate);
548 const gboolean ok = (sqlite3_step(stmt) == SQLITE_DONE);
550
551 dt_free(query);
553 return ok;
554}
555
557 const int32_t imgid, const int history_num)
558{
559 if(styleid == 0) return;
560
561 // Every column is copied from one history row, so the SET list is generated rather than typed
562 // out twice. The original built the same list the same way.
563 static const char *const fields[] = { "op_params", "module", "enabled", "blendop_params",
564 "blendop_version", "multi_priority", "multi_name", NULL };
565
566 GString *q = g_string_new("UPDATE data.style_items SET ");
567 for(int k = 0; fields[k]; k++)
568 {
569 if(k != 0) g_string_append_c(q, ',');
570 g_string_append_printf(q, "%s=(SELECT %s FROM main.history WHERE imgid=%d AND num=%d)", fields[k],
571 fields[k], imgid, history_num);
572 }
573 g_string_append_printf(q, " WHERE styleid=%d AND data.style_items.num=%d", styleid, item_num);
574
575 char *query = g_string_free(q, FALSE);
577 dt_free(query);
578}
579
580void dt_style_repository_append_item_from_history(const int32_t styleid, const int32_t imgid,
581 const int history_num)
582{
583 if(styleid == 0) return;
584
585 // clang-format off
586 char *query = g_strdup_printf(
587 "INSERT INTO data.style_items "
588 " (styleid, num, module, operation, op_params, enabled, blendop_params,"
589 " blendop_version, multi_priority, multi_name)"
590 " SELECT %d,"
591 " (SELECT num+1 "
592 " FROM data.style_items"
593 " WHERE styleid=%d"
594 " ORDER BY num DESC LIMIT 1), "
595 " module, operation, op_params, enabled, blendop_params, blendop_version,"
596 " multi_priority, multi_name"
597 " FROM main.history"
598 " WHERE imgid=%d AND num=%d",
599 styleid, styleid, imgid, history_num);
600 // clang-format on
601
603 dt_free(query);
604}
605
606gboolean dt_style_repository_insert_item(const int32_t styleid, const int num,
607 const int module_version, const char *operation,
608 const void *params, const int32_t params_size,
609 const int enabled, const void *blendop_params,
610 const int32_t blendop_params_size,
611 const int blendop_version, const int multi_priority,
612 const char *multi_name)
613{
614 if(styleid == 0) return FALSE;
615
617 // clang-format off
619 "INSERT INTO data.style_items "
620 " (styleid, num, module, operation, op_params, enabled, blendop_params,"
621 " blendop_version, multi_priority, multi_name)"
622 " VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10)",
623 -1, &stmt, NULL);
624 // clang-format on
627 DT_DEBUG_SQLITE3_BIND_INT(stmt, 3, module_version);
630 DT_DEBUG_SQLITE3_BIND_INT(stmt, 6, enabled);
631 DT_DEBUG_SQLITE3_BIND_BLOB(stmt, 7, blendop_params, blendop_params_size, SQLITE_TRANSIENT);
632 DT_DEBUG_SQLITE3_BIND_INT(stmt, 8, blendop_version);
633 DT_DEBUG_SQLITE3_BIND_INT(stmt, 9, multi_priority);
635
636 const gboolean ok = (sqlite3_step(stmt) == SQLITE_DONE);
638 return ok;
639}
640
642{
643 if(styleid == 0) return FALSE;
644
646 GList *list = NULL;
647 struct _data
648 {
649 int rowid;
650 int mi;
651 };
652 char last_operation[128] = { 0 };
653 int last_mi = 0;
654
655 /* let's clean-up the style multi-instance. What we want to do is have a unique multi_priority value for
656 each iop.
657 Furthermore this value must start to 0 and increment one by one for each multi-instance of the same
658 module. On
659 SQLite there is no notion of ROW_NUMBER, so we use rather resource consuming SQL statement, but as a
660 style has
661 never a huge number of items that's not a real issue. */
662
663 /* 1. read all data for the style and record multi_instance value. */
664
667 "SELECT rowid,operation FROM data.style_items WHERE styleid=?1 ORDER BY operation, multi_priority ASC", -1,
668 &stmt, NULL);
670
671 while(sqlite3_step(stmt) == SQLITE_ROW)
672 {
673 struct _data *d = malloc(sizeof(struct _data));
674 const char *operation = (const char *)sqlite3_column_text(stmt, 1);
675
676 if(strncmp(last_operation, operation, 128) != 0)
677 {
678 last_mi = 0;
679 g_strlcpy(last_operation, operation, sizeof(last_operation));
680 }
681 else
682 last_mi++;
683
684 d->rowid = sqlite3_column_int(stmt, 0);
685 d->mi = last_mi;
686 list = g_list_prepend(list, d);
687 }
689 list = g_list_reverse(list); // list was built in reverse order, so un-reverse it
690
691 /* 2. now update all multi_instance values previously recorded */
692
693 gboolean ok = TRUE;
695 {
696 struct _data *d = (struct _data *)list_iter->data;
697
699 "UPDATE data.style_items SET multi_priority=?1 WHERE rowid=?2", -1, &stmt, NULL);
701 DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, d->rowid);
702 ok &= (sqlite3_step(stmt) == SQLITE_DONE);
704 }
705
706 /* 3. free the list we built in step 1 */
708
709 return ok;
710}
711
728
729// clang-format off
730// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
731// vim: shiftwidth=2 expandtab tabstop=2 cindent
732// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
733// clang-format on
const char ** description(struct dt_iop_module_t *self)
Definition ashift.c:166
#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
sqlite3 * dt_database_get_sqlite3_global(void)
Definition database.c:3753
static int dt_pthread_mutex_unlock(dt_pthread_mutex_t *mutex) RELEASE(mutex) NO_THREAD_SAFETY_ANALYSIS
Definition dtpthread.h:385
static int dt_pthread_mutex_init(dt_pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
Definition dtpthread.h:370
static int dt_pthread_mutex_lock(dt_pthread_mutex_t *mutex) ACQUIRE(mutex) NO_THREAD_SAFETY_ANALYSIS
Definition dtpthread.h:375
float *const restrict const size_t k
#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:65
static void dt_free_gpointer(gpointer ptr)
Definition mem_alloc.h:104
#define dt_free(ptr)
Definition mem_alloc.h:97
const char * name
Definition pdf.h:90
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
static dt_pthread_mutex_t _styles_stmt_mutex
gboolean dt_style_repository_delete_items_except(const int32_t styleid, GList *nums)
gboolean dt_style_repository_copy_items_from_history(const int32_t styleid, const int32_t imgid, GList *nums)
void dt_style_repository_foreach_style(const char *filter, dt_style_repository_style_cb cb, void *user_data)
gboolean dt_style_repository_get_style(const char *name, dt_style_repository_style_cb cb, void *user_data)
int32_t dt_style_repository_get_id_by_name(const char *name)
char * dt_style_repository_get_iop_list(const char *name)
void dt_style_repository_foreach_item_with_params(const int32_t styleid, dt_style_repository_item_cb cb, void *user_data)
gboolean dt_style_repository_normalize_multi_priority(const int32_t styleid)
static gsize _styles_stmt_mutex_inited
void dt_style_repository_foreach_item(const int32_t styleid, dt_style_repository_item_cb cb, void *user_data)
gboolean dt_style_repository_insert_item(const int32_t styleid, const int num, const int module_version, const char *operation, const void *params, const int32_t params_size, const int enabled, const void *blendop_params, const int32_t blendop_params_size, const int blendop_version, const int multi_priority, const char *multi_name)
gboolean dt_style_repository_set_iop_list(const int32_t styleid, const char *iop_list_txt)
void dt_style_repository_cleanup(void)
void dt_style_repository_foreach_item_against_image(const int32_t styleid, const int32_t imgid, dt_style_repository_item_cb cb, void *user_data)
static sqlite3_stmt * _styles_apply_items_stmt
void dt_style_repository_foreach_apply_item(const int32_t styleid, dt_style_repository_item_cb cb, void *user_data)
gboolean dt_style_repository_update_header(const int32_t styleid, const char *newname, const char *description)
static void _styles_stmt_mutex_ensure(void)
gboolean dt_style_repository_insert_header(const char *name, const char *description, const char *iop_list_txt)
void dt_style_repository_append_item_from_history(const int32_t styleid, const int32_t imgid, const int history_num)
static char * _num_set_predicate(GList *nums, const gboolean negate)
char * dt_style_repository_get_description(const int32_t styleid)
gboolean dt_style_repository_delete(const int32_t styleid)
void dt_style_repository_foreach_item_for_export(const int32_t styleid, dt_style_repository_item_cb cb, void *user_data)
static sqlite3_stmt * _styles_get_list_stmt
void dt_style_repository_update_item_from_history(const int32_t styleid, const int item_num, const int32_t imgid, const int history_num)
gboolean dt_style_repository_copy_items_from_style(const int32_t dest_styleid, const int32_t source_styleid, GList *nums)
void(* dt_style_repository_style_cb)(void *user_data, const char *name, const char *description)
void(* dt_style_repository_item_cb)(void *user_data, const int num, const int multi_priority, const int module_version, const char *operation, const int enabled, const void *params, const int32_t params_size, const void *blendop_params, const int32_t blendop_params_size, const int blendop_version, const char *multi_name, const int selimg_num, const double iop_order)