1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16  */
17 
18 #include "config.h"
19 
20 #include <glib-object.h>
21 
22 #include "core-types.h"
23 
24 #include "core/gimpsubprogress.h"
25 #include "core/gimpprogress.h"
26 
27 
28 enum
29 {
30   PROP_0,
31   PROP_PROGRESS
32 };
33 
34 
35 static void           gimp_sub_progress_iface_init    (GimpProgressInterface *iface);
36 
37 static void           gimp_sub_progress_finalize      (GObject             *object);
38 static void           gimp_sub_progress_set_property  (GObject             *object,
39                                                        guint                property_id,
40                                                        const GValue        *value,
41                                                        GParamSpec          *pspec);
42 static void           gimp_sub_progress_get_property  (GObject             *object,
43                                                        guint                property_id,
44                                                        GValue              *value,
45                                                        GParamSpec          *pspec);
46 
47 static GimpProgress * gimp_sub_progress_start         (GimpProgress        *progress,
48                                                        gboolean             cancellable,
49                                                        const gchar         *message);
50 static void           gimp_sub_progress_end           (GimpProgress        *progress);
51 static gboolean       gimp_sub_progress_is_active     (GimpProgress        *progress);
52 static void           gimp_sub_progress_set_text      (GimpProgress        *progress,
53                                                        const gchar         *message);
54 static void           gimp_sub_progress_set_value     (GimpProgress        *progress,
55                                                        gdouble              percentage);
56 static gdouble        gimp_sub_progress_get_value     (GimpProgress        *progress);
57 static void           gimp_sub_progress_pulse         (GimpProgress        *progress);
58 static guint32        gimp_sub_progress_get_window_id (GimpProgress        *progress);
59 static gboolean       gimp_sub_progress_message       (GimpProgress        *progress,
60                                                        Gimp                *gimp,
61                                                        GimpMessageSeverity  severity,
62                                                        const gchar         *domain,
63                                                        const gchar         *message);
64 
65 
G_DEFINE_TYPE_WITH_CODE(GimpSubProgress,gimp_sub_progress,G_TYPE_OBJECT,G_IMPLEMENT_INTERFACE (GIMP_TYPE_PROGRESS,gimp_sub_progress_iface_init))66 G_DEFINE_TYPE_WITH_CODE (GimpSubProgress, gimp_sub_progress, G_TYPE_OBJECT,
67                          G_IMPLEMENT_INTERFACE (GIMP_TYPE_PROGRESS,
68                                                 gimp_sub_progress_iface_init))
69 
70 #define parent_class gimp_sub_progress_parent_class
71 
72 
73 static void
74 gimp_sub_progress_class_init (GimpSubProgressClass *klass)
75 {
76   GObjectClass *object_class = G_OBJECT_CLASS (klass);
77 
78   object_class->finalize     = gimp_sub_progress_finalize;
79   object_class->set_property = gimp_sub_progress_set_property;
80   object_class->get_property = gimp_sub_progress_get_property;
81 
82   g_object_class_install_property (object_class, PROP_PROGRESS,
83                                    g_param_spec_object ("progress",
84                                                         NULL, NULL,
85                                                         GIMP_TYPE_PROGRESS,
86                                                         G_PARAM_READWRITE |
87                                                         G_PARAM_CONSTRUCT_ONLY));
88 }
89 
90 static void
gimp_sub_progress_init(GimpSubProgress * sub)91 gimp_sub_progress_init (GimpSubProgress *sub)
92 {
93   sub->progress = NULL;
94   sub->start    = 0.0;
95   sub->end      = 1.0;
96 }
97 
98 static void
gimp_sub_progress_finalize(GObject * object)99 gimp_sub_progress_finalize (GObject *object)
100 {
101   GimpSubProgress *sub = GIMP_SUB_PROGRESS (object);
102 
103   g_clear_object (&sub->progress);
104 
105   G_OBJECT_CLASS (parent_class)->finalize (object);
106 }
107 
108 static void
gimp_sub_progress_iface_init(GimpProgressInterface * iface)109 gimp_sub_progress_iface_init (GimpProgressInterface *iface)
110 {
111   iface->start         = gimp_sub_progress_start;
112   iface->end           = gimp_sub_progress_end;
113   iface->is_active     = gimp_sub_progress_is_active;
114   iface->set_text      = gimp_sub_progress_set_text;
115   iface->set_value     = gimp_sub_progress_set_value;
116   iface->get_value     = gimp_sub_progress_get_value;
117   iface->pulse         = gimp_sub_progress_pulse;
118   iface->get_window_id = gimp_sub_progress_get_window_id;
119   iface->message       = gimp_sub_progress_message;
120 }
121 
122 static void
gimp_sub_progress_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)123 gimp_sub_progress_set_property (GObject      *object,
124                                 guint         property_id,
125                                 const GValue *value,
126                                 GParamSpec   *pspec)
127 {
128   GimpSubProgress *sub = GIMP_SUB_PROGRESS (object);
129 
130   switch (property_id)
131     {
132     case PROP_PROGRESS:
133       g_return_if_fail (sub->progress == NULL);
134       sub->progress = g_value_dup_object (value);
135       break;
136 
137     default:
138       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
139       break;
140     }
141 }
142 
143 static void
gimp_sub_progress_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)144 gimp_sub_progress_get_property (GObject    *object,
145                                 guint       property_id,
146                                 GValue     *value,
147                                 GParamSpec *pspec)
148 {
149   GimpSubProgress *sub = GIMP_SUB_PROGRESS (object);
150 
151   switch (property_id)
152     {
153     case PROP_PROGRESS:
154       g_value_set_object (value, sub->progress);
155       break;
156 
157     default:
158       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
159       break;
160     }
161 }
162 
163 static GimpProgress *
gimp_sub_progress_start(GimpProgress * progress,gboolean cancellable,const gchar * message)164 gimp_sub_progress_start (GimpProgress *progress,
165                          gboolean      cancellable,
166                          const gchar  *message)
167 {
168   /* does nothing */
169   return NULL;
170 }
171 
172 static void
gimp_sub_progress_end(GimpProgress * progress)173 gimp_sub_progress_end (GimpProgress *progress)
174 {
175   /* does nothing */
176 }
177 
178 static gboolean
gimp_sub_progress_is_active(GimpProgress * progress)179 gimp_sub_progress_is_active (GimpProgress *progress)
180 {
181   GimpSubProgress *sub = GIMP_SUB_PROGRESS (progress);
182 
183   if (sub->progress)
184     return gimp_progress_is_active (sub->progress);
185 
186   return FALSE;
187 }
188 
189 static void
gimp_sub_progress_set_text(GimpProgress * progress,const gchar * message)190 gimp_sub_progress_set_text (GimpProgress *progress,
191                             const gchar  *message)
192 {
193   /* does nothing */
194 }
195 
196 static void
gimp_sub_progress_set_value(GimpProgress * progress,gdouble percentage)197 gimp_sub_progress_set_value (GimpProgress *progress,
198                              gdouble       percentage)
199 {
200   GimpSubProgress *sub = GIMP_SUB_PROGRESS (progress);
201 
202   if (sub->progress)
203     gimp_progress_set_value (sub->progress,
204                              sub->start + percentage * (sub->end - sub->start));
205 }
206 
207 static gdouble
gimp_sub_progress_get_value(GimpProgress * progress)208 gimp_sub_progress_get_value (GimpProgress *progress)
209 {
210   GimpSubProgress *sub = GIMP_SUB_PROGRESS (progress);
211 
212   if (sub->progress)
213     return gimp_progress_get_value (sub->progress);
214 
215   return 0.0;
216 }
217 
218 static void
gimp_sub_progress_pulse(GimpProgress * progress)219 gimp_sub_progress_pulse (GimpProgress *progress)
220 {
221   GimpSubProgress *sub = GIMP_SUB_PROGRESS (progress);
222 
223   if (sub->progress)
224     gimp_progress_pulse (sub->progress);
225 }
226 
227 static guint32
gimp_sub_progress_get_window_id(GimpProgress * progress)228 gimp_sub_progress_get_window_id (GimpProgress *progress)
229 {
230   GimpSubProgress *sub = GIMP_SUB_PROGRESS (progress);
231 
232   if (sub->progress)
233     return gimp_progress_get_window_id (sub->progress);
234 
235   return 0;
236 }
237 
238 static gboolean
gimp_sub_progress_message(GimpProgress * progress,Gimp * gimp,GimpMessageSeverity severity,const gchar * domain,const gchar * message)239 gimp_sub_progress_message (GimpProgress        *progress,
240                            Gimp                *gimp,
241                            GimpMessageSeverity  severity,
242                            const gchar         *domain,
243                            const gchar         *message)
244 {
245   GimpSubProgress *sub = GIMP_SUB_PROGRESS (progress);
246 
247   if (sub->progress)
248     return gimp_progress_message (sub->progress,
249                                   gimp, severity, domain, message);
250 
251   return FALSE;
252 }
253 
254 /**
255  * gimp_sub_progress_new:
256  * @progress: parent progress or %NULL
257  *
258  * GimpSubProgress implements the GimpProgress interface and can be
259  * used wherever a GimpProgress is needed. It maps progress
260  * information to a sub-range of its parent @progress. This is useful
261  * when an action breaks down into multiple sub-actions that itself
262  * need a #GimpProgress pointer. See gimp_image_scale() for an example.
263  *
264  * Return value: a new #GimpProgress object
265  */
266 GimpProgress *
gimp_sub_progress_new(GimpProgress * progress)267 gimp_sub_progress_new (GimpProgress *progress)
268 {
269   GimpSubProgress *sub;
270 
271   g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);
272 
273   sub = g_object_new (GIMP_TYPE_SUB_PROGRESS,
274                       "progress", progress,
275                       NULL);
276 
277   return GIMP_PROGRESS (sub);
278 }
279 
280 /**
281  * gimp_sub_progress_set_range:
282  * @start: start value of range on the parent process
283  * @end:   end value of range on the parent process
284  *
285  * Sets a range on the parent progress that this @progress should be
286  * mapped to.
287  */
288 void
gimp_sub_progress_set_range(GimpSubProgress * progress,gdouble start,gdouble end)289 gimp_sub_progress_set_range (GimpSubProgress *progress,
290                              gdouble          start,
291                              gdouble          end)
292 {
293   g_return_if_fail (GIMP_IS_SUB_PROGRESS (progress));
294   g_return_if_fail (start < end);
295 
296   progress->start = start;
297   progress->end   = end;
298 }
299 
300 /**
301  * gimp_sub_progress_set_step:
302  * @index:     step index
303  * @num_steps: number of steps
304  *
305  * A more convenient form of gimp_sub_progress_set_range().
306  */
307 void
gimp_sub_progress_set_step(GimpSubProgress * progress,gint index,gint num_steps)308 gimp_sub_progress_set_step (GimpSubProgress *progress,
309                             gint             index,
310                             gint             num_steps)
311 {
312   g_return_if_fail (GIMP_IS_SUB_PROGRESS (progress));
313   g_return_if_fail (index < num_steps && num_steps > 0);
314 
315   progress->start = (gdouble) index / num_steps;
316   progress->end   = (gdouble) (index + 1) / num_steps;
317 }
318