Fix bug #3380. Initialize widget before callback handler for 'clicked'
[claws.git] / src / plugins / vcalendar / vcal_dbus.c
1 /*
2  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2011 Colin Leroy <colin@colino.net> and 
4  * the Claws Mail team
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU 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  * 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 General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #  include "config.h"
23 #include "claws-features.h"
24 #endif
25
26 #include <stddef.h>
27 #include <glib.h>
28 #include <glib/gi18n.h>
29
30 #include <ical.h>
31 #include <gtk/gtk.h>
32
33 #include "utils.h"
34 #include "vcal_manager.h"
35 #include "vcal_folder.h"
36
37 #if(GLIB_CHECK_VERSION(2,26,0))
38
39 static guint dbus_own_id;
40
41 static void add_event_to_builder_if_match(VCalEvent *event, GVariantBuilder *array,
42                                           time_t start, time_t end)
43 {
44         time_t evt_start = icaltime_as_timet((icaltime_from_string(event->dtstart)));
45         time_t evt_end = icaltime_as_timet((icaltime_from_string(event->dtend)));
46         if ((evt_start >= start && evt_start <= end)
47          || (evt_end >= start && evt_end <= end)) {
48                 g_variant_builder_open(array, 
49                         G_VARIANT_TYPE("(sssbxxa{sv})"));
50                         g_variant_builder_add(array, "s", event->uid);
51                         g_variant_builder_add(array, "s", event->summary);
52                         g_variant_builder_add(array, "s", event->description);
53                         g_variant_builder_add(array, "b", FALSE);
54                         g_variant_builder_add(array, "x", (gint64)evt_start);
55                         g_variant_builder_add(array, "x", (gint64)evt_end);
56                         g_variant_builder_open(array, G_VARIANT_TYPE("a{sv}"));
57                                 /* We don't put stuff there. */
58                         g_variant_builder_close(array);
59                 g_variant_builder_close(array);
60          }
61 }
62
63 static void handle_method_call (GDBusConnection       *connection,
64                                 const gchar           *sender,
65                                 const gchar           *object_path,
66                                 const gchar           *interface_name,
67                                 const gchar           *method_name,
68                                 GVariant              *parameters,
69                                 GDBusMethodInvocation *invocation,
70                                 gpointer               user_data)
71 {
72         time_t start, end;
73         gboolean refresh;
74         GSList *list, *cur;
75         int i;
76         GVariantBuilder *array = g_variant_builder_new(
77                         G_VARIANT_TYPE("(a(sssbxxa{sv}))"));
78         GVariant *value;
79
80         if (g_strcmp0(method_name, "GetEvents") != 0) {
81                 debug_print("Unknown method %s\n", method_name);
82         }
83         
84         g_variant_get(parameters, "(xxb)", &start, &end, &refresh);
85
86         
87         g_variant_builder_open(array, G_VARIANT_TYPE("a(sssbxxa{sv})"));
88
89         /* First our own calendar */
90         list = vcal_folder_get_waiting_events();
91         for (cur = list, i = 0; cur; cur = cur->next, i++) {
92                 VCalEvent *event = (VCalEvent *)cur->data;
93
94                 add_event_to_builder_if_match(event, array, start, end);
95
96                 g_free(event);
97         }
98         g_slist_free(list);
99
100         /* Then subs. */
101         list = vcal_folder_get_webcal_events();
102         for (cur = list; cur; cur = cur->next) {
103                 /* Don't free that, it's done when subscriptions are
104                  * fetched */
105                 icalcomponent *ical = (icalcomponent *)cur->data;
106                 if (ical != NULL) {
107                         VCalEvent *event = vcal_get_event_from_ical(
108                                 icalcomponent_as_ical_string(ical), NULL);
109                         if (event != NULL) {
110                                 add_event_to_builder_if_match(
111                                         event, array, start, end);
112                                 g_free(event);
113                         }
114                 }
115         }
116         g_slist_free(list);
117
118         g_variant_builder_close(array);
119         
120         value = g_variant_builder_end(array);
121         g_variant_builder_unref(array);
122
123         g_dbus_method_invocation_return_value (invocation, value);
124         g_variant_unref(value);
125 }
126
127
128 static const GDBusInterfaceVTable interface_vtable =
129 {
130         handle_method_call,
131         NULL,
132         NULL
133 };
134
135 static GDBusNodeInfo *introspection_data = NULL;
136 static GDBusInterfaceInfo *interface_info = NULL;
137
138 static const gchar introspection_xml[] =
139   "<node>"
140   "  <interface name='org.gnome.Shell.CalendarServer'>"
141   "    <method name='GetEvents'>"
142   "      <arg type='x' name='greeting' direction='in'/>"
143   "      <arg type='x' name='greeting' direction='in'/>"
144   "      <arg type='b' name='greeting' direction='in'/>"
145   "      <arg type='a(sssbxxa{sv})' name='events' direction='out'/>"
146   "    </method>"
147   "  </interface>"
148   "</node>";
149
150 static void name_acquired (GDBusConnection *connection,
151                            const gchar     *name,
152                            gpointer         user_data)
153 {
154         debug_print("Acquired DBUS name %s\n", name);
155 }
156
157 static void name_lost (GDBusConnection *connection,
158                        const gchar     *name,
159                        gpointer         user_data)
160 {
161         debug_print("Lost DBUS name %s\n", name);
162 }
163
164 static void bus_acquired(GDBusConnection *connection,
165                          const gchar     *name,
166                          gpointer         user_data)
167 {
168         GError *err = NULL;
169         g_dbus_connection_register_object(connection,
170                 "/org/gnome/Shell/CalendarServer",
171                 introspection_data->interfaces[0],
172                 &interface_vtable, NULL, NULL, &err);
173         if (err != NULL)
174                 debug_print("Error: %s\n", err->message);
175 }
176
177 void connect_dbus(void)
178 {
179         introspection_data = g_dbus_node_info_new_for_xml(
180                                 introspection_xml, NULL);
181         if (introspection_data == NULL) {
182                 debug_print("Couldn't figure out XML.");
183                 return;
184         }
185         
186         interface_info = g_dbus_node_info_lookup_interface(
187                                 introspection_data,
188                                 "org.gnome.Shell.CalendarServer");
189         dbus_own_id = g_bus_own_name(G_BUS_TYPE_SESSION,
190                         "org.gnome.Shell.CalendarServer",
191                         G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT
192                         | G_BUS_NAME_OWNER_FLAGS_REPLACE,
193                         bus_acquired,
194                         name_acquired,
195                         name_lost,
196                         NULL, NULL);
197 }
198
199 void disconnect_dbus(void)
200 {
201         g_bus_unown_name(dbus_own_id);
202 }
203
204 #else
205 void connect_dbus(void)
206 {
207         debug_print("DBUS calendar export is not supported with Glib < 2.26\n");
208 }
209 void disconnect_dbus(void)
210 {
211         debug_print("DBUS calendar export is not supported with Glib < 2.26\n");
212 }
213 #endif