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/selection.h"
39#include "common/image.h"
40#include "system/mem_alloc.h"
41#include "history/history.h"
42#include "common/styles.h"
44#include "develop/imageop.h"
45#include "gui/application.h"
46#include "widgets/draw.h"
47#include "gui/styles.h"
48#include "widgets/label.h"
50#ifdef GDK_WINDOWING_QUARTZ
51#include "osx/osx.h"
52#endif
53
54/* creates a styles dialog, if edit equals true id=styleid else id=imgid */
55static void _gui_styles_dialog_run(gboolean edit, const char *name, int32_t imgid);
56
58{
59 gboolean edit;
60 int32_t imgid;
61 gchar *nameorig;
63 GtkTreeView *items;
64 GtkTreeView *items_new;
66
67
78
80{
81 // Exactly one selected image, or nothing. The length test must come FIRST: it null-checks the
82 // selection, dt_selection_get_first_id() does not.
86}
87
89{
90 /* first item is the copy-module */
91 GtkTreeIter iter;
92 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(d->items));
93
94 gboolean active = FALSE;
95 gint num = 0;
96 if(gtk_tree_model_get_iter_first(model, &iter))
97 gtk_tree_model_get(model, &iter, DT_STYLE_ITEMS_COL_ENABLED, &active, DT_STYLE_ITEMS_COL_NUM, &num, -1);
98 return active && (num == -1);
99}
100
102{
103 /* first item is the copy-module */
104 GtkTreeIter iter;
105 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(d->items));
106
107 gboolean active = FALSE;
108 gint num = 0;
109 if(gtk_tree_model_get_iter_first(model, &iter))
110 gtk_tree_model_get(model, &iter, DT_STYLE_ITEMS_COL_UPDATE, &active, DT_STYLE_ITEMS_COL_NUM, &num, -1);
111 return active && (num == -1);
112}
113
115{
116 /* run through all items and add active ones to result */
117 GtkTreeIter iter;
118 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(sd->items));
119 gint num = 0, update_num = 0;
120 gboolean active, uactive;
121
122 if(gtk_tree_model_get_iter_first(model, &iter))
123 {
124 do
125 {
126 gtk_tree_model_get(model, &iter, DT_STYLE_ITEMS_COL_ENABLED, &active,
130 -1);
131 if((active || uactive) && num >= 0)
132 {
133 *enabled = g_list_append(*enabled, GINT_TO_POINTER(num));
134 if(!IS_NULL_PTR(update))
135 {
136 if(uactive)
137 *update = g_list_append(*update, GINT_TO_POINTER(update_num));
138 else
139 *update = g_list_append(*update, GINT_TO_POINTER(-1));
140 }
141 }
142 } while(gtk_tree_model_iter_next(model, &iter));
143 }
144
145 /* check for new items to be included */
146 model = gtk_tree_view_get_model(GTK_TREE_VIEW(sd->items_new));
147 if(gtk_tree_model_get_iter_first(model, &iter))
148 {
149 do
150 {
151 gtk_tree_model_get(model, &iter,
155 -1);
156 if(active)
157 {
158 if(update_num == -1) // item from style
159 {
160 *enabled = g_list_append(*enabled, GINT_TO_POINTER(num));
161 *update = g_list_append(*update, GINT_TO_POINTER(-1));
162 }
163 else // item from image
164 {
165 *update = g_list_append(*update, GINT_TO_POINTER(update_num));
166 *enabled = g_list_append(*enabled, GINT_TO_POINTER(-1));
167 }
168 }
169 } while(gtk_tree_model_iter_next(model, &iter));
170 }
171}
172
174{
175 /* run through all items and set active status */
176 GtkTreeView *items = (d->duplicate) ? d->items_new : d->items;
177 GtkTreeIter iter;
178 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(items));
179 if(gtk_tree_model_get_iter_first(model, &iter))
180 {
181 do
182 {
183 gtk_list_store_set(GTK_LIST_STORE(model), &iter, DT_STYLE_ITEMS_COL_ENABLED, active, -1);
184 } while(gtk_tree_model_iter_next(model, &iter));
185 }
186}
187
188static void _gui_styles_new_style_response(GtkDialog *dialog, gint response_id, dt_gui_styles_dialog_t *g)
189{
190 if(response_id == GTK_RESPONSE_YES)
191 {
193 return;
194 }
195 else if(response_id == GTK_RESPONSE_NONE)
196 {
198 return;
199 }
200 else if(response_id == GTK_RESPONSE_ACCEPT)
201 {
202 /* get the filtered list from dialog */
203 GList *result = NULL;
204 _gui_styles_get_active_items(g, &result, NULL);
205
206 /* create the style from imageid */
207 const gchar *name = gtk_entry_get_text(GTK_ENTRY(g->name));
208 if(name && *name)
209 {
210
211 /* show prompt dialog when style already exists */
212 if(name && (dt_styles_exists(name)) != 0)
213 {
215 GtkWidget *dlg_overwrite = gtk_message_dialog_new(
216 GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO,
217 _("style `%s' already exists.\ndo you want to overwrite?"), name);
218#ifdef GDK_WINDOWING_QUARTZ
219 dt_osx_disallow_fullscreen(dlg_overwrite);
220#endif
221
222 gtk_window_set_title(GTK_WINDOW(dlg_overwrite), _("overwrite style?"));
223
224 const gint dlg_ret = gtk_dialog_run(GTK_DIALOG(dlg_overwrite));
225 gtk_widget_destroy(dlg_overwrite);
226
227 /* on button yes delete style name for overwriting */
228 if(dlg_ret == GTK_RESPONSE_YES)
229 {
231 }
232 else
233 {
234 /* on RESPONSE_NO and escape key return to dialog */
235 return;
236 }
237 }
238
239 if(dt_styles_create_from_image(name, gtk_entry_get_text(GTK_ENTRY(g->description)),
240 g->imgid, result, _gui_styles_is_copy_module_order_set(g)))
241 {
242 dt_control_log(_("style named '%s' successfully created"), name);
243 };
244 }
245 else
246 {
247 /* show dialog if name is missing from entry */
249 GtkWidget *dlg_changename
250 = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING,
251 GTK_BUTTONS_OK, _("please give style a name"));
252#ifdef GDK_WINDOWING_QUARTZ
253 dt_osx_disallow_fullscreen(dlg_changename);
254#endif
255 gtk_window_set_title(GTK_WINDOW(dlg_changename), _("unnamed style"));
256 gtk_dialog_run(GTK_DIALOG(dlg_changename));
257 gtk_widget_destroy(dlg_changename);
258 return;
259 }
260 }
261 gtk_widget_destroy(GTK_WIDGET(dialog));
262 dt_free(g->nameorig);
263 dt_free(g);
264}
265
266static void _gui_styles_edit_style_response(GtkDialog *dialog, gint response_id, dt_gui_styles_dialog_t *g)
267{
268 if(response_id == GTK_RESPONSE_YES)
269 {
271 return;
272 }
273 else if(response_id == GTK_RESPONSE_NONE)
274 {
276 return;
277 }
278 else if(response_id == GTK_RESPONSE_ACCEPT)
279 {
280 /* get the filtered list from dialog */
281 GList *result = NULL, *update = NULL;
282
283 _gui_styles_get_active_items(g, &result, &update);
284
285 const gchar *name = gtk_entry_get_text(GTK_ENTRY(g->name));
286 if(name && *name)
287 {
288 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g->duplicate)))
289 {
290 dt_styles_create_from_style(g->nameorig, name, gtk_entry_get_text(GTK_ENTRY(g->description)),
291 result, g->imgid, update,
294 }
295 else
296 {
297 dt_styles_update(g->nameorig, name, gtk_entry_get_text(GTK_ENTRY(g->description)),
298 result, g->imgid, update,
301 }
302 dt_control_log(_("style %s was successfully saved"), name);
303 }
304 else
305 {
306 /* show dialog if name is missing from entry */
308 GtkWidget *dlg_changename
309 = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING,
310 GTK_BUTTONS_OK, _("please give style a name"));
311#ifdef GDK_WINDOWING_QUARTZ
312 dt_osx_disallow_fullscreen(dlg_changename);
313#endif
314 gtk_window_set_title(GTK_WINDOW(dlg_changename), _("unnamed style"));
315 gtk_dialog_run(GTK_DIALOG(dlg_changename));
316 gtk_widget_destroy(dlg_changename);
317 return;
318 }
319 }
320 gtk_widget_destroy(GTK_WIDGET(dialog));
321 dt_free(g->nameorig);
322 dt_free(g);
323}
324
325static void _gui_styles_item_toggled(GtkCellRendererToggle *cell, gchar *path_str, gpointer data)
326{
328
329 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(sd->items));
330 GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
331 GtkTreeIter iter;
332 gboolean toggle_item;
333 gint num, update_num;
334
335 gtk_tree_model_get_iter(model, &iter, path);
336 gtk_tree_model_get(model, &iter,
337 DT_STYLE_ITEMS_COL_ENABLED, &toggle_item,
340 -1);
341
342 toggle_item = (toggle_item == TRUE) ? FALSE : TRUE;
343
344 if(update_num != -1 && toggle_item) // include so not updated
345 gtk_list_store_set(GTK_LIST_STORE(model), &iter, DT_STYLE_ITEMS_COL_UPDATE, FALSE, -1);
346
347 gtk_list_store_set(GTK_LIST_STORE(model), &iter, DT_STYLE_ITEMS_COL_ENABLED, toggle_item, -1);
348 gtk_tree_path_free(path);
349}
350
351static void _gui_styles_item_new_toggled(GtkCellRendererToggle *cell, gchar *path_str, gpointer data)
352{
354
355 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(sd->items_new));
356 GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
357 GtkTreeIter iter;
358 gboolean toggle_item;
359
360 gtk_tree_model_get_iter(model, &iter, path);
361 gtk_tree_model_get(model, &iter, DT_STYLE_ITEMS_COL_ENABLED, &toggle_item, -1);
362
363 toggle_item = (toggle_item == TRUE) ? FALSE : TRUE;
364
365 gtk_list_store_set(GTK_LIST_STORE(model), &iter, DT_STYLE_ITEMS_COL_ENABLED, toggle_item, -1);
366 gtk_tree_path_free(path);
367}
368
369static void _gui_styles_update_toggled(GtkCellRendererToggle *cell, gchar *path_str, gpointer data)
370{
372
373 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(sd->items));
374 GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
375 GtkTreeIter iter;
376 gboolean toggle_item;
377
378 gtk_tree_model_get_iter(model, &iter, path);
379 gtk_tree_model_get(model, &iter, DT_STYLE_ITEMS_COL_UPDATE, &toggle_item, -1);
380
381 toggle_item = (toggle_item == TRUE) ? FALSE : TRUE;
382
383 gtk_list_store_set(GTK_LIST_STORE(model), &iter, DT_STYLE_ITEMS_COL_ENABLED, !toggle_item, -1);
384 gtk_list_store_set(GTK_LIST_STORE(model), &iter, DT_STYLE_ITEMS_COL_UPDATE, toggle_item, -1);
385 gtk_tree_path_free(path);
386}
387
388void dt_gui_styles_dialog_new(int32_t imgid)
389{
390 _gui_styles_dialog_run(FALSE, NULL, imgid);
391}
392
397
398static gint _g_list_find_module_by_name(gconstpointer a, gconstpointer b)
399{
400 return strncmp(((dt_iop_module_t *)a)->op, b, strlen(((dt_iop_module_t *)a)->op));
401}
402
403static void _gui_styles_dialog_run(gboolean edit, const char *name, int32_t imgid)
404{
405 char title[512];
406
407 /* check if style exists */
408 if(name && (dt_styles_exists(name)) == 0) return;
409
410 /* initialize the dialog */
412 sd->nameorig = g_strdup(name);
413 sd->imgid = imgid;
414
415 if(edit)
416 {
417 snprintf(title, sizeof(title), "%s \"%s\"", _("edit style"), name);
418 sd->duplicate = gtk_check_button_new_with_label(_("duplicate style"));
419 gtk_widget_set_tooltip_text(sd->duplicate, _("creates a duplicate of the style before applying changes"));
420 }
421 else
422 {
423 g_strlcpy(title, _("create new style"), sizeof(title));
424 sd->duplicate = NULL;
425 }
427 GtkDialog *dialog = GTK_DIALOG(
428 gtk_dialog_new_with_buttons(title, GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT,
429 _("_cancel"), GTK_RESPONSE_REJECT,
430 _("select _all"), GTK_RESPONSE_YES,
431 _("select _none"), GTK_RESPONSE_NONE,
432 _("_save"), GTK_RESPONSE_ACCEPT, NULL));
433#ifdef GDK_WINDOWING_QUARTZ
434 dt_osx_disallow_fullscreen(GTK_WIDGET(dialog));
435#endif
436
437 GtkContainer *content_area = GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog)));
438
439 // label box
440 GtkBox *box = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING));
441
442 GtkWidget *scroll = gtk_scrolled_window_new(NULL, NULL);
443 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
444 gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(scroll), DT_PIXEL_APPLY_DPI(450));
445// only available in 3.22, and not making the expected job anyway
446// gtk_scrolled_window_set_max_content_height(GTK_SCROLLED_WINDOW(scroll), DT_PIXEL_APPLY_DPI(700));
447// gtk_scrolled_window_set_propagate_natural_height(GTK_SCROLLED_WINDOW(scroll), TRUE);
448
449 // box in scrollwindow containing the two possible trees
450 GtkBox *sbox = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING));
451 dt_gui_add_class(GTK_WIDGET(sbox), "dt_recessed_scroll");
452
453 gtk_box_pack_start(GTK_BOX(content_area), GTK_WIDGET(box), TRUE, TRUE, 0);
454 gtk_container_add(GTK_CONTAINER(scroll), GTK_WIDGET(sbox));
455
456 sd->name = gtk_entry_new();
458 gtk_entry_set_placeholder_text(GTK_ENTRY(sd->name), _("name"));
459 gtk_widget_set_tooltip_text(sd->name, _("enter a name for the new style"));
460
461 sd->description = gtk_entry_new();
463 gtk_entry_set_placeholder_text(GTK_ENTRY(sd->description), _("description"));
464 gtk_widget_set_tooltip_text(sd->description,
465 _("enter a description for the new style, this description is searchable"));
466
467 /*set values*/
468 if(edit && name)
469 {
470 /* name */
471 gtk_entry_set_text(GTK_ENTRY(sd->name), name);
472 /* description */
473 gchar *desc = dt_styles_get_description(name);
474 if(desc)
475 {
476 gtk_entry_set_text(GTK_ENTRY(sd->description), desc);
477 dt_free(desc);
478 }
479 }
480
481 gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(sd->name), FALSE, TRUE, 0);
482 gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(sd->description), FALSE, TRUE, 0);
483 gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(scroll), TRUE, TRUE, 0);
484
485 /* create the list of items */
486 sd->items = GTK_TREE_VIEW(gtk_tree_view_new());
487 GtkListStore *liststore = gtk_list_store_new(DT_STYLE_ITEMS_NUM_COLS, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
488 GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT);
489
490 sd->items_new = GTK_TREE_VIEW(gtk_tree_view_new());
491 GtkListStore *liststore_new = gtk_list_store_new(DT_STYLE_ITEMS_NUM_COLS, G_TYPE_BOOLEAN, G_TYPE_STRING,
492 GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT);
493
494 /* enabled */
495 GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new();
496 gtk_cell_renderer_toggle_set_activatable(GTK_CELL_RENDERER_TOGGLE(renderer), TRUE);
497 g_object_set_data(G_OBJECT(renderer), "column", (gint *)DT_STYLE_ITEMS_COL_ENABLED);
498 g_signal_connect(renderer, "toggled", G_CALLBACK(_gui_styles_item_toggled), sd);
499
500 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(sd->items), -1, _("include"), renderer, "active",
502
503 if(edit)
504 {
505 renderer = gtk_cell_renderer_toggle_new();
506 gtk_cell_renderer_toggle_set_activatable(GTK_CELL_RENDERER_TOGGLE(renderer), TRUE);
507 g_object_set_data(G_OBJECT(renderer), "column", (gint *)DT_STYLE_ITEMS_COL_ENABLED);
508 g_signal_connect(renderer, "toggled", G_CALLBACK(_gui_styles_item_new_toggled), sd);
509 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(sd->items_new), -1, _("include"), renderer,
510 "active", DT_STYLE_ITEMS_COL_ENABLED, NULL);
511 }
512
513 /* update */
514 if(edit && imgid != UNKNOWN_IMAGE)
515 {
516 renderer = gtk_cell_renderer_toggle_new();
517 gtk_cell_renderer_toggle_set_activatable(GTK_CELL_RENDERER_TOGGLE(renderer), TRUE);
518 g_object_set_data(G_OBJECT(renderer), "column", (gint *)DT_STYLE_ITEMS_COL_UPDATE);
519 g_signal_connect(renderer, "toggled", G_CALLBACK(_gui_styles_update_toggled), sd);
520
521 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(sd->items), -1, _("update"), renderer, "active",
523 }
524
525 /* active */
526 renderer = gtk_cell_renderer_pixbuf_new();
527 GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes("", renderer, "pixbuf",
529 gtk_tree_view_append_column(GTK_TREE_VIEW(sd->items), column);
530 gtk_tree_view_column_set_alignment(column, 0.5);
531 gtk_tree_view_column_set_clickable(column, FALSE);
532 gtk_tree_view_column_set_min_width(column, DT_PIXEL_APPLY_DPI(30));
533
534 if(edit)
535 {
536 column = gtk_tree_view_column_new_with_attributes("", renderer, "pixbuf",
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 gtk_tree_view_append_column(GTK_TREE_VIEW(sd->items_new), column);
542 }
543
544 /* name */
545 renderer = gtk_cell_renderer_text_new();
546 g_object_set_data(G_OBJECT(renderer), "column", (gint *)DT_STYLE_ITEMS_COL_NAME);
547 g_object_set(renderer, "xalign", 0.0, (gchar *)0);
548 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(sd->items), -1, _("item"), renderer, "text",
550
551 if(edit)
552 {
553 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(sd->items_new), -1, _("item"), renderer, "text",
555 }
556
557 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(sd->items)), GTK_SELECTION_SINGLE);
558 gtk_tree_view_set_model(GTK_TREE_VIEW(sd->items), GTK_TREE_MODEL(liststore));
559
560 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(sd->items_new)), GTK_SELECTION_SINGLE);
561 gtk_tree_view_set_model(GTK_TREE_VIEW(sd->items_new), GTK_TREE_MODEL(liststore_new));
562
563 gboolean has_new_item = FALSE, has_item = FALSE;
564
565 GdkPixbuf *is_active_pb =
566 dt_draw_paint_to_pixbuf(GTK_WIDGET(dialog), 10, 0, dtgtk_cairo_paint_switch);
567 GdkPixbuf *is_inactive_pb =
569
570 /* fill list with history items */
571 GtkTreeIter iter;
572 if(edit)
573 {
574 gtk_list_store_append(GTK_LIST_STORE(liststore), &iter);
575 gtk_list_store_set(GTK_LIST_STORE(liststore), &iter,
577 DT_STYLE_ITEMS_COL_ISACTIVE, is_active_pb,
578 DT_STYLE_ITEMS_COL_NAME, _("module order"),
580 -1);
581 /* get history items for named style and populate the items list */
582 GList *items = dt_styles_get_item_list(name, FALSE, imgid);
583 if(items)
584 {
585 for(const GList *items_iter = items; items_iter; items_iter = g_list_next(items_iter))
586 {
587 dt_style_item_t *item = (dt_style_item_t *)items_iter->data;
588
589 if(item->num != -1 && item->selimg_num != -1) // defined in style and image
590 {
591 gtk_list_store_append(GTK_LIST_STORE(liststore), &iter);
592 gtk_list_store_set(GTK_LIST_STORE(liststore), &iter,
595 DT_STYLE_ITEMS_COL_ISACTIVE, item->enabled ? is_active_pb : is_inactive_pb,
599 -1);
600 has_item = TRUE;
601 }
602 else if(item->num != -1
603 || item->selimg_num != -1) // defined in one or the other, let a way to select it or not
604 {
605 gtk_list_store_append(GTK_LIST_STORE(liststore_new), &iter);
606 gtk_list_store_set(GTK_LIST_STORE(liststore_new), &iter,
607 DT_STYLE_ITEMS_COL_ENABLED, item->num != -1 ? TRUE : FALSE,
608 DT_STYLE_ITEMS_COL_ISACTIVE, item->enabled ? is_active_pb : is_inactive_pb,
612 -1);
613 has_new_item = TRUE;
614 }
615 }
616 g_list_free_full(items, dt_style_item_free);
617 items = NULL;
618 }
619 }
620 else
621 {
623 char *label = g_strdup_printf("%s (%s)", _("module order"), dt_iop_order_string(order));
624 gtk_list_store_append(GTK_LIST_STORE(liststore), &iter);
625 gtk_list_store_set(GTK_LIST_STORE(liststore), &iter,
627 DT_STYLE_ITEMS_COL_ISACTIVE, is_active_pb,
630 -1);
631 dt_free(label);
632
633 GList *items = dt_history_get_items(imgid, FALSE);
634 if(items)
635 {
636 for(const GList *items_iter = items; items_iter; items_iter = g_list_next(items_iter))
637 {
638 dt_history_item_t *item = (dt_history_item_t *)items_iter->data;
639
640 /* lookup history item module */
641 gboolean enabled = TRUE;
642 dt_iop_module_t *module = NULL;
643 GList *modules = dt_dev_get_global()->iop;
644 if(modules)
645 {
646 GList *result = g_list_find_custom(
647 modules, item->op, _g_list_find_module_by_name); // (dt_iop_module_t *)(modules->data);
648 if(result)
649 {
650 module = (dt_iop_module_t *)(result->data);
651 enabled = (module->flags() & IOP_FLAGS_INCLUDE_IN_STYLES) ? TRUE : FALSE;
652 }
653 }
654
655 gtk_list_store_append(GTK_LIST_STORE(liststore), &iter);
656 gtk_list_store_set(GTK_LIST_STORE(liststore), &iter,
658 DT_STYLE_ITEMS_COL_ISACTIVE, item->enabled ? is_active_pb : is_inactive_pb,
661 -1);
662
663 has_item = TRUE;
664 }
665 g_list_free_full(items, dt_history_item_free);
666 items = NULL;
667 }
668 else
669 {
670 dt_control_log(_("can't create style out of unaltered image"));
671 return;
672 }
673 }
674
675 if(has_item) gtk_box_pack_start(GTK_BOX(sbox), GTK_WIDGET(sd->items), TRUE, TRUE, 0);
676
677 if(has_new_item) gtk_box_pack_start(GTK_BOX(sbox), GTK_WIDGET(sd->items_new), TRUE, TRUE, 0);
678
679 if(edit) gtk_box_pack_start(GTK_BOX(content_area), GTK_WIDGET(sd->duplicate), FALSE, TRUE, 0);
680
681 g_object_unref(liststore);
682 g_object_unref(liststore_new);
683
684 /* run dialog */
685 if(edit)
686 g_signal_connect(dialog, "response", G_CALLBACK(_gui_styles_edit_style_response), sd);
687 else
688 g_signal_connect(dialog, "response", G_CALLBACK(_gui_styles_new_style_response), sd);
689
690 gtk_widget_show_all(GTK_WIDGET(dialog));
691 gtk_dialog_run(GTK_DIALOG(dialog));
692
693 g_object_unref(is_active_pb);
694 g_object_unref(is_inactive_pb);
695}
696// clang-format off
697// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
698// vim: shiftwidth=2 expandtab tabstop=2 cindent
699// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
700// clang-format on
void dt_accels_disconnect_on_text_input(GtkWidget *widget)
Disconnect accels while a text or search entry has the focus, and reconnect them when it loses it....
GtkWidget * dt_gui_main_window(void)
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
Definition colorspaces.h:98
void dt_control_log(const char *msg,...)
Definition control.c:824
struct dt_develop_t * dt_dev_get_global(void)
Definition darktable.c:528
GtkWidget * window
gboolean enabled
–doc was passed on the command line
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:514
const dt_collection_sort_t items[]
Definition filter.c:102
_style_items_columns_t
Definition hist_dialog.c:52
GList * dt_history_get_items(const int32_t imgid, gboolean enabled)
void dt_history_item_free(gpointer data)
#define UNKNOWN_IMAGE
Definition image.h:78
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:82
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:811
dt_iop_order_t
Definition iop_order.h:149
gchar * delete_underscore(const char *s)
Definition label.c:75
#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
void dt_osx_disallow_fullscreen(GtkWidget *widget)
Definition osx.mm:105
const char * name
Definition pdf.h:90
int32_t dt_selection_get_first_id(struct dt_selection_t *selection)
Definition selection.c:103
struct dt_selection_t * dt_selection_get_global(void)
Definition selection.c:80
int dt_selection_get_length(struct dt_selection_t *selection)
Definition selection.c:193
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)
GList * iop
Definition develop.h:269
GtkTreeView * items_new
gboolean enabled
Definition history.h:83
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)
Telling the user something happened.
#define DT_GUI_BOX_SPACING
#define DT_PIXEL_APPLY_DPI(value)
void dt_gui_add_class(GtkWidget *widget, const gchar *class_name)
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)