Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
styles_dialog.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) 2010-2012 johannes hanika.
5 Copyright (C) 2011 Robert Bieber.
6 Copyright (C) 2012 Frédéric Grollier.
7 Copyright (C) 2012-2013, 2019-2022 Pascal Obry.
8 Copyright (C) 2012 Richard Wonka.
9 Copyright (C) 2013 Jérémy Rosen.
10 Copyright (C) 2013-2016 Tobias Ellinghaus.
11 Copyright (C) 2014, 2016 Roman Lebedev.
12 Copyright (C) 2017 luzpaz.
13 Copyright (C) 2017 parafin.
14 Copyright (C) 2019, 2022-2023, 2025 Aurélien PIERRE.
15 Copyright (C) 2019 Sam Smith.
16 Copyright (C) 2020 darkelectron.
17 Copyright (C) 2021 Chris Elston.
18 Copyright (C) 2021 Hubert Kowalski.
19 Copyright (C) 2021 Ralf Brown.
20 Copyright (C) 2022 Martin Bařinka.
21
22 darktable is free software: you can redistribute it and/or modify
23 it under the terms of the GNU General Public License as published by
24 the Free Software Foundation, either version 3 of the License, or
25 (at your option) any later version.
26
27 darktable is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU General Public License for more details.
31
32 You should have received a copy of the GNU General Public License
33 along with darktable. If not, see <http://www.gnu.org/licenses/>.
34*/
35#ifdef HAVE_CONFIG_H
36#include "config.h"
37#endif
38#include "common/darktable.h"
39#include "common/debug.h"
40#include "common/history.h"
41#include "common/styles.h"
42#include "control/control.h"
43#include "develop/imageop.h"
44#include "gui/gtk.h"
45#include "gui/draw.h"
46#include "gui/styles.h"
47#ifdef GDK_WINDOWING_QUARTZ
48#include "osx/osx.h"
49#endif
50
51/* creates a styles dialog, if edit equals true id=styleid else id=imgid */
52static void _gui_styles_dialog_run(gboolean edit, const char *name, int32_t imgid);
53
55{
56 gboolean edit;
57 int32_t imgid;
58 gchar *nameorig;
60 GtkTreeView *items;
61 GtkTreeView *items_new;
63
64
75
77{
78 int32_t imgid = UNKNOWN_IMAGE;
79 sqlite3_stmt *stmt;
80 DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "SELECT imgid FROM main.selected_images", -1, &stmt,
81 NULL);
82 while(sqlite3_step(stmt) == SQLITE_ROW)
83 {
84 if(imgid == UNKNOWN_IMAGE)
85 imgid = sqlite3_column_int(stmt, 0);
86 else
87 {
88 imgid = UNKNOWN_IMAGE;
89 break;
90 }
91 }
92 sqlite3_finalize(stmt);
93 return imgid;
94}
95
97{
98 /* first item is the copy-module */
99 GtkTreeIter iter;
100 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(d->items));
101
102 gboolean active = FALSE;
103 gint num = 0;
104 if(gtk_tree_model_get_iter_first(model, &iter))
105 gtk_tree_model_get(model, &iter, DT_STYLE_ITEMS_COL_ENABLED, &active, DT_STYLE_ITEMS_COL_NUM, &num, -1);
106 return active && (num == -1);
107}
108
110{
111 /* first item is the copy-module */
112 GtkTreeIter iter;
113 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(d->items));
114
115 gboolean active = FALSE;
116 gint num = 0;
117 if(gtk_tree_model_get_iter_first(model, &iter))
118 gtk_tree_model_get(model, &iter, DT_STYLE_ITEMS_COL_UPDATE, &active, DT_STYLE_ITEMS_COL_NUM, &num, -1);
119 return active && (num == -1);
120}
121
122void _gui_styles_get_active_items(dt_gui_styles_dialog_t *sd, GList **enabled, GList **update)
123{
124 /* run through all items and add active ones to result */
125 GtkTreeIter iter;
126 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(sd->items));
127 gint num = 0, update_num = 0;
128 gboolean active, uactive;
129
130 if(gtk_tree_model_get_iter_first(model, &iter))
131 {
132 do
133 {
134 gtk_tree_model_get(model, &iter, DT_STYLE_ITEMS_COL_ENABLED, &active,
138 -1);
139 if((active || uactive) && num >= 0)
140 {
141 *enabled = g_list_append(*enabled, GINT_TO_POINTER(num));
142 if(!IS_NULL_PTR(update))
143 {
144 if(uactive)
145 *update = g_list_append(*update, GINT_TO_POINTER(update_num));
146 else
147 *update = g_list_append(*update, GINT_TO_POINTER(-1));
148 }
149 }
150 } while(gtk_tree_model_iter_next(model, &iter));
151 }
152
153 /* check for new items to be included */
154 model = gtk_tree_view_get_model(GTK_TREE_VIEW(sd->items_new));
155 if(gtk_tree_model_get_iter_first(model, &iter))
156 {
157 do
158 {
159 gtk_tree_model_get(model, &iter,
163 -1);
164 if(active)
165 {
166 if(update_num == -1) // item from style
167 {
168 *enabled = g_list_append(*enabled, GINT_TO_POINTER(num));
169 *update = g_list_append(*update, GINT_TO_POINTER(-1));
170 }
171 else // item from image
172 {
173 *update = g_list_append(*update, GINT_TO_POINTER(update_num));
174 *enabled = g_list_append(*enabled, GINT_TO_POINTER(-1));
175 }
176 }
177 } while(gtk_tree_model_iter_next(model, &iter));
178 }
179}
180
182{
183 /* run through all items and set active status */
184 GtkTreeView *items = (d->duplicate) ? d->items_new : d->items;
185 GtkTreeIter iter;
186 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(items));
187 if(gtk_tree_model_get_iter_first(model, &iter))
188 {
189 do
190 {
191 gtk_list_store_set(GTK_LIST_STORE(model), &iter, DT_STYLE_ITEMS_COL_ENABLED, active, -1);
192 } while(gtk_tree_model_iter_next(model, &iter));
193 }
194}
195
196static void _gui_styles_new_style_response(GtkDialog *dialog, gint response_id, dt_gui_styles_dialog_t *g)
197{
198 if(response_id == GTK_RESPONSE_YES)
199 {
201 return;
202 }
203 else if(response_id == GTK_RESPONSE_NONE)
204 {
206 return;
207 }
208 else if(response_id == GTK_RESPONSE_ACCEPT)
209 {
210 /* get the filtered list from dialog */
211 GList *result = NULL;
212 _gui_styles_get_active_items(g, &result, NULL);
213
214 /* create the style from imageid */
215 const gchar *name = gtk_entry_get_text(GTK_ENTRY(g->name));
216 if(name && *name)
217 {
218
219 /* show prompt dialog when style already exists */
220 if(name && (dt_styles_exists(name)) != 0)
221 {
223 GtkWidget *dlg_overwrite = gtk_message_dialog_new(
224 GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO,
225 _("style `%s' already exists.\ndo you want to overwrite?"), name);
226#ifdef GDK_WINDOWING_QUARTZ
227 dt_osx_disallow_fullscreen(dlg_overwrite);
228#endif
229
230 gtk_window_set_title(GTK_WINDOW(dlg_overwrite), _("overwrite style?"));
231
232 const gint dlg_ret = gtk_dialog_run(GTK_DIALOG(dlg_overwrite));
233 gtk_widget_destroy(dlg_overwrite);
234
235 /* on button yes delete style name for overwriting */
236 if(dlg_ret == GTK_RESPONSE_YES)
237 {
239 }
240 else
241 {
242 /* on RESPONSE_NO and escape key return to dialog */
243 return;
244 }
245 }
246
247 if(dt_styles_create_from_image(name, gtk_entry_get_text(GTK_ENTRY(g->description)),
248 g->imgid, result, _gui_styles_is_copy_module_order_set(g)))
249 {
250 dt_control_log(_("style named '%s' successfully created"), name);
251 };
252 }
253 else
254 {
255 /* show dialog if name is missing from entry */
257 GtkWidget *dlg_changename
258 = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING,
259 GTK_BUTTONS_OK, _("please give style a name"));
260#ifdef GDK_WINDOWING_QUARTZ
261 dt_osx_disallow_fullscreen(dlg_changename);
262#endif
263 gtk_window_set_title(GTK_WINDOW(dlg_changename), _("unnamed style"));
264 gtk_dialog_run(GTK_DIALOG(dlg_changename));
265 gtk_widget_destroy(dlg_changename);
266 return;
267 }
268 }
269 gtk_widget_destroy(GTK_WIDGET(dialog));
270 dt_free(g->nameorig);
271 dt_free(g);
272}
273
274static void _gui_styles_edit_style_response(GtkDialog *dialog, gint response_id, dt_gui_styles_dialog_t *g)
275{
276 if(response_id == GTK_RESPONSE_YES)
277 {
279 return;
280 }
281 else if(response_id == GTK_RESPONSE_NONE)
282 {
284 return;
285 }
286 else if(response_id == GTK_RESPONSE_ACCEPT)
287 {
288 /* get the filtered list from dialog */
289 GList *result = NULL, *update = NULL;
290
291 _gui_styles_get_active_items(g, &result, &update);
292
293 const gchar *name = gtk_entry_get_text(GTK_ENTRY(g->name));
294 if(name && *name)
295 {
296 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g->duplicate)))
297 {
298 dt_styles_create_from_style(g->nameorig, name, gtk_entry_get_text(GTK_ENTRY(g->description)),
299 result, g->imgid, update,
302 }
303 else
304 {
305 dt_styles_update(g->nameorig, name, gtk_entry_get_text(GTK_ENTRY(g->description)),
306 result, g->imgid, update,
309 }
310 dt_control_log(_("style %s was successfully saved"), name);
311 }
312 else
313 {
314 /* show dialog if name is missing from entry */
316 GtkWidget *dlg_changename
317 = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING,
318 GTK_BUTTONS_OK, _("please give style a name"));
319#ifdef GDK_WINDOWING_QUARTZ
320 dt_osx_disallow_fullscreen(dlg_changename);
321#endif
322 gtk_window_set_title(GTK_WINDOW(dlg_changename), _("unnamed style"));
323 gtk_dialog_run(GTK_DIALOG(dlg_changename));
324 gtk_widget_destroy(dlg_changename);
325 return;
326 }
327 }
328 gtk_widget_destroy(GTK_WIDGET(dialog));
329 dt_free(g->nameorig);
330 dt_free(g);
331}
332
333static void _gui_styles_item_toggled(GtkCellRendererToggle *cell, gchar *path_str, gpointer data)
334{
336
337 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(sd->items));
338 GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
339 GtkTreeIter iter;
340 gboolean toggle_item;
341 gint num, update_num;
342
343 gtk_tree_model_get_iter(model, &iter, path);
344 gtk_tree_model_get(model, &iter,
345 DT_STYLE_ITEMS_COL_ENABLED, &toggle_item,
348 -1);
349
350 toggle_item = (toggle_item == TRUE) ? FALSE : TRUE;
351
352 if(update_num != -1 && toggle_item) // include so not updated
353 gtk_list_store_set(GTK_LIST_STORE(model), &iter, DT_STYLE_ITEMS_COL_UPDATE, FALSE, -1);
354
355 gtk_list_store_set(GTK_LIST_STORE(model), &iter, DT_STYLE_ITEMS_COL_ENABLED, toggle_item, -1);
356 gtk_tree_path_free(path);
357}
358
359static void _gui_styles_item_new_toggled(GtkCellRendererToggle *cell, gchar *path_str, gpointer data)
360{
362
363 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(sd->items_new));
364 GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
365 GtkTreeIter iter;
366 gboolean toggle_item;
367
368 gtk_tree_model_get_iter(model, &iter, path);
369 gtk_tree_model_get(model, &iter, DT_STYLE_ITEMS_COL_ENABLED, &toggle_item, -1);
370
371 toggle_item = (toggle_item == TRUE) ? FALSE : TRUE;
372
373 gtk_list_store_set(GTK_LIST_STORE(model), &iter, DT_STYLE_ITEMS_COL_ENABLED, toggle_item, -1);
374 gtk_tree_path_free(path);
375}
376
377static void _gui_styles_update_toggled(GtkCellRendererToggle *cell, gchar *path_str, gpointer data)
378{
380
381 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(sd->items));
382 GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
383 GtkTreeIter iter;
384 gboolean toggle_item;
385
386 gtk_tree_model_get_iter(model, &iter, path);
387 gtk_tree_model_get(model, &iter, DT_STYLE_ITEMS_COL_UPDATE, &toggle_item, -1);
388
389 toggle_item = (toggle_item == TRUE) ? FALSE : TRUE;
390
391 gtk_list_store_set(GTK_LIST_STORE(model), &iter, DT_STYLE_ITEMS_COL_ENABLED, !toggle_item, -1);
392 gtk_list_store_set(GTK_LIST_STORE(model), &iter, DT_STYLE_ITEMS_COL_UPDATE, toggle_item, -1);
393 gtk_tree_path_free(path);
394}
395
396void dt_gui_styles_dialog_new(int32_t imgid)
397{
398 _gui_styles_dialog_run(FALSE, NULL, imgid);
399}
400
405
406static gint _g_list_find_module_by_name(gconstpointer a, gconstpointer b)
407{
408 return strncmp(((dt_iop_module_t *)a)->op, b, strlen(((dt_iop_module_t *)a)->op));
409}
410
411static void _gui_styles_dialog_run(gboolean edit, const char *name, int32_t imgid)
412{
413 char title[512];
414
415 /* check if style exists */
416 if(name && (dt_styles_exists(name)) == 0) return;
417
418 /* initialize the dialog */
420 sd->nameorig = g_strdup(name);
421 sd->imgid = imgid;
422
423 if(edit)
424 {
425 snprintf(title, sizeof(title), "%s \"%s\"", _("edit style"), name);
426 sd->duplicate = gtk_check_button_new_with_label(_("duplicate style"));
427 gtk_widget_set_tooltip_text(sd->duplicate, _("creates a duplicate of the style before applying changes"));
428 }
429 else
430 {
431 g_strlcpy(title, _("create new style"), sizeof(title));
432 sd->duplicate = NULL;
433 }
435 GtkDialog *dialog = GTK_DIALOG(
436 gtk_dialog_new_with_buttons(title, GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT,
437 _("_cancel"), GTK_RESPONSE_REJECT,
438 _("select _all"), GTK_RESPONSE_YES,
439 _("select _none"), GTK_RESPONSE_NONE,
440 _("_save"), GTK_RESPONSE_ACCEPT, NULL));
441#ifdef GDK_WINDOWING_QUARTZ
442 dt_osx_disallow_fullscreen(GTK_WIDGET(dialog));
443#endif
444
445 GtkContainer *content_area = GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog)));
446
447 // label box
448 GtkBox *box = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING));
449
450 GtkWidget *scroll = gtk_scrolled_window_new(NULL, NULL);
451 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
452 gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(scroll), DT_PIXEL_APPLY_DPI(450));
453// only available in 3.22, and not making the expected job anyway
454// gtk_scrolled_window_set_max_content_height(GTK_SCROLLED_WINDOW(scroll), DT_PIXEL_APPLY_DPI(700));
455// gtk_scrolled_window_set_propagate_natural_height(GTK_SCROLLED_WINDOW(scroll), TRUE);
456
457 // box in scrollwindow containing the two possible trees
458 GtkBox *sbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING));
459 dt_gui_add_class(GTK_WIDGET(sbox), "dt_recessed_scroll");
460
461 gtk_box_pack_start(GTK_BOX(content_area), GTK_WIDGET(box), TRUE, TRUE, 0);
462 gtk_container_add(GTK_CONTAINER(scroll), GTK_WIDGET(sbox));
463
464 sd->name = gtk_entry_new();
466 gtk_entry_set_placeholder_text(GTK_ENTRY(sd->name), _("name"));
467 gtk_widget_set_tooltip_text(sd->name, _("enter a name for the new style"));
468
469 sd->description = gtk_entry_new();
471 gtk_entry_set_placeholder_text(GTK_ENTRY(sd->description), _("description"));
472 gtk_widget_set_tooltip_text(sd->description,
473 _("enter a description for the new style, this description is searchable"));
474
475 /*set values*/
476 if(edit && name)
477 {
478 /* name */
479 gtk_entry_set_text(GTK_ENTRY(sd->name), name);
480 /* description */
481 gchar *desc = dt_styles_get_description(name);
482 if(desc)
483 {
484 gtk_entry_set_text(GTK_ENTRY(sd->description), desc);
485 dt_free(desc);
486 }
487 }
488
489 gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(sd->name), FALSE, TRUE, 0);
490 gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(sd->description), FALSE, TRUE, 0);
491 gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(scroll), TRUE, TRUE, 0);
492
493 /* create the list of items */
494 sd->items = GTK_TREE_VIEW(gtk_tree_view_new());
495 GtkListStore *liststore = gtk_list_store_new(DT_STYLE_ITEMS_NUM_COLS, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
496 GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT);
497
498 sd->items_new = GTK_TREE_VIEW(gtk_tree_view_new());
499 GtkListStore *liststore_new = gtk_list_store_new(DT_STYLE_ITEMS_NUM_COLS, G_TYPE_BOOLEAN, G_TYPE_STRING,
500 GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT);
501
502 /* enabled */
503 GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new();
504 gtk_cell_renderer_toggle_set_activatable(GTK_CELL_RENDERER_TOGGLE(renderer), TRUE);
505 g_object_set_data(G_OBJECT(renderer), "column", (gint *)DT_STYLE_ITEMS_COL_ENABLED);
506 g_signal_connect(renderer, "toggled", G_CALLBACK(_gui_styles_item_toggled), sd);
507
508 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(sd->items), -1, _("include"), renderer, "active",
510
511 if(edit)
512 {
513 renderer = gtk_cell_renderer_toggle_new();
514 gtk_cell_renderer_toggle_set_activatable(GTK_CELL_RENDERER_TOGGLE(renderer), TRUE);
515 g_object_set_data(G_OBJECT(renderer), "column", (gint *)DT_STYLE_ITEMS_COL_ENABLED);
516 g_signal_connect(renderer, "toggled", G_CALLBACK(_gui_styles_item_new_toggled), sd);
517 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(sd->items_new), -1, _("include"), renderer,
518 "active", DT_STYLE_ITEMS_COL_ENABLED, NULL);
519 }
520
521 /* update */
522 if(edit && imgid != UNKNOWN_IMAGE)
523 {
524 renderer = gtk_cell_renderer_toggle_new();
525 gtk_cell_renderer_toggle_set_activatable(GTK_CELL_RENDERER_TOGGLE(renderer), TRUE);
526 g_object_set_data(G_OBJECT(renderer), "column", (gint *)DT_STYLE_ITEMS_COL_UPDATE);
527 g_signal_connect(renderer, "toggled", G_CALLBACK(_gui_styles_update_toggled), sd);
528
529 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(sd->items), -1, _("update"), renderer, "active",
531 }
532
533 /* active */
534 renderer = gtk_cell_renderer_pixbuf_new();
535 GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes("", renderer, "pixbuf",
537 gtk_tree_view_append_column(GTK_TREE_VIEW(sd->items), column);
538 gtk_tree_view_column_set_alignment(column, 0.5);
539 gtk_tree_view_column_set_clickable(column, FALSE);
540 gtk_tree_view_column_set_min_width(column, DT_PIXEL_APPLY_DPI(30));
541
542 if(edit)
543 {
544 column = gtk_tree_view_column_new_with_attributes("", renderer, "pixbuf",
546 gtk_tree_view_column_set_alignment(column, 0.5);
547 gtk_tree_view_column_set_clickable(column, FALSE);
548 gtk_tree_view_column_set_min_width(column, DT_PIXEL_APPLY_DPI(30));
549 gtk_tree_view_append_column(GTK_TREE_VIEW(sd->items_new), column);
550 }
551
552 /* name */
553 renderer = gtk_cell_renderer_text_new();
554 g_object_set_data(G_OBJECT(renderer), "column", (gint *)DT_STYLE_ITEMS_COL_NAME);
555 g_object_set(renderer, "xalign", 0.0, (gchar *)0);
556 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(sd->items), -1, _("item"), renderer, "text",
558
559 if(edit)
560 {
561 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(sd->items_new), -1, _("item"), renderer, "text",
563 }
564
565 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(sd->items)), GTK_SELECTION_SINGLE);
566 gtk_tree_view_set_model(GTK_TREE_VIEW(sd->items), GTK_TREE_MODEL(liststore));
567
568 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(sd->items_new)), GTK_SELECTION_SINGLE);
569 gtk_tree_view_set_model(GTK_TREE_VIEW(sd->items_new), GTK_TREE_MODEL(liststore_new));
570
571 gboolean has_new_item = FALSE, has_item = FALSE;
572
573 GdkPixbuf *is_active_pb =
574 dt_draw_paint_to_pixbuf(GTK_WIDGET(dialog), 10, 0, dtgtk_cairo_paint_switch);
575 GdkPixbuf *is_inactive_pb =
577
578 /* fill list with history items */
579 GtkTreeIter iter;
580 if(edit)
581 {
582 gtk_list_store_append(GTK_LIST_STORE(liststore), &iter);
583 gtk_list_store_set(GTK_LIST_STORE(liststore), &iter,
585 DT_STYLE_ITEMS_COL_ISACTIVE, is_active_pb,
586 DT_STYLE_ITEMS_COL_NAME, _("module order"),
588 -1);
589 /* get history items for named style and populate the items list */
590 GList *items = dt_styles_get_item_list(name, FALSE, imgid);
591 if(items)
592 {
593 for(const GList *items_iter = items; items_iter; items_iter = g_list_next(items_iter))
594 {
595 dt_style_item_t *item = (dt_style_item_t *)items_iter->data;
596
597 if(item->num != -1 && item->selimg_num != -1) // defined in style and image
598 {
599 gtk_list_store_append(GTK_LIST_STORE(liststore), &iter);
600 gtk_list_store_set(GTK_LIST_STORE(liststore), &iter,
603 DT_STYLE_ITEMS_COL_ISACTIVE, item->enabled ? is_active_pb : is_inactive_pb,
607 -1);
608 has_item = TRUE;
609 }
610 else if(item->num != -1
611 || item->selimg_num != -1) // defined in one or the other, let a way to select it or not
612 {
613 gtk_list_store_append(GTK_LIST_STORE(liststore_new), &iter);
614 gtk_list_store_set(GTK_LIST_STORE(liststore_new), &iter,
615 DT_STYLE_ITEMS_COL_ENABLED, item->num != -1 ? TRUE : FALSE,
616 DT_STYLE_ITEMS_COL_ISACTIVE, item->enabled ? is_active_pb : is_inactive_pb,
620 -1);
621 has_new_item = TRUE;
622 }
623 }
624 g_list_free_full(items, dt_style_item_free);
625 items = NULL;
626 }
627 }
628 else
629 {
631 char *label = g_strdup_printf("%s (%s)", _("module order"), dt_iop_order_string(order));
632 gtk_list_store_append(GTK_LIST_STORE(liststore), &iter);
633 gtk_list_store_set(GTK_LIST_STORE(liststore), &iter,
635 DT_STYLE_ITEMS_COL_ISACTIVE, is_active_pb,
638 -1);
639 dt_free(label);
640
641 GList *items = dt_history_get_items(imgid, FALSE);
642 if(items)
643 {
644 for(const GList *items_iter = items; items_iter; items_iter = g_list_next(items_iter))
645 {
646 dt_history_item_t *item = (dt_history_item_t *)items_iter->data;
647
648 /* lookup history item module */
649 gboolean enabled = TRUE;
650 dt_iop_module_t *module = NULL;
651 GList *modules = darktable.develop->iop;
652 if(modules)
653 {
654 GList *result = g_list_find_custom(
655 modules, item->op, _g_list_find_module_by_name); // (dt_iop_module_t *)(modules->data);
656 if(result)
657 {
658 module = (dt_iop_module_t *)(result->data);
659 enabled = (module->flags() & IOP_FLAGS_INCLUDE_IN_STYLES) ? TRUE : FALSE;
660 }
661 }
662
663 gtk_list_store_append(GTK_LIST_STORE(liststore), &iter);
664 gtk_list_store_set(GTK_LIST_STORE(liststore), &iter,
666 DT_STYLE_ITEMS_COL_ISACTIVE, item->enabled ? is_active_pb : is_inactive_pb,
669 -1);
670
671 has_item = TRUE;
672 }
673 g_list_free_full(items, dt_history_item_free);
674 items = NULL;
675 }
676 else
677 {
678 dt_control_log(_("can't create style out of unaltered image"));
679 return;
680 }
681 }
682
683 if(has_item) gtk_box_pack_start(GTK_BOX(sbox), GTK_WIDGET(sd->items), TRUE, TRUE, 0);
684
685 if(has_new_item) gtk_box_pack_start(GTK_BOX(sbox), GTK_WIDGET(sd->items_new), TRUE, TRUE, 0);
686
687 if(edit) gtk_box_pack_start(GTK_BOX(content_area), GTK_WIDGET(sd->duplicate), FALSE, TRUE, 0);
688
689 g_object_unref(liststore);
690 g_object_unref(liststore_new);
691
692 /* run dialog */
693 if(edit)
694 g_signal_connect(dialog, "response", G_CALLBACK(_gui_styles_edit_style_response), sd);
695 else
696 g_signal_connect(dialog, "response", G_CALLBACK(_gui_styles_new_style_response), sd);
697
698 gtk_widget_show_all(GTK_WIDGET(dialog));
699 gtk_dialog_run(GTK_DIALOG(dialog));
700
701 g_object_unref(is_active_pb);
702 g_object_unref(is_inactive_pb);
703}
704// clang-format off
705// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
706// vim: shiftwidth=2 expandtab tabstop=2 cindent
707// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
708// clang-format on
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
GList * dt_history_get_items(const int32_t imgid, gboolean enabled)
void dt_history_item_free(gpointer data)
char * name
void dt_control_log(const char *msg,...)
Definition control.c:761
darktable_t darktable
Definition darktable.c:181
#define UNKNOWN_IMAGE
Definition darktable.h:182
#define dt_free(ptr)
Definition darktable.h:456
static gchar * delete_underscore(const char *s)
Definition darktable.h:1083
#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_PREPARE_V2(a, b, c, d, e)
Definition debug.h:107
static GdkPixbuf * dt_draw_paint_to_pixbuf(GtkWidget *widget, const guint pixbuf_size, const int flags, void(*dtgtk_cairo_paint_fct)(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data))
Definition draw.h:499
void dtgtk_cairo_paint_switch(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_switch_inactive(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
const dt_collection_sort_t items[]
Definition filter.c:95
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
#define DT_PIXEL_APPLY_DPI(value)
Definition gtk.h:90
_style_items_columns_t
Definition hist_dialog.c:49
const char * model
const char * dt_iop_order_string(const dt_iop_order_t order)
Return the human-readable name for an IOP order enum value.
Definition iop_order.c:80
dt_iop_order_t dt_ioppr_get_iop_order_version(const int32_t imgid)
Fetch the IOP order version stored for an image.
Definition iop_order.c:761
dt_iop_order_t
Definition iop_order.h:143
void dt_osx_disallow_fullscreen(GtkWidget *widget)
Definition osx.mm:104
struct _GtkWidget GtkWidget
Definition splash.h:29
gboolean dt_styles_exists(const char *name)
GList * dt_styles_get_item_list(const char *name, gboolean params, int32_t imgid)
gchar * dt_styles_get_description(const char *name)
void dt_styles_update(const char *name, const char *newname, const char *newdescription, GList *filter, const int32_t imgid, GList *update, const gboolean copy_iop_order, const gboolean update_iop_order)
void dt_style_item_free(gpointer data)
void dt_styles_create_from_style(const char *name, const char *newname, const char *description, GList *filter, const int32_t imgid, GList *update, const gboolean copy_iop_order, const gboolean update_iop_order)
void dt_styles_delete_by_name(const char *name)
gboolean dt_styles_has_module_order(const char *name)
gboolean dt_styles_create_from_image(const char *name, const char *description, const int32_t imgid, GList *filter, gboolean copy_iop_order)
struct dt_gui_gtk_t * gui
Definition darktable.h:775
const struct dt_database_t * db
Definition darktable.h:779
struct dt_develop_t * develop
Definition darktable.h:770
GList * iop
Definition develop.h:279
dt_ui_t * ui
Definition gtk.h:164
GtkTreeView * items_new
gboolean enabled
Definition history.h:111
static void _gui_styles_update_toggled(GtkCellRendererToggle *cell, gchar *path_str, gpointer data)
static int _single_selected_imgid()
static void _gui_styles_dialog_run(gboolean edit, const char *name, int32_t imgid)
enum _style_items_columns_t _styles_columns_t
void _gui_styles_get_active_items(dt_gui_styles_dialog_t *sd, GList **enabled, GList **update)
void dt_gui_styles_dialog_new(int32_t imgid)
static void _gui_styles_item_toggled(GtkCellRendererToggle *cell, gchar *path_str, gpointer data)
static gint _g_list_find_module_by_name(gconstpointer a, gconstpointer b)
static gboolean _gui_styles_is_copy_module_order_set(dt_gui_styles_dialog_t *d)
static void _gui_styles_edit_style_response(GtkDialog *dialog, gint response_id, dt_gui_styles_dialog_t *g)
static void _gui_styles_select_all_items(dt_gui_styles_dialog_t *d, gboolean active)
static void _gui_styles_item_new_toggled(GtkCellRendererToggle *cell, gchar *path_str, gpointer data)
static gboolean _gui_styles_is_update_module_order_set(dt_gui_styles_dialog_t *d)
@ DT_STYLE_ITEMS_COL_ISACTIVE
@ DT_STYLE_ITEMS_COL_NUM
@ DT_STYLE_ITEMS_NUM_COLS
@ DT_STYLE_ITEMS_COL_UPDATE_NUM
@ DT_STYLE_ITEMS_COL_ENABLED
@ DT_STYLE_ITEMS_COL_UPDATE
@ DT_STYLE_ITEMS_COL_NAME
static void _gui_styles_new_style_response(GtkDialog *dialog, gint response_id, dt_gui_styles_dialog_t *g)
void dt_gui_styles_dialog_edit(const char *name)