Merge branch 'master' of ssh://git.claws-mail.org/home/git/claws
[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                 VCalEvent *event = vcal_get_event_from_ical(
107                         icalcomponent_as_ical_string(ical), NULL);
108
109                 add_event_to_builder_if_match(event, array, start, end);
110                 g_free(event);
111         }
112         g_slist_free(list);
113
114         g_variant_builder_close(array);
115         
116         value = g_variant_builder_end(array);
117         g_variant_builder_unref(array);
118
119         g_dbus_method_invocation_return_value (invocation, value);
120         g_variant_unref(value);
121 }
122
123
124 static const GDBusInterfaceVTable interface_vtable =
125 {
126         handle_method_call,
127         NULL,
128         NULL
129 };
130
131 static GDBusNodeInfo *introspection_data = NULL;
132 static GDBusInterfaceInfo *interface_info = NULL;
133
134 static const gchar introspection_xml[] =
135   "<node>"
136   "  <interface name='org.gnome.Shell.CalendarServer'>"
137   "    <method name='GetEvents'>"
138   "      <arg type='x' name='greeting' direction='in'/>"
139   "      <arg type='x' name='greeting' direction='in'/>"
140   "      <arg type='b' name='greeting' direction='in'/>"
141   "      <arg type='a(sssbxxa{sv})' name='events' direction='out'/>"
142   "    </method>"
143   "  </interface>"
144   "</node>";
145
146 static void name_acquired (GDBusConnection *connection,
147                            const gchar     *name,
148                            gpointer         user_data)
149 {
150         debug_print("Acquired DBUS name %s\n", name);
151 }
152
153 static void name_lost (GDBusConnection *connection,
154                        const gchar     *name,
155                        gpointer         user_data)
156 {
157         debug_print("Lost DBUS name %s\n", name);
158 }
159
160 static void bus_acquired(GDBusConnection *connection,
161                          const gchar     *name,
162                          gpointer         user_data)
163 {
164         GError *err = NULL;
165         g_dbus_connection_register_object(connection,
166                 "/org/gnome/Shell/CalendarServer",
167                 introspection_data->interfaces[0],
168                 &interface_vtable, NULL, NULL, &err);
169         if (err != NULL)
170                 debug_print("Error: %s\n", err->message);
171 }
172
173 void connect_dbus(void)
174 {
175         introspection_data = g_dbus_node_info_new_for_xml(
176                                 introspection_xml, NULL);
177         if (introspection_data == NULL) {
178                 debug_print("Couldn't figure out XML.");
179                 return;
180         }
181         
182         interface_info = g_dbus_node_info_lookup_interface(
183                                 introspection_data,
184                                 "org.gnome.Shell.CalendarServer");
185         dbus_own_id = g_bus_own_name(G_BUS_TYPE_SESSION,
186                         "org.gnome.Shell.CalendarServer",
187                         G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT
188                         | G_BUS_NAME_OWNER_FLAGS_REPLACE,
189                         bus_acquired,
190                         name_acquired,
191                         name_lost,
192                         NULL, NULL);
193 }
194
195 void disconnect_dbus(void)
196 {
197         g_bus_unown_name(dbus_own_id);
198 }
199
200 #else
201 void connect_dbus(void)
202 {
203         debug_print("DBUS calendar export is not supported with Glib < 2.26\n");
204 }
205 void disconnect_dbus(void)
206 {
207         debug_print("DBUS calendar export is not supported with Glib < 2.26\n");
208 }
209 #endif