src/mn-evolution-mailbox.gob (7148B) - raw
1 /*
2 * Mail Notification
3 * Copyright (C) 2003-2008 Jean-Yves Lefort <jylefort@brutele.be>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 %headertop{
21 #include "mn-mailbox.h"
22 %}
23
24 %privateheader{
25 #include <time.h>
26 #include "mn-evolution-client.h"
27 %}
28
29 %{
30 #include <stdarg.h>
31 #include <gobject/gvaluecollector.h>
32 #include <glib/gi18n.h>
33 #include "mn-evolution.h"
34 #include "mn-mailbox-private.h"
35 #include "mn-message.h"
36 #include "mn-util.h"
37 #include "mn-stock.h"
38 #include "mn-evolution-message.h"
39 #include "mn-shell.h"
40 #include "mn-evolution-client-dbus.h"
41
42 typedef struct
43 {
44 const char *uid;
45 unsigned int sent_time;
46 unsigned int received_time;
47 const char *id;
48 const char *from;
49 const char *subject;
50 } MessageInfo;
51 %}
52
53 class MN:Evolution:Mailbox from MN:Mailbox
54 {
55 public char *uri destroywith g_free;
56 property STRING uri (link, flags = MN_MAILBOX_PARAM_LOAD_SAVE | MN_MAILBOX_PARAM_REQUIRED);
57
58 /*
59 * Evolution might not be running when we instantiate the mailbox,
60 * so we cache the folder name.
61 */
62 public char *folder_name destroywith g_free;
63 property STRING folder_name (link, flags = MN_MAILBOX_PARAM_LOAD_SAVE | MN_MAILBOX_PARAM_REQUIRED);
64
65 private MNEvolutionClient *client;
66 private gboolean signals_connected;
67 private DBusGProxyCall *pending_call;
68
69 private time_t last_browsed;
70
71 class_init (class)
72 {
73 MN_MAILBOX_CLASS(class)->type = "evolution";
74 }
75
76 init (self)
77 {
78 mn_mailbox_set_format(MN_MAILBOX(self), "Evolution");
79 mn_mailbox_set_stock_id(MN_MAILBOX(self), MN_STOCK_EVOLUTION_MAILBOX);
80
81 /* we receive notifications from Evolution, no need to poll */
82 mn_mailbox_set_poll(MN_MAILBOX(self), FALSE);
83 }
84
85 override (MN:Mailbox) void
86 seal (MNMailbox *mailbox)
87 {
88 PARENT_HANDLER(mailbox);
89
90 if (! mailbox->runtime_name)
91 mailbox->runtime_name = g_strdup(SELF(mailbox)->folder_name);
92 }
93
94 finalize (self)
95 {
96 if (selfp->client)
97 {
98 if (selfp->pending_call)
99 {
100 g_assert(selfp->client->proxy != NULL);
101 dbus_g_proxy_cancel_call(selfp->client->proxy, selfp->pending_call);
102 }
103
104 self_disconnect_proxy_signals(self);
105
106 g_signal_handlers_disconnect_by_func(selfp->client, mn_mailbox_check, self);
107 }
108 }
109
110 private void
111 connect_proxy_signals (self)
112 {
113 g_return_if_fail(selfp->client != NULL);
114 g_return_if_fail(selfp->client->proxy != NULL);
115
116 if (selfp->signals_connected)
117 return;
118
119 dbus_g_proxy_connect_signal(selfp->client->proxy,
120 MN_EVOLUTION_SERVER_SIGNAL_FOLDER_CHANGED,
121 G_CALLBACK(self_folder_changed_h),
122 self,
123 NULL);
124 dbus_g_proxy_connect_signal(selfp->client->proxy,
125 MN_EVOLUTION_SERVER_SIGNAL_MESSAGE_READING,
126 G_CALLBACK(self_message_reading_h),
127 self,
128 NULL);
129
130 selfp->signals_connected = TRUE;
131 }
132
133 private void
134 disconnect_proxy_signals (self)
135 {
136 g_return_if_fail(selfp->client != NULL);
137
138 if (! selfp->signals_connected)
139 return;
140
141 selfp->signals_connected = FALSE;
142
143 if (! selfp->client->proxy)
144 return;
145
146 dbus_g_proxy_disconnect_signal(selfp->client->proxy,
147 MN_EVOLUTION_SERVER_SIGNAL_FOLDER_CHANGED,
148 G_CALLBACK(self_folder_changed_h),
149 self);
150 dbus_g_proxy_disconnect_signal(selfp->client->proxy,
151 MN_EVOLUTION_SERVER_SIGNAL_MESSAGE_READING,
152 G_CALLBACK(self_message_reading_h),
153 self);
154 }
155
156 private void
157 folder_changed_h (DBusGProxy *proxy, const char *uri, gpointer user_data)
158 {
159 Self *self = user_data;
160
161 if (! strcmp(uri, self->uri))
162 {
163 GDK_THREADS_ENTER();
164 mn_mailbox_check(MN_MAILBOX(self));
165 GDK_THREADS_LEAVE();
166 }
167 }
168
169 private void
170 message_reading_h (DBusGProxy *proxy, const char *uri, gpointer user_data)
171 {
172 Self *self = user_data;
173
174 if (! strcmp(uri, self->uri))
175 {
176 selfp->last_browsed = mn_time();
177
178 GDK_THREADS_ENTER();
179 mn_mailbox_check(MN_MAILBOX(self));
180 GDK_THREADS_LEAVE();
181 }
182 }
183
184 private void
185 value_array_get_values (GValueArray *value_array (check null), ...)
186 {
187 va_list args;
188 int i;
189
190 va_start(args, value_array);
191
192 for (i = 0; i < value_array->n_values; i++)
193 {
194 GValue *value = g_value_array_get_nth(value_array, i);
195 char *error = NULL;
196
197 G_VALUE_LCOPY(value, args, G_VALUE_NOCOPY_CONTENTS, &error);
198 g_assert(error == NULL);
199 }
200
201 va_end(args);
202 }
203
204 override (MN:Mailbox) void
205 check (MNMailbox *mailbox)
206 {
207 Self *self = SELF(mailbox);
208
209 PARENT_HANDLER(mailbox);
210
211 mn_mailbox_set_error(mailbox, NULL);
212
213 if (! selfp->client)
214 {
215 selfp->client = mn_evolution_client_get();
216 g_signal_connect_swapped(selfp->client, "notify::proxy", G_CALLBACK(mn_mailbox_check), self);
217 }
218
219 if (! selfp->client->proxy) /* not connected */
220 {
221 selfp->pending_call = NULL;
222
223 self_disconnect_proxy_signals(self);
224
225 mn_mailbox_set_error(mailbox, _("unable to contact Evolution"));
226
227 return;
228 }
229
230 self_connect_proxy_signals(self);
231
232 if (selfp->pending_call)
233 dbus_g_proxy_cancel_call(selfp->client->proxy, selfp->pending_call);
234
235 selfp->pending_call = org_gnome_MailNotification_Evolution_get_unseen_messages_async(selfp->client->proxy,
236 self->uri,
237 self_get_unseen_messages_cb,
238 self);
239 }
240
241 private void
242 get_unseen_messages_cb (DBusGProxy *proxy,
243 GPtrArray *messages_array,
244 GError *err,
245 gpointer user_data)
246 {
247 Self *self = user_data;
248
249 GDK_THREADS_ENTER();
250
251 if (err)
252 {
253 mn_mailbox_set_error(MN_MAILBOX(self), "%s", err->message);
254 g_error_free(err);
255 }
256 else
257 {
258 int i;
259 GSList *messages = NULL;
260
261 for (i = 0; i < messages_array->len; i++)
262 {
263 GValueArray *value_array = g_ptr_array_index(messages_array, i);
264 MessageInfo info;
265 MNMessageFlags flags = 0;
266
267 self_value_array_get_values(value_array,
268 &info.uid,
269 &info.sent_time,
270 &info.received_time,
271 &info.id,
272 &info.from,
273 &info.subject);
274
275 if (info.received_time > selfp->last_browsed)
276 flags |= MN_MESSAGE_NEW;
277
278 messages = g_slist_prepend(messages,
279 mn_evolution_message_new(MN_MAILBOX(self),
280 info.sent_time,
281 info.id,
282 info.from,
283 info.subject,
284 flags,
285 info.uid));
286 }
287
288 mn_g_ptr_array_free_deep_custom(messages_array, (GFunc) g_value_array_free, NULL);
289
290 mn_mailbox_set_messages(MN_MAILBOX(self), messages);
291 mn_g_object_slist_free(messages);
292 }
293
294 selfp->pending_call = NULL;
295
296 GDK_THREADS_LEAVE();
297 }
298 }