1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * gimpprogress.c
5  * Copyright (C) 2004  Michael Natterer <mitch@gimp.org>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  */
20 
21 #include "config.h"
22 
23 #include <string.h>
24 
25 #include <gio/gio.h>
26 #include <gegl.h>
27 
28 #include "core-types.h"
29 
30 #include "gimp.h"
31 #include "gimpmarshal.h"
32 #include "gimpprogress.h"
33 
34 #include "gimp-intl.h"
35 
36 
37 enum
38 {
39   CANCEL,
40   LAST_SIGNAL
41 };
42 
43 
44 G_DEFINE_INTERFACE (GimpProgress, gimp_progress, G_TYPE_OBJECT)
45 
46 
47 static guint progress_signals[LAST_SIGNAL] = { 0 };
48 
49 
50 /*  private functions  */
51 
52 
53 static void
gimp_progress_default_init(GimpProgressInterface * progress_iface)54 gimp_progress_default_init (GimpProgressInterface *progress_iface)
55 {
56   progress_signals[CANCEL] =
57     g_signal_new ("cancel",
58                   G_TYPE_FROM_INTERFACE (progress_iface),
59                   G_SIGNAL_RUN_FIRST,
60                   G_STRUCT_OFFSET (GimpProgressInterface, cancel),
61                   NULL, NULL,
62                   gimp_marshal_VOID__VOID,
63                   G_TYPE_NONE, 0);
64 }
65 
66 
67 /*  public functions  */
68 
69 
70 GimpProgress *
gimp_progress_start(GimpProgress * progress,gboolean cancellable,const gchar * format,...)71 gimp_progress_start (GimpProgress *progress,
72                      gboolean      cancellable,
73                      const gchar  *format,
74                      ...)
75 {
76   GimpProgressInterface *progress_iface;
77 
78   g_return_val_if_fail (GIMP_IS_PROGRESS (progress), NULL);
79   g_return_val_if_fail (format != NULL, NULL);
80 
81   progress_iface = GIMP_PROGRESS_GET_INTERFACE (progress);
82 
83   if (progress_iface->start)
84     {
85       GimpProgress *ret;
86       va_list       args;
87       gchar        *text;
88 
89       va_start (args, format);
90       text = g_strdup_vprintf (format, args);
91       va_end (args);
92 
93       ret = progress_iface->start (progress, cancellable, text);
94 
95       g_free (text);
96 
97       return ret;
98     }
99 
100   return NULL;
101 }
102 
103 void
gimp_progress_end(GimpProgress * progress)104 gimp_progress_end (GimpProgress *progress)
105 {
106   GimpProgressInterface *progress_iface;
107 
108   g_return_if_fail (GIMP_IS_PROGRESS (progress));
109 
110   progress_iface = GIMP_PROGRESS_GET_INTERFACE (progress);
111 
112   if (progress_iface->end)
113     progress_iface->end (progress);
114 }
115 
116 gboolean
gimp_progress_is_active(GimpProgress * progress)117 gimp_progress_is_active (GimpProgress *progress)
118 {
119   GimpProgressInterface *progress_iface;
120 
121   g_return_val_if_fail (GIMP_IS_PROGRESS (progress), FALSE);
122 
123   progress_iface = GIMP_PROGRESS_GET_INTERFACE (progress);
124 
125   if (progress_iface->is_active)
126     return progress_iface->is_active (progress);
127 
128   return FALSE;
129 }
130 
131 void
gimp_progress_set_text(GimpProgress * progress,const gchar * format,...)132 gimp_progress_set_text (GimpProgress *progress,
133                         const gchar  *format,
134                         ...)
135 {
136   va_list  args;
137   gchar   *message;
138 
139   g_return_if_fail (GIMP_IS_PROGRESS (progress));
140   g_return_if_fail (format != NULL);
141 
142   va_start (args, format);
143   message = g_strdup_vprintf (format, args);
144   va_end (args);
145 
146   gimp_progress_set_text_literal (progress, message);
147 
148   g_free (message);
149 }
150 
151 void
gimp_progress_set_text_literal(GimpProgress * progress,const gchar * message)152 gimp_progress_set_text_literal (GimpProgress *progress,
153                                 const gchar  *message)
154 {
155   GimpProgressInterface *progress_iface;
156 
157   g_return_if_fail (GIMP_IS_PROGRESS (progress));
158   g_return_if_fail (message != NULL);
159 
160   progress_iface = GIMP_PROGRESS_GET_INTERFACE (progress);
161 
162   if (progress_iface->set_text)
163     progress_iface->set_text (progress, message);
164 }
165 
166 void
gimp_progress_set_value(GimpProgress * progress,gdouble percentage)167 gimp_progress_set_value (GimpProgress *progress,
168                          gdouble       percentage)
169 {
170   GimpProgressInterface *progress_iface;
171 
172   g_return_if_fail (GIMP_IS_PROGRESS (progress));
173 
174   percentage = CLAMP (percentage, 0.0, 1.0);
175 
176   progress_iface = GIMP_PROGRESS_GET_INTERFACE (progress);
177 
178   if (progress_iface->set_value)
179     progress_iface->set_value (progress, percentage);
180 }
181 
182 gdouble
gimp_progress_get_value(GimpProgress * progress)183 gimp_progress_get_value (GimpProgress *progress)
184 {
185   GimpProgressInterface *progress_iface;
186 
187   g_return_val_if_fail (GIMP_IS_PROGRESS (progress), 0.0);
188 
189   progress_iface = GIMP_PROGRESS_GET_INTERFACE (progress);
190 
191   if (progress_iface->get_value)
192     return progress_iface->get_value (progress);
193 
194   return 0.0;
195 }
196 
197 void
gimp_progress_pulse(GimpProgress * progress)198 gimp_progress_pulse (GimpProgress *progress)
199 {
200   GimpProgressInterface *progress_iface;
201 
202   g_return_if_fail (GIMP_IS_PROGRESS (progress));
203 
204   progress_iface = GIMP_PROGRESS_GET_INTERFACE (progress);
205 
206   if (progress_iface->pulse)
207     progress_iface->pulse (progress);
208 }
209 
210 guint32
gimp_progress_get_window_id(GimpProgress * progress)211 gimp_progress_get_window_id (GimpProgress *progress)
212 {
213   GimpProgressInterface *progress_iface;
214 
215   g_return_val_if_fail (GIMP_IS_PROGRESS (progress), 0);
216 
217   progress_iface = GIMP_PROGRESS_GET_INTERFACE (progress);
218 
219   if (progress_iface->get_window_id)
220     return progress_iface->get_window_id (progress);
221 
222   return 0;
223 }
224 
225 gboolean
gimp_progress_message(GimpProgress * progress,Gimp * gimp,GimpMessageSeverity severity,const gchar * domain,const gchar * message)226 gimp_progress_message (GimpProgress        *progress,
227                        Gimp                *gimp,
228                        GimpMessageSeverity  severity,
229                        const gchar         *domain,
230                        const gchar         *message)
231 {
232   GimpProgressInterface *progress_iface;
233 
234   g_return_val_if_fail (GIMP_IS_PROGRESS (progress), FALSE);
235   g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
236   g_return_val_if_fail (domain != NULL, FALSE);
237   g_return_val_if_fail (message != NULL, FALSE);
238 
239   progress_iface = GIMP_PROGRESS_GET_INTERFACE (progress);
240 
241   if (progress_iface->message)
242     return progress_iface->message (progress, gimp, severity, domain, message);
243 
244   return FALSE;
245 }
246 
247 void
gimp_progress_cancel(GimpProgress * progress)248 gimp_progress_cancel (GimpProgress *progress)
249 {
250   g_return_if_fail (GIMP_IS_PROGRESS (progress));
251 
252   g_signal_emit (progress, progress_signals[CANCEL], 0);
253 }
254 
255 void
gimp_progress_update_and_flush(gint min,gint max,gint current,gpointer data)256 gimp_progress_update_and_flush (gint     min,
257                                 gint     max,
258                                 gint     current,
259                                 gpointer data)
260 {
261   gimp_progress_set_value (GIMP_PROGRESS (data),
262                            (gdouble) (current - min) / (gdouble) (max - min));
263 
264   while (g_main_context_pending (NULL))
265     g_main_context_iteration (NULL, TRUE);
266 }
267