Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
dev_toolbox.c
Go to the documentation of this file.
1/*
2 This file is part of the Ansel project.
3 Copyright (C) 2026 Guillaume STUTIN.
4
5 Ansel 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 Ansel 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
16#include "views/dev_toolbox.h"
17
18#include "bauhaus/bauhaus.h"
19#include "common/colorspaces.h"
20#include "common/darktable.h"
23#include "control/conf.h"
24#include "control/control.h"
25#include "control/signal.h"
26#include "develop/develop.h"
28#include "dtgtk/button.h"
29#include "dtgtk/paint.h"
30#include "dtgtk/togglebutton.h"
31#include "gui/accelerators.h"
32#include "gui/gtk.h"
33
34#include <limits.h>
35
36#define DT_DEV_TOOLBOX_BUTTON_TYPE_KEY "dt-dev-toolbox-button-type"
37
39{
40 if(dev->iso_12646.enabled)
41 {
42 // For ISO 12646, we want portraits and landscapes to cover roughly the same surface
43 // no matter the size of the widget. Meaning we force them to fit a square
44 // of length matching the smaller widget dimension. The goal is to leave
45 // a consistent perceptual impression between pictures, independent from orientation.
46 const int main_dim = MIN(dev->roi.orig_width, dev->roi.orig_height);
47 dev->roi.border_size = 0.125 * main_dim;
48 }
49 else
50 {
51 dev->roi.border_size = DT_PIXEL_APPLY_DPI(dt_conf_get_int("plugins/darkroom/ui/border_size"));
52 }
53
54 dt_dev_configure(dev, dev->roi.orig_width - 2 * dev->roi.border_size, dev->roi.orig_height - 2 * dev->roi.border_size);
55}
56
57/*
58 * Popover show/anchor plumbing, generic: reusable for any button+popover
59 * pair, including ones outside the button set below (darkroom's guides and
60 * auto-set popovers use this too).
61 */
62
63#define DT_DEV_TOOLBOX_PRESHOW_FN_KEY "dt-dev-toolbox-popover-preshow-fn"
64#define DT_DEV_TOOLBOX_PRESHOW_DATA_KEY "dt-dev-toolbox-popover-preshow-data"
65
66void dt_dev_toolbox_popover_set_preshow(GtkWidget *popover, void (*preshow)(gpointer user_data), gpointer user_data)
67{
68 g_object_set_data(G_OBJECT(popover), DT_DEV_TOOLBOX_PRESHOW_FN_KEY, (gpointer)preshow);
69 g_object_set_data(G_OBJECT(popover), DT_DEV_TOOLBOX_PRESHOW_DATA_KEY, user_data);
70}
71
72gboolean dt_dev_toolbox_show_popup(gpointer user_data)
73{
74 GtkPopover *popover = GTK_POPOVER(user_data);
75
76 GtkWidget *button = gtk_popover_get_relative_to(popover);
77 GdkRectangle button_rect = { 0 };
78 GtkWidget *anchor = dt_gui_get_popup_relative_widget(button, &button_rect);
79 GdkDevice *pointer = gdk_seat_get_pointer(gdk_display_get_default_seat(gdk_display_get_default()));
80
81 int x, y;
82 GdkWindow *pointer_window = gdk_device_get_window_at_position(pointer, &x, &y);
83 gpointer pointer_widget = NULL;
84 if(pointer_window) gdk_window_get_user_data(pointer_window, &pointer_widget);
85
86 gtk_popover_set_relative_to(popover, anchor ? anchor : button);
87
88 GdkRectangle rect = { button_rect.x + button_rect.width / 2, button_rect.y, 1, 1 };
89
90 if(pointer_widget == anchor)
91 {
92 rect.x = x;
93 rect.y = y;
94 }
95 else if(pointer_widget && anchor && pointer_widget != anchor)
96 {
97 gtk_widget_translate_coordinates(pointer_widget, anchor, x, y, &rect.x, &rect.y);
98 }
99
100 gtk_popover_set_pointing_to(popover, &rect);
101
102 void (*preshow)(gpointer) = (void (*)(gpointer))g_object_get_data(G_OBJECT(popover), DT_DEV_TOOLBOX_PRESHOW_FN_KEY);
103 if(preshow) preshow(g_object_get_data(G_OBJECT(popover), DT_DEV_TOOLBOX_PRESHOW_DATA_KEY));
104
105 gtk_widget_show_all(GTK_WIDGET(popover));
106
107 // cancel glib timeout if invoked by long button press
108 return FALSE;
109}
110
111static gboolean _quickbutton_press_release(GtkWidget *button, GdkEventButton *event, GtkWidget *popover)
112{
113 static guint start_time = 0;
114
115 int delay = 0;
116 g_object_get(gtk_settings_get_default(), "gtk-long-press-time", &delay, NULL);
117
118 if((event->type == GDK_BUTTON_PRESS && event->button == 3)
119 || (event->type == GDK_BUTTON_RELEASE && event->time - start_time > delay))
120 {
121 gtk_popover_set_relative_to(GTK_POPOVER(popover), button);
122 g_object_set(G_OBJECT(popover), "transitions-enabled", FALSE, NULL);
123
125 return TRUE;
126 }
127 else
128 {
129 start_time = event->time;
130 return FALSE;
131 }
132}
133
135{
136 g_signal_connect(button, "button-press-event", G_CALLBACK(_quickbutton_press_release), popover);
137 g_signal_connect(button, "button-release-event", G_CALLBACK(_quickbutton_press_release), popover);
138}
139
140/*
141 * Accelerators: forward keyboard activation to the existing Gtk buttons so
142 * the keyboard path reuses the exact same callbacks, state changes and
143 * popover anchoring as the pointer path. Generic — reused for guides and
144 * auto-set (outside the button set below) by whichever view owns them.
145 */
146
147gboolean dt_dev_toolbox_activate_accel(GtkAccelGroup *accel_group, GObject *accelerable, guint keyval,
148 GdkModifierType modifier, gpointer data)
149{
150 GtkWidget *button = GTK_WIDGET(data);
151 if(IS_NULL_PTR(button) || !gtk_widget_is_visible(button) || !gtk_widget_is_sensitive(button)) return FALSE;
152
153 gtk_button_clicked(GTK_BUTTON(button));
154 return TRUE;
155}
156
157gboolean dt_dev_toolbox_focus_accel(GtkAccelGroup *accel_group, GObject *accelerable, guint keyval,
158 GdkModifierType modifier, gpointer data)
159{
160 GtkWidget *button = GTK_WIDGET(data);
161 if(IS_NULL_PTR(button) || !gtk_widget_is_visible(button) || !gtk_widget_is_sensitive(button)) return FALSE;
162
163 GtkWidget *popover = g_object_get_data(G_OBJECT(button), DT_DEV_TOOLBOX_POPOVER_KEY);
164 if(IS_NULL_PTR(popover) || !gtk_widget_is_sensitive(popover)) return FALSE;
165
166 gtk_widget_grab_focus(button);
167 gtk_popover_set_relative_to(GTK_POPOVER(popover), button);
169 return TRUE;
170}
171
172void dt_dev_toolbox_add_accels(dt_develop_t *dev, GtkAccelGroup *accel_group, const char *category,
173 const dt_dev_toolbox_button_t *buttons, size_t n_buttons)
174{
175 for(size_t i = 0; i < n_buttons; i++)
176 {
177 GtkWidget *button = NULL;
178 const char *activate_label = NULL;
179 const char *focus_label = NULL;
180
181 switch(buttons[i])
182 {
184 button = dev->iso_12646.button;
185 activate_label = N_("Toggle ISO 12646 color assessment conditions");
186 break;
187
189 button = dev->overexposed.button;
190 activate_label = N_("Toggle clipping indication");
191 focus_label = N_("Focus clipping indication options");
192 break;
193
195 button = dev->rawoverexposed.button;
196 activate_label = N_("Toggle raw over exposed indication");
197 focus_label = N_("Focus raw over exposed indication options");
198 break;
199
201 button = dev->profile.softproof_button;
202 activate_label = N_("Toggle softproofing");
203 focus_label = N_("Focus softproof options");
204 break;
205
207 button = dev->profile.gamut_button;
208 activate_label = N_("Toggle gamut checking");
209 focus_label = N_("Focus gamut checking options");
210 break;
211
213 button = dev->display.button;
214 focus_label = N_("Focus picture display options");
215 break;
216 }
217
218 if(activate_label)
220 category, activate_label, 0, 0, FALSE, _("Triggers the action"));
221 if(focus_label)
223 category, focus_label, 0, 0, FALSE, _("Shows the options popover"));
224 }
225}
226
227/*
228 * Single click dispatcher for every button below: which one fired is read
229 * back from a tag set at creation time, instead of one callback per button.
230 */
231
232static void _button_clicked(GtkWidget *w, gpointer user_data);
233
234/* Keep both buttons' active state in sync with darktable.color_profiles->mode,
235 since enabling one implicitly disables the other. */
237{
238 g_signal_handlers_block_by_func(dev->profile.softproof_button, _button_clicked, dev);
239 g_signal_handlers_block_by_func(dev->profile.gamut_button, _button_clicked, dev);
240
241 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dev->profile.softproof_button),
243 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dev->profile.gamut_button),
245
246 g_signal_handlers_unblock_by_func(dev->profile.softproof_button, _button_clicked, dev);
247 g_signal_handlers_unblock_by_func(dev->profile.gamut_button, _button_clicked, dev);
248}
249
250static void _button_clicked(GtkWidget *w, gpointer user_data)
251{
252 dt_develop_t *dev = (dt_develop_t *)user_data;
254 = (dt_dev_toolbox_button_t)GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), DT_DEV_TOOLBOX_BUTTON_TYPE_KEY));
255
256 switch(type)
257 {
259 if(!dev->gui_attached) return;
260 dev->iso_12646.enabled = !dev->iso_12646.enabled;
262 // This is already called in apply_iso_12646_size but it's not enough
264 break;
265
269 break;
270
274 break;
275
281 break;
282
288 break;
289
291 // No toggle state: this button only anchors an options popover, attached by the caller.
292 break;
293 }
294}
295
296/*
297 * Popover content: generic controls only. View-specific extras (darkroom's
298 * rendering-size and mask-preview-checkerboard additions to Picture
299 * display) are packed into the returned box by the caller afterward.
300 */
301
302static void _overexposed_mode_callback(GtkWidget *slider, gpointer user_data)
303{
304 dt_develop_t *dev = (dt_develop_t *)user_data;
306 if(dev->overexposed.enabled == FALSE) gtk_button_clicked(GTK_BUTTON(dev->overexposed.button));
308}
309
310static void _overexposed_colorscheme_callback(GtkWidget *combo, gpointer user_data)
311{
312 dt_develop_t *dev = (dt_develop_t *)user_data;
314 if(dev->overexposed.enabled == FALSE) gtk_button_clicked(GTK_BUTTON(dev->overexposed.button));
316}
317
318static void _overexposed_lower_callback(GtkWidget *slider, gpointer user_data)
319{
320 dt_develop_t *dev = (dt_develop_t *)user_data;
322 if(dev->overexposed.enabled == FALSE) gtk_button_clicked(GTK_BUTTON(dev->overexposed.button));
324}
325
326static void _overexposed_upper_callback(GtkWidget *slider, gpointer user_data)
327{
328 dt_develop_t *dev = (dt_develop_t *)user_data;
330 if(dev->overexposed.enabled == FALSE) gtk_button_clicked(GTK_BUTTON(dev->overexposed.button));
332}
333
335{
337
338 dev->overexposed.floating_window = gtk_popover_new(dev->overexposed.button);
340 g_object_set_data(G_OBJECT(dev->overexposed.button), DT_DEV_TOOLBOX_POPOVER_KEY, dev->overexposed.floating_window);
341
342 GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING);
343 gtk_container_add(GTK_CONTAINER(dev->overexposed.floating_window), vbox);
344
345 GtkWidget *mode;
346 DT_BAUHAUS_COMBOBOX_NEW_FULL(darktable.bauhaus, mode, NULL, N_("clipping preview mode"),
347 _("select the metric you want to preview\nfull gamut is the combination of all other modes"),
349 N_("full gamut"), N_("any RGB channel"), N_("luminance only"), N_("saturation only"));
350 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(mode), TRUE, TRUE, 0);
351
352 GtkWidget *colorscheme;
353 DT_BAUHAUS_COMBOBOX_NEW_FULL(darktable.bauhaus, colorscheme, NULL, N_("color scheme"),
354 _("select colors to indicate clipping"), dev->overexposed.colorscheme,
355 _overexposed_colorscheme_callback, dev, N_("black & white"), N_("red & blue"),
356 N_("purple & green"));
357 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(colorscheme), TRUE, TRUE, 0);
358
359 GtkWidget *lower = dt_bauhaus_slider_new_with_range(darktable.bauhaus, DT_GUI_MODULE(NULL), -32., -4., 1., -12.69, 2);
361 dt_bauhaus_slider_set_format(lower, _(" EV"));
362 dt_bauhaus_widget_set_label(lower, N_("lower threshold"));
363 gtk_widget_set_tooltip_text(lower, _("clipping threshold for the black point,\n"
364 "in EV, relatively to white (0 EV).\n"
365 "8 bits sRGB clips blacks at -12.69 EV,\n"
366 "8 bits Adobe RGB clips blacks at -19.79 EV,\n"
367 "16 bits sRGB clips blacks at -20.69 EV,\n"
368 "typical fine-art mat prints produce black at -5.30 EV,\n"
369 "typical color glossy prints produce black at -8.00 EV,\n"
370 "typical B&W glossy prints produce black at -9.00 EV."));
371 g_signal_connect(G_OBJECT(lower), "value-changed", G_CALLBACK(_overexposed_lower_callback), dev);
372 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(lower), TRUE, TRUE, 0);
373
374 GtkWidget *upper = dt_bauhaus_slider_new_with_range(darktable.bauhaus, DT_GUI_MODULE(NULL), 0.0, 100.0, 0.1, 99.99, 2);
377 dt_bauhaus_widget_set_label(upper, N_("upper threshold"));
378 /* xgettext:no-c-format */
379 gtk_widget_set_tooltip_text(upper, _("clipping threshold for the white point.\n100% is peak medium luminance."));
380 g_signal_connect(G_OBJECT(upper), "value-changed", G_CALLBACK(_overexposed_upper_callback), dev);
381 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(upper), TRUE, TRUE, 0);
382
383 gtk_widget_show_all(vbox);
384}
385
386static void _rawoverexposed_mode_callback(GtkWidget *combo, gpointer user_data)
387{
388 dt_develop_t *dev = (dt_develop_t *)user_data;
390 if(dev->rawoverexposed.enabled == FALSE) gtk_button_clicked(GTK_BUTTON(dev->rawoverexposed.button));
392}
393
394static void _rawoverexposed_colorscheme_callback(GtkWidget *combo, gpointer user_data)
395{
396 dt_develop_t *dev = (dt_develop_t *)user_data;
398 if(dev->rawoverexposed.enabled == FALSE) gtk_button_clicked(GTK_BUTTON(dev->rawoverexposed.button));
400}
401
402static void _rawoverexposed_threshold_callback(GtkWidget *slider, gpointer user_data)
403{
404 dt_develop_t *dev = (dt_develop_t *)user_data;
406 if(dev->rawoverexposed.enabled == FALSE) gtk_button_clicked(GTK_BUTTON(dev->rawoverexposed.button));
408}
409
411{
413
414 dev->rawoverexposed.floating_window = gtk_popover_new(dev->rawoverexposed.button);
416 g_object_set_data(G_OBJECT(dev->rawoverexposed.button), DT_DEV_TOOLBOX_POPOVER_KEY,
418
419 GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING);
420 gtk_container_add(GTK_CONTAINER(dev->rawoverexposed.floating_window), vbox);
421
422 GtkWidget *mode;
423 DT_BAUHAUS_COMBOBOX_NEW_FULL(darktable.bauhaus, mode, NULL, N_("mode"), _("select how to mark the clipped pixels"),
425 N_("mark with CFA color"), N_("mark with solid color"), N_("false color"));
426 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(mode), TRUE, TRUE, 0);
427
428 // FIXME can't use DT_BAUHAUS_COMBOBOX_NEW_FULL because of (unnecessary?) translation context
430 dt_bauhaus_widget_set_label(colorscheme, N_("color scheme"));
431 dt_bauhaus_combobox_add(colorscheme, C_("solidcolor", "red"));
432 dt_bauhaus_combobox_add(colorscheme, C_("solidcolor", "green"));
433 dt_bauhaus_combobox_add(colorscheme, C_("solidcolor", "blue"));
434 dt_bauhaus_combobox_add(colorscheme, C_("solidcolor", "black"));
436 gtk_widget_set_tooltip_text(
437 colorscheme, _("select the solid color to indicate over exposure.\nwill only be used if mode = mark with solid color"));
438 g_signal_connect(G_OBJECT(colorscheme), "value-changed", G_CALLBACK(_rawoverexposed_colorscheme_callback), dev);
439 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(colorscheme), TRUE, TRUE, 0);
440
443 dt_bauhaus_widget_set_label(threshold, N_("clipping threshold"));
444 gtk_widget_set_tooltip_text(threshold,
445 _("threshold of what shall be considered overexposed\n1.0 - white level\n0.0 - black level"));
446 g_signal_connect(G_OBJECT(threshold), "value-changed", G_CALLBACK(_rawoverexposed_threshold_callback), dev);
447 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(threshold), TRUE, TRUE, 0);
448
449 gtk_widget_show_all(vbox);
450}
451
452static void _softproof_profile_callback(GtkWidget *combo, gpointer user_data)
453{
454 dt_develop_t *dev = (dt_develop_t *)user_data;
455 gboolean profile_changed = FALSE;
456 const int pos = dt_bauhaus_combobox_get(combo);
457 for(GList *profiles = darktable.color_profiles->profiles; profiles; profiles = g_list_next(profiles))
458 {
460 if(pp->out_pos == pos)
461 {
465 {
470 }
471 goto end;
472 }
473 }
474
475 // profile not found, fall back to sRGB. shouldn't happen
476 fprintf(stderr, "can't find softproof profile `%s', using sRGB instead\n", dt_bauhaus_combobox_get_text(combo));
480
481end:
483 {
487 }
488}
489
491{
494
495 // the popup window, shared between the two profile buttons
496 dev->profile.floating_window = gtk_popover_new(NULL);
499 g_object_set_data(G_OBJECT(dev->profile.softproof_button), DT_DEV_TOOLBOX_POPOVER_KEY, dev->profile.floating_window);
500 g_object_set_data(G_OBJECT(dev->profile.gamut_button), DT_DEV_TOOLBOX_POPOVER_KEY, dev->profile.floating_window);
501
502 GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING);
503 gtk_container_add(GTK_CONTAINER(dev->profile.floating_window), vbox);
504
505 char datadir[PATH_MAX] = { 0 };
506 char confdir[PATH_MAX] = { 0 };
507 dt_loc_get_user_config_dir(confdir, sizeof(confdir));
508 dt_loc_get_datadir(datadir, sizeof(datadir));
509
511 dt_bauhaus_widget_set_label(softproof_profile, N_("softproof profile"));
512 dt_bauhaus_combobox_set_entries_ellipsis(softproof_profile, PANGO_ELLIPSIZE_MIDDLE);
513 gtk_box_pack_start(GTK_BOX(vbox), softproof_profile, TRUE, TRUE, 0);
514
515 for(const GList *l = darktable.color_profiles->profiles; l; l = g_list_next(l))
516 {
518 // the system display profile is only suitable for display purposes
519 if(prof->out_pos > -1)
520 {
521 dt_bauhaus_combobox_add(softproof_profile, prof->name);
524 dt_bauhaus_combobox_set(softproof_profile, prof->out_pos);
525 }
526 }
527
528 char *system_profile_dir = g_build_filename(datadir, "color", "out", NULL);
529 char *user_profile_dir = g_build_filename(confdir, "color", "out", NULL);
530 char *tooltip = g_strdup_printf(_("softproof ICC profiles in %s or %s"), user_profile_dir, system_profile_dir);
531 gtk_widget_set_tooltip_text(softproof_profile, tooltip);
533 dt_free(system_profile_dir);
534 dt_free(user_profile_dir);
535
536 g_signal_connect(G_OBJECT(softproof_profile), "value-changed", G_CALLBACK(_softproof_profile_callback), dev);
537
538 gtk_widget_show_all(vbox);
539}
540
547
548static void _display_borders_callback(GtkWidget *slider, gpointer user_data)
549{
550 dt_develop_t *dev = (dt_develop_t *)user_data;
551 dt_conf_set_int("plugins/darkroom/ui/border_size", (int)dt_bauhaus_slider_get(slider));
555}
556
558{
559 dev->display.floating_window = gtk_popover_new(dev->display.button);
561 g_object_set_data(G_OBJECT(dev->display.button), DT_DEV_TOOLBOX_POPOVER_KEY, dev->display.floating_window);
562
563 GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING);
564 gtk_widget_set_margin_bottom(vbox, DT_PIXEL_APPLY_DPI(DT_GUI_BOX_SPACING));
565 gtk_container_add(GTK_CONTAINER(dev->display.floating_window), vbox);
566
567 GtkWidget *brightness = dt_bauhaus_slider_new_with_range(darktable.bauhaus, DT_GUI_MODULE(NULL), 0, 100, 5, 50, 0);
568 dt_bauhaus_slider_set(brightness, (int)dt_conf_get_int("display/brightness"));
569 dt_bauhaus_widget_set_label(brightness, N_("Background brightness"));
570 dt_bauhaus_slider_set_format(brightness, "%");
571 g_signal_connect(G_OBJECT(brightness), "value-changed", G_CALLBACK(_display_brightness_callback), dev);
572 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(brightness), TRUE, TRUE, 0);
573
574 GtkWidget *borders = dt_bauhaus_slider_new_with_range(darktable.bauhaus, DT_GUI_MODULE(NULL), 0, 250, 5, 10, 0);
575 dt_bauhaus_slider_set(borders, dt_conf_get_int("plugins/darkroom/ui/border_size"));
576 dt_bauhaus_widget_set_label(borders, N_("Picture margins"));
577 dt_bauhaus_slider_set_format(borders, "px");
578 g_signal_connect(G_OBJECT(borders), "value-changed", G_CALLBACK(_display_borders_callback), dev);
579 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(borders), TRUE, TRUE, 0);
580
581 // Left un-shown: callers wanting view-specific extras (darkroom's rendering
582 // size and mask preview checkerboard) pack them into this same vbox and
583 // call gtk_widget_show_all() themselves once done.
584}
585
586/*
587 * Button creation.
588 */
589
591{
592 GtkWidget *button = NULL;
593 const char *tooltip = NULL;
594
595 switch(type)
596 {
599 tooltip = _("toggle ISO 12646 color assessment conditions");
600 dev->iso_12646.button = button;
601 break;
602
605 tooltip = _("toggle clipping indication\nright click for options");
606 dev->overexposed.button = button;
607 break;
608
611 tooltip = _("toggle raw over exposed indication\nright click for options");
612 dev->rawoverexposed.button = button;
613 break;
614
617 tooltip = _("toggle softproofing\nright click for profile options");
618 dev->profile.softproof_button = button;
619 break;
620
623 tooltip = _("toggle gamut checking\nright click for profile options");
624 dev->profile.gamut_button = button;
625 break;
626
629 tooltip = _("Picture display options");
630 dev->display.button = button;
631 break;
632 }
633
634 g_object_set_data(G_OBJECT(button), DT_DEV_TOOLBOX_BUTTON_TYPE_KEY, GINT_TO_POINTER(type));
635 gtk_widget_set_tooltip_text(button, tooltip);
636 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(_button_clicked), dev);
638 return button;
639}
640
642 size_t n_buttons)
643{
644 gboolean has_softproof = FALSE;
645 gboolean has_gamut = FALSE;
646
647 for(size_t i = 0; i < n_buttons; i++)
648 {
649 _create_one_button(dev, views, buttons[i]);
650 // Popover options
651 switch(buttons[i])
652 {
654 // No options popover for this one: it's a plain toggle.
655 break;
657 has_softproof = TRUE;
658 break;
660 has_gamut = TRUE;
661 break;
664 break;
667 break;
670 break;
671 }
672 }
673
674 // Both buttons exist only once both are requested in the same call.
675 if(has_softproof && has_gamut)
676 {
679 }
680}
void dt_accels_new_action_shortcut(dt_accels_t *accels, gboolean(*action_callback)(GtkAccelGroup *group, GObject *acceleratable, guint keyval, GdkModifierType mods, gpointer user_data), gpointer data, GtkAccelGroup *accel_group, const gchar *action_scope, const gchar *action_name, guint key_val, GdkModifierType accel_mods, const gboolean lock, const char *description)
Register a new shortcut for a generic action, setting up its path, default keys and accel group....
Handle default and user-set shortcuts (accelerators)
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
const char ** views(dt_lib_module_t *self)
float dt_bauhaus_slider_get(GtkWidget *widget)
Definition bauhaus.c:3486
int dt_bauhaus_combobox_get(GtkWidget *widget)
Definition bauhaus.c:2350
void dt_bauhaus_combobox_set_entries_ellipsis(GtkWidget *widget, PangoEllipsizeMode ellipis)
Definition bauhaus.c:2067
const char * dt_bauhaus_combobox_get_text(GtkWidget *widget)
Definition bauhaus.c:2165
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
Definition bauhaus.c:3537
void dt_bauhaus_combobox_set(GtkWidget *widget, const int pos)
Definition bauhaus.c:2304
void dt_bauhaus_widget_set_label(GtkWidget *widget, const char *label)
Definition bauhaus.c:1656
GtkWidget * dt_bauhaus_slider_new_with_range(dt_bauhaus_t *bh, dt_gui_module_t *self, float min, float max, float step, float defval, int digits)
Definition bauhaus.c:1783
GtkWidget * dt_bauhaus_combobox_new(dt_bauhaus_t *bh, dt_gui_module_t *self)
Definition bauhaus.c:1845
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
Definition bauhaus.c:3613
void dt_bauhaus_combobox_add(GtkWidget *widget, const char *text)
Definition bauhaus.c:2019
#define DT_BAUHAUS_COMBOBOX_NEW_FULL(bauhaus, widget, action, label, tip, pos, callback, data,...)
Definition bauhaus.h:392
GtkWidget * dtgtk_button_new(DTGTKCairoPaintIconFunc paint, gint paintflags, void *paintdata)
Definition button.c:134
static void profile_changed(GtkWidget *widget, gpointer user_data)
Definition colorin.c:511
@ DT_COLORSPACE_FILE
Definition colorspaces.h:83
@ DT_COLORSPACE_SRGB
Definition colorspaces.h:84
@ DT_COLORSPACES_PROFILE_TYPE_SOFTPROOF
Definition colorspaces.h:77
@ DT_PROFILE_GAMUTCHECK
@ DT_PROFILE_SOFTPROOF
@ DT_PROFILE_NORMAL
const float threshold
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
int type
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
void dt_control_queue_redraw_center()
request redraw of center window. This redraws the center view within a gdk critical section to preven...
Definition control.c:877
darktable_t darktable
Definition darktable.c:183
#define dt_free(ptr)
Definition darktable.h:468
#define PATH_MAX
Definition darktable.h:1179
#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:293
void dt_dev_pixelpipe_change_zoom_main(dt_develop_t *dev)
#define dt_dev_pixelpipe_resync_history_main(dev)
#define dt_dev_pixelpipe_update_history_main(dev)
static gboolean _quickbutton_press_release(GtkWidget *button, GdkEventButton *event, GtkWidget *popover)
static void _rawoverexposed_colorscheme_callback(GtkWidget *combo, gpointer user_data)
#define DT_DEV_TOOLBOX_BUTTON_TYPE_KEY
Definition dev_toolbox.c:36
static void _overexposed_lower_callback(GtkWidget *slider, gpointer user_data)
static void _build_overexposed_popover(dt_develop_t *dev)
static GtkWidget * _create_one_button(dt_develop_t *dev, dt_view_type_flags_t views, dt_dev_toolbox_button_t type)
gboolean dt_dev_toolbox_focus_accel(GtkAccelGroup *accel_group, GObject *accelerable, guint keyval, GdkModifierType modifier, gpointer data)
static void _build_display_popover(dt_develop_t *dev)
void dt_dev_toolbox_connect_popover(GtkWidget *button, GtkWidget *popover)
static void _build_softproof_gamut_popover(dt_develop_t *dev)
static void _display_brightness_callback(GtkWidget *slider, gpointer user_data)
gboolean dt_dev_toolbox_show_popup(gpointer user_data)
Definition dev_toolbox.c:72
gboolean dt_dev_toolbox_activate_accel(GtkAccelGroup *accel_group, GObject *accelerable, guint keyval, GdkModifierType modifier, gpointer data)
void dt_dev_toolbox_popover_set_preshow(GtkWidget *popover, void(*preshow)(gpointer user_data), gpointer user_data)
Definition dev_toolbox.c:66
void dt_dev_toolbox_create(dt_develop_t *dev, dt_view_type_flags_t views, const dt_dev_toolbox_button_t *buttons, size_t n_buttons)
#define DT_DEV_TOOLBOX_PRESHOW_DATA_KEY
Definition dev_toolbox.c:64
static void _rawoverexposed_threshold_callback(GtkWidget *slider, gpointer user_data)
static void _display_borders_callback(GtkWidget *slider, gpointer user_data)
static void _update_softproof_gamut_checking(dt_develop_t *dev)
void dt_dev_toolbox_apply_iso_12646_size(dt_develop_t *dev)
Definition dev_toolbox.c:38
static void _button_clicked(GtkWidget *w, gpointer user_data)
static void _overexposed_upper_callback(GtkWidget *slider, gpointer user_data)
static void _overexposed_colorscheme_callback(GtkWidget *combo, gpointer user_data)
static void _overexposed_mode_callback(GtkWidget *slider, gpointer user_data)
static void _rawoverexposed_mode_callback(GtkWidget *combo, gpointer user_data)
static void _softproof_profile_callback(GtkWidget *combo, gpointer user_data)
static void _build_rawoverexposed_popover(dt_develop_t *dev)
void dt_dev_toolbox_add_accels(dt_develop_t *dev, GtkAccelGroup *accel_group, const char *category, const dt_dev_toolbox_button_t *buttons, size_t n_buttons)
#define DT_DEV_TOOLBOX_PRESHOW_FN_KEY
Definition dev_toolbox.c:63
dt_dev_toolbox_button_t
Definition dev_toolbox.h:27
@ DT_DEV_TOOLBOX_DISPLAY
Definition dev_toolbox.h:33
@ DT_DEV_TOOLBOX_GAMUT
Definition dev_toolbox.h:32
@ DT_DEV_TOOLBOX_RAWOVEREXPOSED
Definition dev_toolbox.h:30
@ DT_DEV_TOOLBOX_OVEREXPOSED
Definition dev_toolbox.h:29
@ DT_DEV_TOOLBOX_SOFTPROOF
Definition dev_toolbox.h:31
@ DT_DEV_TOOLBOX_ISO_12646
Definition dev_toolbox.h:28
#define DT_DEV_TOOLBOX_POPOVER_KEY
#define dt_dev_configure(dev, wd, ht)
Definition develop.h:607
void dtgtk_cairo_paint_bulb(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_overexposed(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_gamut_check(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_rawoverexposed(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_softproof(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dtgtk_cairo_paint_display(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dt_loc_get_datadir(char *datadir, size_t bufsize)
void dt_loc_get_user_config_dir(char *configdir, size_t bufsize)
void dt_gui_add_help_link(GtkWidget *widget, char *link)
Definition gtk.c:2232
GtkWidget * dt_gui_get_popup_relative_widget(GtkWidget *widget, GdkRectangle *rect)
Resolve the widget used as parent for nested popups on Wayland.
Definition gtk.c:3157
#define DT_GUI_BOX_SPACING
Definition gtk.h:109
#define DT_PIXEL_APPLY_DPI(value)
Definition gtk.h:90
#define DT_GUI_MODULE(x)
const char * tooltip
Definition image.h:251
static const float x
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
Definition signal.h:366
@ DT_SIGNAL_CONTROL_PROFILE_USER_CHANGED
This signal is raised when a profile is changed by the user 1 uint32_t : the profile type that has ch...
Definition signal.h:242
@ DT_SIGNAL_DARKROOM_UI_CHANGED
Signal that the darkroom GUI color changed.
Definition signal.h:224
struct _GtkWidget GtkWidget
Definition splash.h:29
struct dt_gui_gtk_t * gui
Definition darktable.h:793
struct dt_colorspaces_t * color_profiles
Definition darktable.h:806
struct dt_control_signal_t * signals
Definition darktable.h:792
struct dt_bauhaus_t * bauhaus
Definition darktable.h:796
struct dt_view_manager_t * view_manager
Definition darktable.h:790
dt_colorspaces_color_profile_type_t type
dt_colorspaces_color_profile_type_t softproof_type
dt_colorspaces_color_mode_t mode
char softproof_filename[512]
int32_t gui_attached
Definition develop.h:162
int32_t orig_height
Definition develop.h:205
struct dt_develop_t::@19 roi
int32_t border_size
Definition develop.h:200
struct dt_develop_t::@23 overexposed
dt_clipping_preview_mode_t mode
Definition develop.h:461
struct dt_develop_t::@25 display
int32_t orig_width
Definition develop.h:205
GtkWidget * floating_window
Definition develop.h:455
float lower
Definition develop.h:459
dt_dev_overexposed_colorscheme_t colorscheme
Definition develop.h:458
struct dt_develop_t::@27 profile
struct dt_develop_t::@26 iso_12646
GtkWidget * button
Definition develop.h:455
GtkWidget * gamut_button
Definition develop.h:493
gboolean enabled
Definition develop.h:393
float threshold
Definition develop.h:472
float upper
Definition develop.h:460
GtkWidget * softproof_button
Definition develop.h:493
struct dt_develop_t::@24 rawoverexposed
dt_accels_t * accels
Definition gtk.h:199
double x
double y
#define MIN(a, b)
Definition thinplate.c:32
GtkWidget * dtgtk_togglebutton_new(DTGTKCairoPaintIconFunc paint, gint paintflags, void *paintdata)
char * dt_get_help_url(char *name)
void dt_view_manager_module_toolbox_add(dt_view_manager_t *vm, GtkWidget *tool, dt_view_type_flags_t views)
Definition view.c:1357
dt_view_type_flags_t
Definition view.h:76