Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
dialog.c
Go to the documentation of this file.
1/*
2 * This file is part of Ansel,
3 * Copyright (C) 2026 Aurélien PIERRE.
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 * You should have received a copy of the GNU General Public License
16 * along with Ansel. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "widgets/dialog.h"
20
21#include "widgets/accelerators.h" // dt_accels_disable around a modal text entry
22#include "widgets/widget_settings.h" // DT_GUI_BOX_SPACING, DT_PIXEL_APPLY_DPI, root window
23#include "system/mem_alloc.h"
24
25#ifdef GDK_WINDOWING_QUARTZ
26#include "osx/osx.h"
27#endif
28
35
41
42static void _gtk_main_quit_safe(GtkWidget *widget, gpointer data)
43{
44 (void)widget;
45 (void)data;
46 if(gtk_main_level() > 0) gtk_main_quit();
47}
48
49static void _yes_no_button_handler(GtkButton *button, gpointer data)
50{
51 result_t *result = (result_t *)data;
52
53 if((void *)button == (void *)result->button_yes)
54 result->result = RESULT_YES;
55 else if((void *)button == (void *)result->button_no)
56 result->result = RESULT_NO;
57
58 if(result->entry)
62}
63
65{
66 if(!GTK_IS_WINDOW(parent))
67 {
68 GtkWidget *main_window = dt_widget_root_window();
69 if(GTK_IS_WINDOW(main_window)) parent = GTK_WINDOW(main_window);
70 }
71
72 if(GTK_IS_WINDOW(parent)) gtk_window_present(parent);
73
74#ifdef GDK_WINDOWING_QUARTZ
76#endif
77}
78
79gboolean dt_gui_show_standalone_yes_no_dialog(const char *title, const char *markup, const char *no_text,
80 const char *yes_text)
81{
83#ifdef GDK_WINDOWING_QUARTZ
85#endif
86
87 // before the CSS theme is loaded there is no styling at all, so pad by hand
88 const int padding = dt_widget_theme_loaded() ? 0 : 5;
89
93
95
96 {
97 GtkWidget *main_window = dt_widget_root_window();
98 if(GTK_IS_WINDOW(main_window))
99 {
100 GtkWindow *win = GTK_WINDOW(main_window);
104 {
106 }
107 }
108 }
109
112
114 gtk_box_pack_start(GTK_BOX(vbox), mhbox, TRUE, TRUE, padding);
115
116 if(padding)
117 {
120 }
121
122 GtkWidget *label = gtk_label_new(NULL);
124 gtk_box_pack_start(GTK_BOX(mhbox), label, TRUE, TRUE, padding);
125
126 if(padding)
127 {
130 }
131
133 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
134
135 result_t result = {.result = RESULT_NONE, .window = window};
136
137 GtkWidget *button;
138
139 if(no_text)
140 {
142 result.button_no = button;
143 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(_yes_no_button_handler), &result);
144 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
145 }
146
147 if(yes_text)
148 {
150 result.button_yes = button;
151 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(_yes_no_button_handler), &result);
152 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
153 }
154
156 gtk_main();
157
158 return result.result == RESULT_YES;
159}
160
161static void _three_choice_button_handler(GtkButton *button, gpointer data)
162{
164
165 if((void *)button == (void *)result->button_first)
166 result->result = 0;
167 else if((void *)button == (void *)result->button_second)
168 result->result = 1;
169 else if((void *)button == (void *)result->button_third)
170 result->result = 2;
171
172 gtk_widget_destroy(result->window);
174}
175
176int dt_gui_show_standalone_three_choice_dialog(const char *title, const char *markup, const char *first_text,
177 const char *second_text, const char *third_text)
178{
180#ifdef GDK_WINDOWING_QUARTZ
182#endif
183
184 // before the CSS theme is loaded there is no styling at all, so pad by hand
185 const int padding = dt_widget_theme_loaded() ? 0 : 5;
186
190
192
193 {
194 GtkWidget *main_window = dt_widget_root_window();
195 if(GTK_IS_WINDOW(main_window))
196 {
197 GtkWindow *win = GTK_WINDOW(main_window);
201 {
203 }
204 }
205 }
206
209
211 gtk_box_pack_start(GTK_BOX(vbox), mhbox, TRUE, TRUE, padding);
212
213 if(padding)
214 {
217 }
218
219 GtkWidget *label = gtk_label_new(NULL);
221 gtk_box_pack_start(GTK_BOX(mhbox), label, TRUE, TRUE, padding);
222
223 if(padding)
224 {
227 }
228
230 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
231
232 _three_choice_result_t result = { .result = -1, .window = window };
233
234 GtkWidget *button;
235
236 if(first_text)
237 {
239 result.button_first = button;
241 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
242 }
243
244 if(second_text)
245 {
247 result.button_second = button;
249 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
250 }
251
252 if(third_text)
253 {
255 result.button_third = button;
257 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
258 }
259
261 gtk_main();
262
263 return result.result;
264}
265
266char *dt_gui_show_standalone_string_dialog(const char *title, const char *markup, const char *placeholder,
267 const char *no_text, const char *yes_text)
268{
270#ifdef GDK_WINDOWING_QUARTZ
272#endif
273
277
279
280 {
281 GtkWidget *main_window = dt_widget_root_window();
282 if(GTK_IS_WINDOW(main_window))
283 {
284 GtkWindow *win = GTK_WINDOW(main_window);
287 {
289 }
290 }
291 }
292
299
300 GtkWidget *label = gtk_label_new(NULL);
302 gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
303
304 GtkWidget *entry = gtk_entry_new();
306
307 g_object_ref(entry);
308 if(placeholder)
309 gtk_entry_set_placeholder_text(GTK_ENTRY(entry), placeholder);
310 gtk_box_pack_start(GTK_BOX(vbox), entry, TRUE, TRUE, 0);
311
314 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
315
316 result_t result = {.result = RESULT_NONE, .window = window, .entry = entry};
317
318 GtkWidget *button;
319
320 if(no_text)
321 {
323 result.button_no = button;
324 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(_yes_no_button_handler), &result);
325 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
326 }
327
328 if(yes_text)
329 {
331 result.button_yes = button;
332 g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(_yes_no_button_handler), &result);
333 gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
334 }
335
337 gtk_main();
338
339 if(result.result == RESULT_YES)
340 return result.entry_text;
341
342 dt_free(result.entry_text);
343 return NULL;
344}
345
346// clang-format off
347// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
348// vim: shiftwidth=2 expandtab tabstop=2 cindent
349// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
350// 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....
Handle default and user-set shortcuts (accelerators)
#define TRUE
Definition ashift_lsd.c:162
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
Definition colorspaces.h:98
static void _three_choice_button_handler(GtkButton *button, gpointer data)
Definition dialog.c:161
static void _gtk_main_quit_safe(GtkWidget *widget, gpointer data)
Definition dialog.c:42
char * dt_gui_show_standalone_string_dialog(const char *title, const char *markup, const char *placeholder, const char *no_text, const char *yes_text)
Definition dialog.c:266
int dt_gui_show_standalone_three_choice_dialog(const char *title, const char *markup, const char *first_text, const char *second_text, const char *third_text)
Definition dialog.c:176
static void _yes_no_button_handler(GtkButton *button, gpointer data)
Definition dialog.c:49
gboolean dt_gui_show_standalone_yes_no_dialog(const char *title, const char *markup, const char *no_text, const char *yes_text)
Definition dialog.c:79
void dt_gui_refocus_parent(GtkWindow *parent)
Definition dialog.c:64
#define dt_free(ptr)
Definition mem_alloc.h:97
void dt_osx_focus_window()
Definition osx.mm:302
void dt_osx_disallow_fullscreen(GtkWidget *widget)
Definition osx.mm:105
GtkWidget * button_first
Definition dialog.c:39
GtkWidget * button_third
Definition dialog.c:39
GtkWidget * button_second
Definition dialog.c:39
GtkWidget * window
Definition dialog.c:39
enum result_t::@67 result
GtkWidget * button_yes
Definition dialog.c:33
char * entry_text
Definition dialog.c:32
GtkWidget * entry
Definition dialog.c:33
GtkWidget * button_no
Definition dialog.c:33
@ RESULT_NO
Definition dialog.c:31
@ RESULT_YES
Definition dialog.c:31
@ RESULT_NONE
Definition dialog.c:31
GtkWidget * window
Definition dialog.c:33
GtkWidget * window
GtkWidget * dt_widget_root_window(void)
gboolean dt_widget_theme_loaded(void)
#define DT_GUI_BOX_SPACING