Fix FSF address (Tobias Mueller, #470445)
[platform/upstream/evolution-data-server.git] / calendar / libecal / e-cal-view.c
1 /* Evolution calendar - Live view client object
2  *
3  * Copyright (C) 2001 Ximian, Inc.
4  *
5  * Author: Federico Mena-Quintero <federico@ximian.com>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of version 2 of the GNU Lesser General Public
9  * License as published by the Free Software Foundation.
10  *
11  * This program 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 Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <string.h>
26 #include <bonobo/bonobo-exception.h>
27 #include "e-cal-marshal.h"
28 #include "e-cal.h"
29 #include "e-cal-view.h"
30 #include "e-cal-view-listener.h"
31 #include "e-cal-view-private.h"
32
33 \f
34
35 /* Private part of the ECalView structure */
36 struct _ECalViewPrivate {
37         /* Handle to the view in the server */
38         GNOME_Evolution_Calendar_CalView view;
39
40         /* Our view listener implementation */
41         ECalViewListener *listener;
42
43         /* The CalClient associated with this view */
44         ECal *client;
45 };
46
47 /* Property IDs */
48 enum props {
49         PROP_0,
50         PROP_VIEW,
51         PROP_LISTENER,
52         PROP_CLIENT
53 };
54
55 /* Signal IDs */
56 enum {
57         OBJECTS_ADDED,
58         OBJECTS_MODIFIED,
59         OBJECTS_REMOVED,
60         VIEW_PROGRESS,
61         VIEW_DONE,
62         LAST_SIGNAL
63 };
64
65 static guint signals[LAST_SIGNAL];
66
67 static GObjectClass *parent_class;
68
69 \f
70
71 static void
72 objects_added_cb (ECalViewListener *listener, GList *objects, gpointer data)
73 {
74         ECalView *view;
75
76         view = E_CAL_VIEW (data);
77
78         g_object_ref (view);
79         g_signal_emit (G_OBJECT (view), signals[OBJECTS_ADDED], 0, objects);
80         g_object_unref (view);
81 }
82
83 static void
84 objects_modified_cb (ECalViewListener *listener, GList *objects, gpointer data)
85 {
86         ECalView *view;
87
88         view = E_CAL_VIEW (data);
89
90         g_object_ref (view);
91         g_signal_emit (G_OBJECT (view), signals[OBJECTS_MODIFIED], 0, objects);
92         g_object_unref (view);
93 }
94
95 static void
96 objects_removed_cb (ECalViewListener *listener, GList *ids, gpointer data)
97 {
98         ECalView *view;
99
100         view = E_CAL_VIEW (data);
101
102         g_object_ref (view);
103         g_signal_emit (G_OBJECT (view), signals[OBJECTS_REMOVED], 0, ids);
104         g_object_unref (view);
105 }
106
107 static void
108 view_progress_cb (ECalViewListener *listener, const char *message, int percent, gpointer data)
109 {
110         ECalView *view;
111
112         view = E_CAL_VIEW (data);
113
114         g_signal_emit (G_OBJECT (view), signals[VIEW_PROGRESS], 0, message, percent);
115 }
116
117 static void
118 view_done_cb (ECalViewListener *listener, ECalendarStatus status, gpointer data)
119 {
120         ECalView *view;
121
122         view = E_CAL_VIEW (data);
123
124         g_signal_emit (G_OBJECT (view), signals[VIEW_DONE], 0, status);
125 }
126
127 /* Object initialization function for the calendar view */
128 static void
129 e_cal_view_init (ECalView *view, ECalViewClass *klass)
130 {
131         ECalViewPrivate *priv;
132
133         priv = g_new0 (ECalViewPrivate, 1);
134         view->priv = priv;
135
136         priv->listener = NULL;
137         priv->view = CORBA_OBJECT_NIL;
138 }
139
140 static void
141 e_cal_view_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
142 {
143         ECalView *view;
144         ECalViewPrivate *priv;
145         
146         view = E_CAL_VIEW (object);
147         priv = view->priv;
148         
149         switch (property_id) {
150         case PROP_VIEW:
151                 if (priv->view != CORBA_OBJECT_NIL)
152                         bonobo_object_release_unref (priv->view, NULL);
153
154                 priv->view = bonobo_object_dup_ref (g_value_get_pointer (value), NULL);
155                 break;
156         case PROP_LISTENER:
157                 if (priv->listener) {
158                         g_signal_handlers_disconnect_matched (priv->listener, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view);
159                         bonobo_object_unref (BONOBO_OBJECT (priv->listener));
160                 }
161
162                 priv->listener = bonobo_object_ref (g_value_get_pointer (value));
163
164                 g_signal_connect (G_OBJECT (priv->listener), "objects_added", 
165                                   G_CALLBACK (objects_added_cb), view);
166                 g_signal_connect (G_OBJECT (priv->listener), "objects_modified", 
167                                   G_CALLBACK (objects_modified_cb), view);
168                 g_signal_connect (G_OBJECT (priv->listener), "objects_removed", 
169                                   G_CALLBACK (objects_removed_cb), view);
170                 g_signal_connect (G_OBJECT (priv->listener), "view_progress", 
171                                   G_CALLBACK (view_progress_cb), view);
172                 g_signal_connect (G_OBJECT (priv->listener), "view_done", 
173                                   G_CALLBACK (view_done_cb), view);
174                 break;          
175         case PROP_CLIENT:
176                 priv->client = E_CAL (g_value_dup_object (value));
177                 break;
178         default:
179                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
180                 break;
181         }
182 }
183
184 static void
185 e_cal_view_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
186 {
187         ECalView *view;
188         ECalViewPrivate *priv;
189         
190         view = E_CAL_VIEW (object);
191         priv = view->priv;
192
193         switch (property_id) {
194         case PROP_VIEW:
195                 g_value_set_pointer (value, priv->view);
196                 break;
197         case PROP_LISTENER:
198                 g_value_set_pointer (value, priv->listener);
199                 break;
200         case PROP_CLIENT:
201                 g_value_set_object (value, priv->client);
202                 break;
203         default:
204                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
205                 break;
206         }
207 }
208
209 /* Finalize handler for the calendar view */
210 static void
211 e_cal_view_finalize (GObject *object)
212 {
213         ECalView *view;
214         ECalViewPrivate *priv;
215
216         g_return_if_fail (object != NULL);
217         g_return_if_fail (E_IS_CAL_VIEW (object));
218
219         view = E_CAL_VIEW (object);
220         priv = view->priv;
221
222         /* The server keeps a copy of the view listener, so we must unref it */
223         g_signal_handlers_disconnect_matched (priv->listener, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view);
224         bonobo_object_unref (BONOBO_OBJECT (priv->listener));
225
226         if (priv->view != CORBA_OBJECT_NIL)
227                 bonobo_object_release_unref (priv->view, NULL);
228
229         g_free (priv);
230
231         if (G_OBJECT_CLASS (parent_class)->finalize)
232                 (* G_OBJECT_CLASS (parent_class)->finalize) (object);
233 }
234
235 /* Class initialization function for the calendar view */
236 static void
237 e_cal_view_class_init (ECalViewClass *klass)
238 {
239         GObjectClass *object_class;
240         GParamSpec *param;
241         
242         object_class = (GObjectClass *) klass;
243
244         parent_class = g_type_class_peek_parent (klass);
245
246         object_class->set_property = e_cal_view_set_property;
247         object_class->get_property = e_cal_view_get_property;
248         object_class->finalize = e_cal_view_finalize;
249
250         param =  g_param_spec_pointer ("view", "The corba view object", NULL,
251                                       G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
252         g_object_class_install_property (object_class, PROP_VIEW, param);
253         /* FIXME type this property as object? */
254         param =  g_param_spec_pointer ("listener", "The view listener object to use", NULL,
255                                       G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
256         g_object_class_install_property (object_class, PROP_LISTENER, param);
257         param =  g_param_spec_object ("client", "The e-cal for the view", NULL, E_TYPE_CAL,
258                                       G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
259         g_object_class_install_property (object_class, PROP_CLIENT, param);
260         
261         signals[OBJECTS_ADDED] =
262                 g_signal_new ("objects_added",
263                               G_TYPE_FROM_CLASS (klass),
264                               G_SIGNAL_RUN_FIRST,
265                               G_STRUCT_OFFSET (ECalViewClass, objects_added),
266                               NULL, NULL,
267                               g_cclosure_marshal_VOID__POINTER,
268                               G_TYPE_NONE, 1, G_TYPE_POINTER);
269         signals[OBJECTS_MODIFIED] =
270                 g_signal_new ("objects_modified",
271                               G_TYPE_FROM_CLASS (klass),
272                               G_SIGNAL_RUN_FIRST,
273                               G_STRUCT_OFFSET (ECalViewClass, objects_modified),
274                               NULL, NULL,
275                               g_cclosure_marshal_VOID__POINTER,
276                               G_TYPE_NONE, 1, G_TYPE_POINTER);
277         signals[OBJECTS_REMOVED] =
278                 g_signal_new ("objects_removed",
279                               G_TYPE_FROM_CLASS (klass),
280                               G_SIGNAL_RUN_FIRST,
281                               G_STRUCT_OFFSET (ECalViewClass, objects_removed),
282                               NULL, NULL,
283                               g_cclosure_marshal_VOID__POINTER,
284                               G_TYPE_NONE, 1, G_TYPE_POINTER);
285         signals[VIEW_PROGRESS] =
286                 g_signal_new ("view_progress",
287                               G_TYPE_FROM_CLASS (klass),
288                               G_SIGNAL_RUN_FIRST,
289                               G_STRUCT_OFFSET (ECalViewClass, view_progress),
290                               NULL, NULL,
291                               e_cal_marshal_VOID__STRING_INT,
292                               G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_INT);
293         signals[VIEW_DONE] =
294                 g_signal_new ("view_done",
295                               G_TYPE_FROM_CLASS (klass),
296                               G_SIGNAL_RUN_FIRST,
297                               G_STRUCT_OFFSET (ECalViewClass, view_done),
298                               NULL, NULL,
299                               g_cclosure_marshal_VOID__INT,
300                               G_TYPE_NONE, 1, G_TYPE_INT);
301 }
302
303 /**
304  * e_cal_view_get_type:
305  * 
306  * Registers the #ECalView class if necessary, and returns the type ID assigned
307  * to it.
308  * 
309  * Return value: The type ID of the #ECalView class.
310  **/
311 GType
312 e_cal_view_get_type (void)
313 {
314         static GType e_cal_view_type = 0;
315
316         if (!e_cal_view_type) {
317                 static GTypeInfo info = {
318                         sizeof (ECalViewClass),
319                         (GBaseInitFunc) NULL,
320                         (GBaseFinalizeFunc) NULL,
321                         (GClassInitFunc) e_cal_view_class_init,
322                         NULL, NULL,
323                         sizeof (ECalView),
324                         0,
325                         (GInstanceInitFunc) e_cal_view_init
326                 };
327                 e_cal_view_type = g_type_register_static (G_TYPE_OBJECT, "ECalView", &info, 0);
328         }
329
330         return e_cal_view_type;
331 }
332
333 /**
334  * e_cal_view_new:
335  * @corba_view: The CORBA object for the view.
336  * @listener: An #ECalViewListener.
337  * @client: An #ECal object.
338  * 
339  * Creates a new view object by issuing the view creation request to the
340  * calendar server.
341  * 
342  * Return value: A newly-created view object, or NULL if the request failed.
343  **/
344 ECalView *
345 e_cal_view_new (GNOME_Evolution_Calendar_CalView corba_view, ECalViewListener *listener, ECal *client)
346 {
347         ECalView *view;
348
349         view = g_object_new (E_TYPE_CAL_VIEW, "view", corba_view, "listener", 
350                               listener, "client", client, NULL);
351
352         return view;
353 }
354
355 /**
356  * e_cal_view_get_client
357  * @view: A #ECalView object.
358  *
359  * Get the #ECal associated with this view.
360  *
361  * Return value: the associated client.
362  */
363 ECal *
364 e_cal_view_get_client (ECalView *view)
365 {
366         g_return_val_if_fail (E_IS_CAL_VIEW (view), NULL);
367
368         return view->priv->client;
369 }
370
371 /**
372  * e_cal_view_start:
373  * @view: A #ECalView object.
374  *
375  * Starts a live query to the calendar/tasks backend.
376  */
377 void
378 e_cal_view_start (ECalView *view)
379 {
380         ECalViewPrivate *priv;
381         CORBA_Environment ev;
382
383         g_return_if_fail (view != NULL);
384         g_return_if_fail (E_IS_CAL_VIEW (view));
385         
386         priv = view->priv;
387         
388         CORBA_exception_init (&ev);
389
390         GNOME_Evolution_Calendar_CalView_start (priv->view, &ev);
391         if (BONOBO_EX (&ev)) 
392                 g_warning (G_STRLOC ": Unable to start view");
393
394         CORBA_exception_free (&ev);
395 }