1 /*
2  * Nautilus
3  *
4  * Copyright (C) 2011 Red Hat, Inc.
5  *
6  * Nautilus is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * Nautilus 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 GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public
17  * License along with this program; see the file COPYING.  If not,
18  * see <http://www.gnu.org/licenses/>.
19  *
20  * Author: Cosimo Cecchi <cosimoc@redhat.com>
21  */
22 
23 #include <config.h>
24 
25 #include "nautilus-progress-info-manager.h"
26 
27 struct _NautilusProgressInfoManager
28 {
29     GObject parent_instance;
30 
31     GList *progress_infos;
32     GList *current_viewers;
33 };
34 
35 enum
36 {
37     NEW_PROGRESS_INFO,
38     HAS_VIEWERS_CHANGED,
39     LAST_SIGNAL
40 };
41 
42 static NautilusProgressInfoManager *singleton = NULL;
43 
44 static guint signals[LAST_SIGNAL] = { 0, };
45 
46 G_DEFINE_TYPE (NautilusProgressInfoManager, nautilus_progress_info_manager,
47                G_TYPE_OBJECT);
48 
49 static void remove_viewer (NautilusProgressInfoManager *self,
50                            GObject                     *viewer);
51 
52 static void
nautilus_progress_info_manager_finalize(GObject * obj)53 nautilus_progress_info_manager_finalize (GObject *obj)
54 {
55     GList *l;
56     NautilusProgressInfoManager *self = NAUTILUS_PROGRESS_INFO_MANAGER (obj);
57 
58     if (self->progress_infos != NULL)
59     {
60         g_list_free_full (self->progress_infos, g_object_unref);
61     }
62 
63     for (l = self->current_viewers; l != NULL; l = l->next)
64     {
65         g_object_weak_unref (l->data, (GWeakNotify) remove_viewer, self);
66     }
67     g_list_free (self->current_viewers);
68 
69     G_OBJECT_CLASS (nautilus_progress_info_manager_parent_class)->finalize (obj);
70 }
71 
72 static GObject *
nautilus_progress_info_manager_constructor(GType type,guint n_props,GObjectConstructParam * props)73 nautilus_progress_info_manager_constructor (GType                  type,
74                                             guint                  n_props,
75                                             GObjectConstructParam *props)
76 {
77     GObject *retval;
78 
79     if (singleton != NULL)
80     {
81         return G_OBJECT (g_object_ref (singleton));
82     }
83 
84     retval = G_OBJECT_CLASS (nautilus_progress_info_manager_parent_class)->constructor
85                  (type, n_props, props);
86 
87     singleton = NAUTILUS_PROGRESS_INFO_MANAGER (retval);
88     g_object_add_weak_pointer (retval, (gpointer) & singleton);
89 
90     return retval;
91 }
92 
93 static void
nautilus_progress_info_manager_init(NautilusProgressInfoManager * self)94 nautilus_progress_info_manager_init (NautilusProgressInfoManager *self)
95 {
96 }
97 
98 static void
nautilus_progress_info_manager_class_init(NautilusProgressInfoManagerClass * klass)99 nautilus_progress_info_manager_class_init (NautilusProgressInfoManagerClass *klass)
100 {
101     GObjectClass *oclass;
102 
103     oclass = G_OBJECT_CLASS (klass);
104     oclass->constructor = nautilus_progress_info_manager_constructor;
105     oclass->finalize = nautilus_progress_info_manager_finalize;
106 
107     signals[NEW_PROGRESS_INFO] =
108         g_signal_new ("new-progress-info",
109                       G_TYPE_FROM_CLASS (klass),
110                       G_SIGNAL_RUN_LAST,
111                       0, NULL, NULL,
112                       g_cclosure_marshal_VOID__OBJECT,
113                       G_TYPE_NONE,
114                       1,
115                       NAUTILUS_TYPE_PROGRESS_INFO);
116 
117     signals[HAS_VIEWERS_CHANGED] =
118         g_signal_new ("has-viewers-changed",
119                       G_TYPE_FROM_CLASS (klass),
120                       G_SIGNAL_RUN_LAST,
121                       0, NULL, NULL,
122                       g_cclosure_marshal_VOID__VOID,
123                       G_TYPE_NONE,
124                       0);
125 }
126 
127 NautilusProgressInfoManager *
nautilus_progress_info_manager_dup_singleton(void)128 nautilus_progress_info_manager_dup_singleton (void)
129 {
130     return g_object_new (NAUTILUS_TYPE_PROGRESS_INFO_MANAGER, NULL);
131 }
132 
133 void
nautilus_progress_info_manager_add_new_info(NautilusProgressInfoManager * self,NautilusProgressInfo * info)134 nautilus_progress_info_manager_add_new_info (NautilusProgressInfoManager *self,
135                                              NautilusProgressInfo        *info)
136 {
137     if (g_list_find (self->progress_infos, info) != NULL)
138     {
139         g_warning ("Adding two times the same progress info object to the manager");
140         return;
141     }
142 
143     self->progress_infos =
144         g_list_prepend (self->progress_infos, g_object_ref (info));
145 
146     g_signal_emit (self, signals[NEW_PROGRESS_INFO], 0, info);
147 }
148 
149 void
nautilus_progress_info_manager_remove_finished_or_cancelled_infos(NautilusProgressInfoManager * self)150 nautilus_progress_info_manager_remove_finished_or_cancelled_infos (NautilusProgressInfoManager *self)
151 {
152     GList *l;
153     GList *next;
154 
155     l = self->progress_infos;
156     while (l != NULL)
157     {
158         next = l->next;
159         if (nautilus_progress_info_get_is_finished (l->data) ||
160             nautilus_progress_info_get_is_cancelled (l->data))
161         {
162             self->progress_infos = g_list_remove (self->progress_infos,
163                                                   l->data);
164         }
165         l = next;
166     }
167 }
168 
169 GList *
nautilus_progress_info_manager_get_all_infos(NautilusProgressInfoManager * self)170 nautilus_progress_info_manager_get_all_infos (NautilusProgressInfoManager *self)
171 {
172     return self->progress_infos;
173 }
174 
175 gboolean
nautilus_progress_manager_are_all_infos_finished_or_cancelled(NautilusProgressInfoManager * self)176 nautilus_progress_manager_are_all_infos_finished_or_cancelled (NautilusProgressInfoManager *self)
177 {
178     GList *l;
179 
180     for (l = self->progress_infos; l != NULL; l = l->next)
181     {
182         if (!(nautilus_progress_info_get_is_finished (l->data) ||
183               nautilus_progress_info_get_is_cancelled (l->data)))
184         {
185             return FALSE;
186         }
187     }
188 
189     return TRUE;
190 }
191 
192 static void
remove_viewer(NautilusProgressInfoManager * self,GObject * viewer)193 remove_viewer (NautilusProgressInfoManager *self,
194                GObject                     *viewer)
195 {
196     self->current_viewers = g_list_remove (self->current_viewers, viewer);
197 
198     if (self->current_viewers == NULL)
199     {
200         g_signal_emit (self, signals[HAS_VIEWERS_CHANGED], 0);
201     }
202 }
203 
204 void
nautilus_progress_manager_add_viewer(NautilusProgressInfoManager * self,GObject * viewer)205 nautilus_progress_manager_add_viewer (NautilusProgressInfoManager *self,
206                                       GObject                     *viewer)
207 {
208     GList *viewers;
209 
210     viewers = self->current_viewers;
211     if (g_list_find (viewers, viewer) == NULL)
212     {
213         g_object_weak_ref (viewer, (GWeakNotify) remove_viewer, self);
214         viewers = g_list_append (viewers, viewer);
215         self->current_viewers = viewers;
216 
217         if (g_list_length (viewers) == 1)
218         {
219             g_signal_emit (self, signals[HAS_VIEWERS_CHANGED], 0);
220         }
221     }
222 }
223 
224 void
nautilus_progress_manager_remove_viewer(NautilusProgressInfoManager * self,GObject * viewer)225 nautilus_progress_manager_remove_viewer (NautilusProgressInfoManager *self,
226                                          GObject                     *viewer)
227 {
228     if (g_list_find (self->current_viewers, viewer) != NULL)
229     {
230         g_object_weak_unref (viewer, (GWeakNotify) remove_viewer, self);
231         remove_viewer (self, viewer);
232     }
233 }
234 
235 gboolean
nautilus_progress_manager_has_viewers(NautilusProgressInfoManager * self)236 nautilus_progress_manager_has_viewers (NautilusProgressInfoManager *self)
237 {
238     return self->current_viewers != NULL;
239 }
240