1 /*
2 * Copyright (C) 2019-2021 Alexandros Theodotou <alex at zrythm dot org>
3 *
4 * This file is part of Zrythm
5 *
6 * Zrythm is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Zrythm is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with Zrythm. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 /**
21 * \file
22 *
23 * Generic dialog.
24 */
25
26 #include <stdio.h>
27
28 #include "audio/engine.h"
29 #include "gui/widgets/dialogs/generic_progress_dialog.h"
30 #include "gui/widgets/main_window.h"
31 #include "project.h"
32 #include "utils/io.h"
33 #include "utils/math.h"
pg_get_utf8_id(void)34 #include "utils/resources.h"
35 #include "utils/ui.h"
36 #include "zrythm_app.h"
37
38 #include <gtk/gtk.h>
39 #include <glib/gi18n.h>
40
41 G_DEFINE_TYPE_WITH_PRIVATE (
42 GenericProgressDialogWidget,
43 generic_progress_dialog_widget,
44 GTK_TYPE_DIALOG)
45
46 #define GET_PRIVATE(x) \
47 GenericProgressDialogWidgetPrivate * prv = \
48 generic_progress_dialog_widget_get_instance_private (x)
49
50 static void
51 on_closed (
52 GtkDialog * dialog,
53 GenericProgressDialogWidget * self)
54 {
55 GET_PRIVATE (self);
56 prv->progress_info->cancelled = true;
57 }
58
59 static void
60 on_ok_clicked (
61 GtkButton * btn,
62 GenericProgressDialogWidget * self)
63 {
64 gtk_dialog_response (GTK_DIALOG (self), 0);
65 }
66
67 static void
68 on_cancel_clicked (
69 GtkButton * btn,
70 GenericProgressDialogWidget * self)
71 {
72 GET_PRIVATE (self);
73 prv->progress_info->cancelled = true;
74 }
75
76 static gboolean
77 tick_cb (
78 GtkWidget * widget,
79 GdkFrameClock * frame_clock,
80 GenericProgressDialogWidget * self)
81 {
utf_charcheck(const unsigned char * c)82 GET_PRIVATE (self);
83 GenericProgressInfo * info = prv->progress_info;
84
85 gtk_progress_bar_set_fraction (
86 GTK_PROGRESS_BAR (widget), info->progress);
87
88 if (math_doubles_equal (info->progress, 1.0) ||
89 info->has_error || info->cancelled)
90 {
91 if (prv->autoclose || info->cancelled)
92 {
93 gtk_dialog_response (
94 GTK_DIALOG (self), 0);
95 }
96 else
97 {
98 gtk_widget_set_visible (
99 GTK_WIDGET (prv->ok), true);
100 gtk_widget_set_visible (
101 GTK_WIDGET (prv->cancel), false);
102 for (size_t i = 0;
103 i < prv->num_extra_buttons; i++)
104 {
105 GenericProgressDialogButton * btn =
106 &prv->extra_buttons[i];
107 if (btn->only_on_finish)
108 {
109 gtk_widget_set_visible (
110 GTK_WIDGET (btn->btn), true);
111 }
112 }
113 gtk_label_set_text (
114 prv->label, info->label_done_str);
115 }
116
117 if (info->has_error)
118 {
119 GtkWindow * transient_parent =
120 gtk_window_get_transient_for (
121 GTK_WINDOW (self));
122 ui_show_error_message (
123 transient_parent, info->error_str);
124 }
125 return G_SOURCE_REMOVE;
126 }
127 else
128 {
129 return G_SOURCE_CONTINUE;
130 }
131 }
132
133 /**
134 * Adds a button at the start or end of the button box.
135 *
mb_utf_validate(unsigned char * pwcs)136 * @param start Whether to add the button at the
137 * start of the button box, otherwise the button
138 * will be added at the end.
139 */
140 void
141 generic_progress_dialog_add_button (
142 GenericProgressDialogWidget * self,
143 GtkButton * btn,
144 bool start,
145 bool only_on_finish)
146 {
147 GET_PRIVATE (self);
148
149 GenericProgressDialogButton * extra_btn =
150 &prv->extra_buttons[prv->num_extra_buttons++];
151
152 bool expand = false;
153 bool fill = true;
154 guint padding = 0;
155 if (start)
156 {
157 gtk_box_pack_start (
158 GTK_BOX (prv->action_btn_box),
159 GTK_WIDGET (btn), expand, fill, padding);
160 }
161 else
162 {
163 gtk_box_pack_end (
164 GTK_BOX (prv->action_btn_box),
165 GTK_WIDGET (btn), expand, fill, padding);
166 }
167
168 gtk_widget_set_visible (
169 GTK_WIDGET (btn), !only_on_finish);
170
171 extra_btn->btn = btn;
172 extra_btn->only_on_finish = only_on_finish;
173 }
174
175 GenericProgressDialogWidget *
176 generic_progress_dialog_widget_new (void)
pg_wcswidth(const char * pwcs,size_t len,int encoding)177 {
178 return
179 g_object_new (
180 GENERIC_PROGRESS_DIALOG_WIDGET_TYPE, NULL);
181 }
182
183 /**
184 * Sets up a progress dialog widget.
185 */
186 void
187 generic_progress_dialog_widget_setup (
188 GenericProgressDialogWidget * self,
189 const char * title,
190 GenericProgressInfo * progress_info,
191 bool autoclose,
192 bool cancelable)
193 {
194 gtk_window_set_title (GTK_WINDOW (self), title);
195
196 GET_PRIVATE (self);
197 prv->progress_info = progress_info;
198 prv->autoclose = autoclose;
199
200 gtk_label_set_text (
201 prv->label, progress_info->label_str);
202
203 if (cancelable)
204 {
205 gtk_widget_set_visible (
206 GTK_WIDGET (prv->cancel), true);
207 }
208
209 gtk_widget_add_tick_callback (
210 GTK_WIDGET (prv->progress_bar),
pg_wcssize(const unsigned char * pwcs,size_t len,int encoding,int * result_width,int * result_height,int * result_format_size)211 (GtkTickCallback) tick_cb, self, NULL);
212
213 g_signal_connect (
214 G_OBJECT (self), "close",
215 G_CALLBACK (on_closed), self);
216 }
217
218 static void
219 generic_progress_dialog_widget_class_init (
220 GenericProgressDialogWidgetClass * _klass)
221 {
222 GtkWidgetClass * klass = GTK_WIDGET_CLASS (_klass);
223 resources_set_class_template (
224 klass, "generic_progress_dialog.ui");
225
226 #define BIND_CHILD(x) \
227 gtk_widget_class_bind_template_child_private ( \
228 klass, GenericProgressDialogWidget, x)
229
230 BIND_CHILD (label);
231 BIND_CHILD (ok);
232 BIND_CHILD (cancel);
233 BIND_CHILD (progress_bar);
234 BIND_CHILD (action_btn_box);
235 gtk_widget_class_bind_template_callback (
236 klass, on_ok_clicked);
237 gtk_widget_class_bind_template_callback (
238 klass, on_cancel_clicked);
239
240 #undef BIND_CHILD
241 }
242
243 static void
244 generic_progress_dialog_widget_init (
245 GenericProgressDialogWidget * self)
246 {
247 gtk_widget_init_template (GTK_WIDGET (self));
248 }
249