|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the Qt Mobility Components. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 #include "modestengine_maemo_p.h" |
|
42 #include "maemohelpers_p.h" |
|
43 #include "qmessage_p.h" |
|
44 #include "qmessageaccount.h" |
|
45 #include "qmessageaccount_p.h" |
|
46 #include "qmessageaccountfilter.h" |
|
47 #include "qmessageaccountfilter_p.h" |
|
48 #include "qmessagefolder_p.h" |
|
49 #include "qmessagestore_p.h" |
|
50 #include "qmessageservice_maemo_p.h" |
|
51 #include "qmessagecontentcontainer_maemo_p.h" |
|
52 #include <QUrl> |
|
53 #include <QtDBus> |
|
54 #include <QFileSystemWatcher> |
|
55 #include <QTimer> |
|
56 |
|
57 #include <dbus/dbus.h> |
|
58 #include <QDebug> |
|
59 |
|
60 #include </usr/include/libmodest-dbus-client-1.0/libmodest-dbus-client/libmodest-dbus-api.h> |
|
61 #include </usr/include/sys/inotify.h> |
|
62 #include </usr/include/sys/ioctl.h> |
|
63 #include </usr/include/sys/fcntl.h> |
|
64 |
|
65 // Marshall the ModestStringMap data into a D-Bus argument |
|
66 QDBusArgument &operator<<(QDBusArgument &argument, |
|
67 const QtMobility::ModestStringMap &map) |
|
68 { |
|
69 QtMobility::ModestStringMap::const_iterator iter; |
|
70 |
|
71 argument.beginMap (QVariant::String, QVariant::String); |
|
72 for (iter = map.constBegin(); iter != map.constEnd(); iter++) { |
|
73 argument.beginMapEntry(); |
|
74 argument << iter.key() << iter.value(); |
|
75 argument.endMapEntry(); |
|
76 } |
|
77 argument.endMap(); |
|
78 |
|
79 return argument; |
|
80 } |
|
81 |
|
82 // Retrieve the ModestStringMap data from the D-Bus argument |
|
83 const QDBusArgument &operator>>(const QDBusArgument &argument, |
|
84 QtMobility::ModestStringMap &map) |
|
85 { |
|
86 map.clear(); |
|
87 |
|
88 argument.beginMap(); |
|
89 while (!argument.atEnd()) { |
|
90 QString key, value; |
|
91 argument.beginMapEntry(); |
|
92 argument >> key >> value; |
|
93 argument.endMapEntry(); |
|
94 map[key] = value; |
|
95 } |
|
96 argument.endMap(); |
|
97 |
|
98 return argument; |
|
99 } |
|
100 |
|
101 QDBusArgument &operator<<(QDBusArgument &argument, |
|
102 const QtMobility::ModestUnreadMessageDBusStruct &unreadMessage) |
|
103 { |
|
104 argument.beginStructure(); |
|
105 argument << unreadMessage.timeStamp; |
|
106 argument << unreadMessage.subject; |
|
107 argument.endStructure(); |
|
108 return argument; |
|
109 } |
|
110 |
|
111 const QDBusArgument &operator>>(const QDBusArgument &argument, |
|
112 QtMobility::ModestUnreadMessageDBusStruct &unreadMessage) |
|
113 { |
|
114 argument.beginStructure(); |
|
115 argument >> unreadMessage.timeStamp; |
|
116 argument >> unreadMessage.subject; |
|
117 argument.endStructure(); |
|
118 return argument; |
|
119 } |
|
120 |
|
121 QDBusArgument &operator<<(QDBusArgument &argument, |
|
122 const QtMobility::ModestAccountsUnreadMessagesDBusStruct &unreadMessages) |
|
123 { |
|
124 argument.beginStructure(); |
|
125 argument << unreadMessages.accountId; |
|
126 argument << unreadMessages.accountName; |
|
127 argument << unreadMessages.accountProtocol; |
|
128 argument << unreadMessages.unreadCount; |
|
129 argument << unreadMessages.unreadMessages; |
|
130 argument.endStructure(); |
|
131 return argument; |
|
132 } |
|
133 |
|
134 const QDBusArgument &operator>>(const QDBusArgument &argument, |
|
135 QtMobility::ModestAccountsUnreadMessagesDBusStruct &unreadMessages) |
|
136 { |
|
137 argument.beginStructure(); |
|
138 argument >> unreadMessages.accountId; |
|
139 argument >> unreadMessages.accountName; |
|
140 argument >> unreadMessages.accountProtocol; |
|
141 argument >> unreadMessages.unreadCount; |
|
142 argument >> unreadMessages.unreadMessages; |
|
143 argument.endStructure(); |
|
144 return argument; |
|
145 } |
|
146 |
|
147 QDBusArgument &operator<<(QDBusArgument &argument, const QtMobility::ModestMessage &message) |
|
148 { |
|
149 argument.beginStructure(); |
|
150 argument << message.id; |
|
151 argument << message.subject; |
|
152 argument << message.folder; |
|
153 argument << message.sender; |
|
154 argument << message.size; |
|
155 argument << message.hasAttachment; |
|
156 argument << message.isUnread; |
|
157 argument << message.timeStamp; |
|
158 argument.endStructure(); |
|
159 return argument; |
|
160 } |
|
161 |
|
162 const QDBusArgument &operator>>(const QDBusArgument &argument, QtMobility::ModestMessage &message) |
|
163 { |
|
164 argument.beginStructure(); |
|
165 argument >> message.id; |
|
166 argument >> message.subject; |
|
167 argument >> message.folder; |
|
168 argument >> message.sender; |
|
169 argument >> message.size; |
|
170 argument >> message.hasAttachment; |
|
171 argument >> message.isUnread; |
|
172 argument >> message.timeStamp; |
|
173 argument.endStructure(); |
|
174 return argument; |
|
175 } |
|
176 |
|
177 QDBusArgument &operator<<(QDBusArgument &argument, const QtMobility::MessagingModestMimePart &mimePart) |
|
178 { |
|
179 argument.beginStructure(); |
|
180 argument << mimePart.mimeType; |
|
181 argument << mimePart.isAttachment; |
|
182 argument << mimePart.fileName; |
|
183 argument << mimePart.contentId; |
|
184 argument.endStructure(); |
|
185 return argument; |
|
186 } |
|
187 |
|
188 const QDBusArgument &operator>>(const QDBusArgument &argument, QtMobility::MessagingModestMimePart &mimePart) |
|
189 { |
|
190 argument.beginStructure(); |
|
191 argument >> mimePart.mimeType; |
|
192 argument >> mimePart.isAttachment; |
|
193 argument >> mimePart.fileName; |
|
194 argument >> mimePart.contentId; |
|
195 argument.endStructure(); |
|
196 return argument; |
|
197 } |
|
198 |
|
199 QDBusArgument &operator<<(QDBusArgument &argument, const QtMobility::MessagingModestFolder &folder) |
|
200 { |
|
201 argument.beginStructure(); |
|
202 argument << folder.parentAccountId; |
|
203 argument << folder.parentFolderId; |
|
204 argument << folder.modestId; |
|
205 argument << static_cast<uint>(folder.type); |
|
206 argument << folder.localizedName; |
|
207 argument.endStructure(); |
|
208 return argument; |
|
209 } |
|
210 |
|
211 const QDBusArgument &operator>>(const QDBusArgument &argument, QtMobility::MessagingModestFolder &folder) |
|
212 { |
|
213 argument.beginStructure(); |
|
214 |
|
215 argument >> folder.parentAccountId; |
|
216 QByteArray str = folder.parentAccountId.toUtf8(); |
|
217 gchar* escaped_string = gconf_escape_key(str.data(), str.length()); |
|
218 folder.parentAccountId = QString::fromUtf8(escaped_string); |
|
219 g_free(escaped_string); |
|
220 |
|
221 argument >> folder.parentFolderId; |
|
222 argument >> folder.modestId; |
|
223 |
|
224 uint type; |
|
225 argument >> type; |
|
226 folder.type = static_cast<QtMobility::MessagingModestFolderType>(type); |
|
227 |
|
228 argument >> folder.localizedName; |
|
229 argument.endStructure(); |
|
230 return argument; |
|
231 } |
|
232 |
|
233 QTM_BEGIN_NAMESPACE |
|
234 |
|
235 /* configuration key definitions for modest */ |
|
236 #define MODESTENGINE_ACCOUNT_NAMESPACE "/apps/modest/accounts" |
|
237 #define MODESTENGINE_SERVER_ACCOUNT_NAMESPACE "/apps/modest/server_accounts" |
|
238 #define MODESTENGINE_DEFAULT_ACCOUNT "/apps/modest/default_account" |
|
239 #define MODESTENGINE_ACCOUNT_ENABLED "enabled" |
|
240 #define MODESTENGINE_ACCOUNT_DISPLAY_NAME "display_name" |
|
241 #define MODESTENGINE_ACCOUNT_FULLNAME "fullname" |
|
242 #define MODESTENGINE_ACCOUNT_EMAIL "email" |
|
243 #define MODESTENGINE_ACCOUNT_STORE_ACCOUNT "store_account" |
|
244 #define MODESTENGINE_ACCOUNT_TRANSPORT_ACCOUNT "transport_account" |
|
245 #define MODESTENGINE_ACCOUNT_PROTOCOL "proto" |
|
246 #define MODESTENGINE_ACCOUNT_USERNAME "username" |
|
247 #define MODESTENGINE_ACCOUNT_HOSTNAME "hostname" |
|
248 #define MODESTENGINE_ACCOUNT_PORT "port" |
|
249 |
|
250 // The modest engine has a new plugin, we need service names for it |
|
251 #define MODESTENGINE_QTM_PLUGIN_PATH "/com/nokia/Qtm/Modest/Plugin" |
|
252 #define MODESTENGINE_QTM_PLUGIN_NAME "com.nokia.Qtm.Modest.Plugin" |
|
253 |
|
254 typedef enum { |
|
255 MODEST_DBUS_SEARCH_SUBJECT = (1 << 0), |
|
256 MODEST_DBUS_SEARCH_SENDER = (1 << 1), |
|
257 MODEST_DBUS_SEARCH_RECIPIENT = (1 << 2), |
|
258 MODEST_DBUS_SEARCH_SIZE = (1 << 3), |
|
259 MODEST_DBUS_SEARCH_BODY = (1 << 6) |
|
260 } ModestDBusSearchFlags; |
|
261 |
|
262 // Specific priority settings to translate to modest priorities |
|
263 #define MODESTENGINE_HIGH_PRIORITY 2 |
|
264 #define MODESTENGINE_NORMAL_PRIORITY 0 |
|
265 #define MODESTENGINE_LOW_PRIORITY 1 |
|
266 |
|
267 Q_GLOBAL_STATIC(ModestEngine,modestEngine); |
|
268 |
|
269 ModestEngine::ModestEngine() |
|
270 : m_queryIds(0) |
|
271 { |
|
272 qWarning() << "ModestEngine::ModestEngine Starting to initialize"; |
|
273 g_type_init(); |
|
274 m_gconfclient = gconf_client_get_default(); |
|
275 if (!m_gconfclient) { |
|
276 qWarning("qtmessaging: could not get gconf client"); |
|
277 } else { |
|
278 updateEmailAccounts(); |
|
279 } |
|
280 |
|
281 qWarning() << "ModestEngine::ModestEngine Connecting to Modest DBus Interface"; |
|
282 // Setup DBus Interface for Modest |
|
283 m_ModestDBusInterface = new QDBusInterface(MODEST_DBUS_SERVICE, |
|
284 MODEST_DBUS_OBJECT, |
|
285 MODEST_DBUS_IFACE, |
|
286 QDBusConnection::sessionBus(), |
|
287 this); |
|
288 if (m_ModestDBusInterface->isValid()) { |
|
289 qWarning() << "ModestEngine::ModestEngine Connected to Modest DBus Interface"; |
|
290 } else { |
|
291 qWarning() << "ModestEngine::ModestEngine Unable to connect to Modest DBus Interface"; |
|
292 } |
|
293 |
|
294 // Get notifications of Incoming Messages |
|
295 m_ModestDBusInterface->connection().connect(MODEST_DBUS_SERVICE, |
|
296 MODEST_DBUS_OBJECT, |
|
297 MODEST_DBUS_IFACE, |
|
298 MODEST_DBUS_SIGNAL_FOLDER_UPDATED, |
|
299 this, SLOT(folderUpdatedSlot(QDBusMessage))); |
|
300 |
|
301 // Get notifications of message Read/Unread state changes |
|
302 m_ModestDBusInterface->connection().connect(MODEST_DBUS_SERVICE, |
|
303 MODEST_DBUS_OBJECT, |
|
304 MODEST_DBUS_IFACE, |
|
305 MODEST_DBUS_SIGNAL_MSG_READ_CHANGED, |
|
306 this, SLOT(messageReadChangedSlot(QDBusMessage))); |
|
307 |
|
308 qWarning() << "ModestEngine::ModestEngine Connecting to Qt Mobility Modest Plugin DBus Interface"; |
|
309 // Setup Qt Mobility Modest Plugin based DBus Interface for Modest |
|
310 m_QtmPluginDBusInterface = new QDBusInterface(MODESTENGINE_QTM_PLUGIN_NAME, |
|
311 MODESTENGINE_QTM_PLUGIN_PATH, |
|
312 MODESTENGINE_QTM_PLUGIN_NAME, |
|
313 QDBusConnection::sessionBus(), |
|
314 this); |
|
315 |
|
316 if (m_QtmPluginDBusInterface->isValid()) { |
|
317 qWarning() << "ModestEngine::ModestEngine Connected to Qt Mobility Modest Plugin DBus Interface"; |
|
318 } else { |
|
319 qWarning() << "ModestEngine::ModestEngine Unable to connect to Qt Mobility Modest Plugin DBus Interface"; |
|
320 } |
|
321 |
|
322 qDBusRegisterMetaType< ModestStringMap >(); |
|
323 qDBusRegisterMetaType< ModestStringMapList >(); |
|
324 |
|
325 qRegisterMetaType<INotifyWatcher::FileNotification>(); |
|
326 |
|
327 qRegisterMetaType<ModestUnreadMessageDBusStruct>(); |
|
328 qRegisterMetaType<ModestAccountsUnreadMessagesDBusStruct>(); |
|
329 qDBusRegisterMetaType<ModestMessage>(); |
|
330 |
|
331 qRegisterMetaType<MessagingModestMimePart>(); |
|
332 |
|
333 qRegisterMetaType<MessagingModestFolder>(); |
|
334 |
|
335 |
|
336 connect(&m_MailFoldersWatcher, SIGNAL(fileChanged(int, QString, uint)), |
|
337 this, SLOT(fileChangedSlot(int, QString, uint))); |
|
338 |
|
339 watchAllKnownEmailFolders(); |
|
340 |
|
341 // Get latest messages from each account |
|
342 // => This ensures that notifications of all incoming messages will be sent |
|
343 int messagesPerAccount = 1; |
|
344 QDBusPendingCall pendingCall = m_ModestDBusInterface->asyncCall(MODEST_DBUS_METHOD_GET_UNREAD_MESSAGES, |
|
345 messagesPerAccount); |
|
346 QDBusPendingCallWatcher* pendingCallWatcher = new QDBusPendingCallWatcher(pendingCall); |
|
347 pendingCallWatcher->setProperty("setOnlyDates", true); |
|
348 connect(pendingCallWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), |
|
349 this, SLOT(pendingGetUnreadMessagesFinishedSlot(QDBusPendingCallWatcher*))); |
|
350 |
|
351 QList<MessagingModestFolder> modestFolders; |
|
352 foldersFromModest(modestFolders); |
|
353 if (modestFolders.count() > 0) { |
|
354 for (int i=0; i < modestFolders.count(); i++) { |
|
355 if (modestFolders[i].type == MessagingModestFolderTypeInbox && modestFolders[i].parentAccountId != "local_folders") { |
|
356 QMessageAccountId accountId = accountIdFromModestAccountId(modestFolders[i].parentAccountId); |
|
357 if (accountExists(accountId)) { |
|
358 QString id = accountId.toString()+"&"+accountEmailProtocolAsString(accountId)+"&"+modestFolders[i].modestId; |
|
359 startObservingModestFolder(id); |
|
360 } |
|
361 } |
|
362 } |
|
363 } |
|
364 |
|
365 qWarning() << "ModestEngine::ModestEngine Initialized successfully"; |
|
366 } |
|
367 |
|
368 ModestEngine::~ModestEngine() |
|
369 { |
|
370 g_object_unref(m_gconfclient); |
|
371 m_gconfclient=NULL; |
|
372 |
|
373 if (m_observed_folders.count()) { |
|
374 for (int i = m_observed_folders.count()-1; i >= 0; i--) { |
|
375 stopObservingModestFolder(m_observed_folders[i]); |
|
376 } |
|
377 } |
|
378 } |
|
379 |
|
380 ModestEngine* ModestEngine::instance() |
|
381 { |
|
382 return modestEngine(); |
|
383 } |
|
384 |
|
385 MessagingModestMessage ModestEngine::messageFromModest(const QString& accountId, const QString &folderId, const QString& messageId) const |
|
386 { |
|
387 MessagingModestMessage modestMessage; |
|
388 |
|
389 if (!m_QtmPluginDBusInterface->isValid() || iAccounts.isEmpty()) { |
|
390 return modestMessage; |
|
391 } |
|
392 |
|
393 QDBusPendingCall pendingCall = m_QtmPluginDBusInterface->asyncCall("GetMessage", |
|
394 accountId, |
|
395 folderId, |
|
396 messageId); |
|
397 QDBusPendingCallWatcher pendingCallWatcher(pendingCall); |
|
398 pendingCallWatcher.waitForFinished(); |
|
399 |
|
400 QDBusMessage msg = pendingCallWatcher.reply(); |
|
401 |
|
402 if (msg.type() == QDBusMessage::ReplyMessage) { |
|
403 modestMessage.id = messageId; |
|
404 modestMessage.accountId = accountId; |
|
405 modestMessage.folderId = folderId; |
|
406 modestMessage.url = msg.arguments()[0].toString(); |
|
407 modestMessage.mimeType = msg.arguments()[1].toString(); |
|
408 modestMessage.from = msg.arguments()[2].toString(); |
|
409 modestMessage.to = msg.arguments()[3].toString(); |
|
410 modestMessage.cc = msg.arguments()[4].toString(); |
|
411 modestMessage.bcc = msg.arguments()[5].toString(); |
|
412 modestMessage.replyTo = msg.arguments()[6].toString(); |
|
413 modestMessage.subject = msg.arguments()[7].toString(); |
|
414 modestMessage.dateReceived = msg.arguments()[8].toLongLong(); |
|
415 modestMessage.dateSent = msg.arguments()[9].toLongLong(); |
|
416 modestMessage.size = msg.arguments()[10].toLongLong(); |
|
417 modestMessage.flags = static_cast<MessagingModestMessageFlags>(msg.arguments()[11].toUInt()); |
|
418 modestMessage.priority = static_cast<MessagingModestMessagePriority>(msg.arguments()[12].toUInt()); |
|
419 |
|
420 QVariant variant = msg.arguments()[13]; |
|
421 QDBusArgument argument = variant.value<QDBusArgument>(); |
|
422 argument >> modestMessage.mimeParts; |
|
423 } else { |
|
424 modestMessage.dateReceived = 0; |
|
425 modestMessage.dateSent = 0; |
|
426 modestMessage.size = 0; |
|
427 modestMessage.flags = MessagingModestMessageNotDefined; |
|
428 modestMessage.priority = MessagingModestMessagePriorityNotDefined; |
|
429 } |
|
430 |
|
431 return modestMessage; |
|
432 } |
|
433 |
|
434 void ModestEngine::updateEmailAccounts() const |
|
435 { |
|
436 iDefaultEmailAccountId = QMessageAccountId(); |
|
437 iAccounts.clear(); |
|
438 |
|
439 GSList *accounts; |
|
440 GError *error = NULL; |
|
441 |
|
442 accounts = gconf_client_all_dirs(m_gconfclient, MODESTENGINE_ACCOUNT_NAMESPACE, &error); |
|
443 if (error) { |
|
444 #ifdef MESSAGING_DEBUG |
|
445 qDebug("qtmessaging: failed to list '%s': '%s'", MODESTENGINE_ACCOUNT_NAMESPACE, error->message); |
|
446 #endif |
|
447 g_error_free(error); |
|
448 } else { |
|
449 gchar *default_account_id = gconf_client_get_string(m_gconfclient, MODESTENGINE_DEFAULT_ACCOUNT, &error); |
|
450 if (error) { |
|
451 qWarning("qtmessaging: failed to get '%s': %s", MODESTENGINE_DEFAULT_ACCOUNT, error->message); |
|
452 g_error_free(error); |
|
453 } |
|
454 |
|
455 const size_t prefix_len = strlen(MODESTENGINE_ACCOUNT_NAMESPACE) + 1; |
|
456 |
|
457 GSList *iter = accounts; |
|
458 while (iter) { |
|
459 if (!(iter->data)) { |
|
460 iter = iter->next; |
|
461 continue; |
|
462 } |
|
463 |
|
464 const gchar* account_key = (const gchar*)iter->data; |
|
465 // account_key = /apps/modest/server_accounts/<account id> |
|
466 // => take account id from account_key & unescape account id |
|
467 gchar* unescaped_account_id = gconf_unescape_key(account_key+prefix_len, strlen(account_key)-prefix_len); |
|
468 |
|
469 gboolean account_ok = FALSE; |
|
470 // Check if account is enabled |
|
471 if (account_key) { |
|
472 gchar* key = g_strconcat(account_key, "/", MODESTENGINE_ACCOUNT_ENABLED, NULL); |
|
473 account_ok = gconf_client_get_bool(m_gconfclient, key, NULL); |
|
474 g_free(key); |
|
475 } |
|
476 |
|
477 // Check if account store is defined |
|
478 if (account_ok) { |
|
479 gchar* key = g_strconcat(account_key, "/", MODESTENGINE_ACCOUNT_STORE_ACCOUNT, NULL); |
|
480 gchar* server_account_name = gconf_client_get_string(m_gconfclient, key, NULL); |
|
481 if (server_account_name) { |
|
482 gchar* escaped_server_account_name = gconf_escape_key(server_account_name, strlen(server_account_name)); |
|
483 g_free(server_account_name); |
|
484 gchar* store_account_key = g_strconcat(MODESTENGINE_SERVER_ACCOUNT_NAMESPACE, "/", escaped_server_account_name, NULL); |
|
485 if (!gconf_client_dir_exists(m_gconfclient, store_account_key, NULL)) { |
|
486 account_ok = FALSE; |
|
487 } |
|
488 g_free(store_account_key); |
|
489 g_free(escaped_server_account_name); |
|
490 } |
|
491 g_free(key); |
|
492 } |
|
493 |
|
494 // Check if account transport is defined |
|
495 if (account_ok) { |
|
496 gchar* key = g_strconcat(account_key, "/", MODESTENGINE_ACCOUNT_TRANSPORT_ACCOUNT, NULL); |
|
497 gchar* server_account_name = gconf_client_get_string(m_gconfclient, key, NULL); |
|
498 if (server_account_name) { |
|
499 gchar* escaped_server_account_name = gconf_escape_key(server_account_name, strlen(server_account_name)); |
|
500 g_free(server_account_name); |
|
501 gchar* transport_account_key = g_strconcat(MODESTENGINE_SERVER_ACCOUNT_NAMESPACE, "/", escaped_server_account_name, NULL); |
|
502 if (!gconf_client_dir_exists(m_gconfclient, transport_account_key, NULL)) { |
|
503 account_ok = FALSE; |
|
504 } |
|
505 g_free(transport_account_key); |
|
506 g_free(escaped_server_account_name); |
|
507 } |
|
508 g_free(key); |
|
509 } |
|
510 |
|
511 if (account_ok) { |
|
512 gchar* escaped_account_id = gconf_escape_key(unescaped_account_id, strlen(unescaped_account_id)); |
|
513 QString accountId = "MO_"+QString::fromUtf8(escaped_account_id); |
|
514 g_free(escaped_account_id); |
|
515 |
|
516 gchar* name_key = g_strconcat(account_key, "/", MODESTENGINE_ACCOUNT_DISPLAY_NAME, NULL); |
|
517 gchar* account_name = gconf_client_get_string(m_gconfclient, name_key, NULL); |
|
518 QString accountName = QString::fromUtf8(account_name); |
|
519 g_free(account_name); |
|
520 g_free(name_key); |
|
521 |
|
522 gchar* email_key = g_strconcat(account_key, "/", MODESTENGINE_ACCOUNT_EMAIL, NULL); |
|
523 gchar* email = gconf_client_get_string(m_gconfclient, email_key, NULL); |
|
524 QString accountAddress = QString::fromUtf8(email); |
|
525 g_free(email); |
|
526 g_free(email_key); |
|
527 |
|
528 QMessageAccount account = QMessageAccountPrivate::from(QMessageAccountId(accountId), |
|
529 accountName, |
|
530 QMessageAddress(QMessageAddress::Email, accountAddress), |
|
531 QMessage::Email); |
|
532 iAccounts.insert(accountId, account); |
|
533 |
|
534 // Check if newly added account is default account |
|
535 if (default_account_id) { |
|
536 if (!strncmp(default_account_id, unescaped_account_id, strlen(default_account_id))) { |
|
537 iDefaultEmailAccountId = accountId; |
|
538 } |
|
539 } |
|
540 } |
|
541 |
|
542 g_free(unescaped_account_id); |
|
543 g_free(iter->data); |
|
544 iter->data = NULL; |
|
545 iter = g_slist_next(iter); |
|
546 } |
|
547 // strings were freed in while loop |
|
548 // => it's enough to just free accounts list |
|
549 g_slist_free(accounts); |
|
550 g_free(default_account_id); |
|
551 } |
|
552 } |
|
553 |
|
554 QMessageAccountIdList ModestEngine::queryAccounts(const QMessageAccountFilter &filter, const QMessageAccountSortOrder &sortOrder, |
|
555 uint limit, uint offset, bool &isFiltered, bool &isSorted) const |
|
556 { |
|
557 Q_UNUSED(sortOrder) |
|
558 Q_UNUSED(limit) |
|
559 Q_UNUSED(offset) |
|
560 |
|
561 QMessageAccountIdList accountIds; |
|
562 |
|
563 if (!m_QtmPluginDBusInterface->isValid()) { |
|
564 return accountIds; |
|
565 } |
|
566 |
|
567 updateEmailAccounts(); |
|
568 foreach (QMessageAccount value, iAccounts) { |
|
569 accountIds.append(value.id()); |
|
570 } |
|
571 |
|
572 MessagingHelper::filterAccounts(accountIds, filter); |
|
573 isFiltered = true; |
|
574 |
|
575 isSorted = false; |
|
576 |
|
577 return accountIds; |
|
578 } |
|
579 |
|
580 int ModestEngine::countAccounts(const QMessageAccountFilter &filter) const |
|
581 { |
|
582 bool isFiltered, isSorted; |
|
583 return queryAccounts(filter, QMessageAccountSortOrder(), 0, 0, isFiltered, isSorted).count(); |
|
584 } |
|
585 |
|
586 QMessageAccount ModestEngine::account(const QMessageAccountId &id) const |
|
587 { |
|
588 updateEmailAccounts(); |
|
589 return iAccounts[id.toString()]; |
|
590 } |
|
591 |
|
592 QMessageAccountId ModestEngine::defaultAccount() const |
|
593 { |
|
594 updateEmailAccounts(); |
|
595 return iDefaultEmailAccountId; |
|
596 } |
|
597 |
|
598 QFileInfoList ModestEngine::localFolders() const |
|
599 { |
|
600 QDir dir(localRootFolder()); |
|
601 dir.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot); |
|
602 QFileInfoList fileInfoList = dir.entryInfoList(); |
|
603 appendLocalSubFolders(fileInfoList, 0); |
|
604 return fileInfoList; |
|
605 } |
|
606 |
|
607 void ModestEngine::appendLocalSubFolders(QFileInfoList& fileInfoList, int startIndex) const |
|
608 { |
|
609 int endIndex = fileInfoList.count(); |
|
610 for (int i=startIndex; i < endIndex; i++) { |
|
611 QDir dir(fileInfoList[i].absoluteFilePath()); |
|
612 if (dir.exists()) { |
|
613 dir.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot); |
|
614 QFileInfoList dirs = dir.entryInfoList(); |
|
615 for (int j = 0; j < dirs.count(); j++) { |
|
616 QString fileName = dirs[j].fileName(); |
|
617 if (fileName != "cur" && fileName != "new" && fileName != "tmp") { |
|
618 fileInfoList.append(dirs[j]); |
|
619 } |
|
620 } |
|
621 } |
|
622 } |
|
623 if (fileInfoList.count() > endIndex) { |
|
624 appendLocalSubFolders(fileInfoList, endIndex); |
|
625 } |
|
626 } |
|
627 |
|
628 void ModestEngine::appendIMAPSubFolders(QFileInfoList& fileInfoList, int startIndex) const |
|
629 { |
|
630 int endIndex = fileInfoList.count(); |
|
631 for (int i=startIndex; i < endIndex; i++) { |
|
632 QDir dir(fileInfoList[i].absoluteFilePath()+QString("/subfolders")); |
|
633 if (dir.exists()) { |
|
634 dir.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot); |
|
635 fileInfoList.append(dir.entryInfoList()); |
|
636 } |
|
637 } |
|
638 if (fileInfoList.count() > endIndex) { |
|
639 appendIMAPSubFolders(fileInfoList, endIndex); |
|
640 } |
|
641 } |
|
642 |
|
643 QString ModestEngine::localRootFolder() const |
|
644 { |
|
645 return QDir::home().absolutePath()+QString("/.modest/local_folders"); |
|
646 } |
|
647 |
|
648 QString ModestEngine::accountRootFolder(QMessageAccountId& accountId) const |
|
649 { |
|
650 QString modestAccountId = escapeString(modestAccountIdFromAccountId(accountId)); |
|
651 |
|
652 QString userName; |
|
653 QString hostName; |
|
654 QString port; |
|
655 QString protocol; |
|
656 |
|
657 gchar* store_account_key = g_strconcat(MODESTENGINE_ACCOUNT_NAMESPACE, "/", modestAccountId.toUtf8().data(), "/", MODESTENGINE_ACCOUNT_STORE_ACCOUNT, NULL); |
|
658 gchar* store_account_name = gconf_client_get_string(m_gconfclient, store_account_key, NULL); |
|
659 g_free(store_account_key); |
|
660 gchar* escaped_store_account_name = gconf_escape_key(store_account_name, strlen(store_account_name)); |
|
661 g_free(store_account_name); |
|
662 |
|
663 gchar* username_key = g_strconcat(MODESTENGINE_SERVER_ACCOUNT_NAMESPACE, "/", escaped_store_account_name, "/", MODESTENGINE_ACCOUNT_USERNAME, NULL); |
|
664 gchar* account_username = gconf_client_get_string(m_gconfclient, username_key, NULL); |
|
665 userName = QString::fromUtf8(account_username); |
|
666 g_free(account_username); |
|
667 g_free(username_key); |
|
668 |
|
669 gchar* hostname_key = g_strconcat(MODESTENGINE_SERVER_ACCOUNT_NAMESPACE, "/", escaped_store_account_name, "/", MODESTENGINE_ACCOUNT_HOSTNAME, NULL); |
|
670 gchar* account_hostname = gconf_client_get_string(m_gconfclient, hostname_key, NULL); |
|
671 hostName = QString::fromUtf8(account_hostname); |
|
672 g_free(account_hostname); |
|
673 g_free(hostname_key); |
|
674 |
|
675 gchar* port_key = g_strconcat(MODESTENGINE_SERVER_ACCOUNT_NAMESPACE, "/", escaped_store_account_name, "/", MODESTENGINE_ACCOUNT_PORT, NULL); |
|
676 gint account_port = gconf_client_get_int(m_gconfclient, port_key, NULL); |
|
677 port = QString::number(account_port); |
|
678 g_free(port_key); |
|
679 |
|
680 gchar* protocol_key = g_strconcat(MODESTENGINE_SERVER_ACCOUNT_NAMESPACE, "/", escaped_store_account_name, "/", MODESTENGINE_ACCOUNT_PROTOCOL, NULL); |
|
681 gchar* account_protocol = gconf_client_get_string(m_gconfclient, protocol_key, NULL); |
|
682 protocol = QString::fromUtf8(account_protocol); |
|
683 g_free(account_protocol); |
|
684 g_free(protocol_key); |
|
685 |
|
686 g_free(escaped_store_account_name); |
|
687 |
|
688 if (protocol == "pop") { |
|
689 return QDir::home().absolutePath()+"/.modest/cache/mail/"+protocol+"/"+userName+"__"+hostName+"_"+port; |
|
690 } else if (protocol == "imap") { |
|
691 return QDir::home().absolutePath()+"/.modest/cache/mail/"+protocol+"/"+userName+"__"+hostName+"_"+port+"/folders"; |
|
692 } |
|
693 return QString(); |
|
694 } |
|
695 |
|
696 QFileInfoList ModestEngine::accountFolders(QMessageAccountId& accountId) const |
|
697 { |
|
698 QFileInfoList fileInfoList; |
|
699 |
|
700 EmailProtocol protocol = accountEmailProtocol(accountId); |
|
701 |
|
702 if (protocol == ModestEngine::EmailProtocolPop3) { |
|
703 QFileInfo fileInfo = QFileInfo(accountRootFolder(accountId)+"/cache"); |
|
704 fileInfoList.append(fileInfo); |
|
705 } else if (protocol == ModestEngine::EmailProtocolIMAP) { |
|
706 QDir dir(accountRootFolder(accountId)); |
|
707 dir.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot); |
|
708 fileInfoList = dir.entryInfoList(); |
|
709 appendIMAPSubFolders(fileInfoList, 0); |
|
710 } |
|
711 |
|
712 return fileInfoList; |
|
713 } |
|
714 |
|
715 ModestEngine::EmailProtocol ModestEngine::accountEmailProtocol(QMessageAccountId& accountId) const |
|
716 { |
|
717 EmailProtocol protocol = EmailProtocolUnknown; |
|
718 |
|
719 QString modestAccountId = escapeString(modestAccountIdFromAccountId(accountId)); |
|
720 |
|
721 gchar* store_account_key = g_strconcat(MODESTENGINE_ACCOUNT_NAMESPACE, "/", modestAccountId.toUtf8().data(), "/", MODESTENGINE_ACCOUNT_STORE_ACCOUNT, NULL); |
|
722 gchar* store_account_name = gconf_client_get_string(m_gconfclient, store_account_key, NULL); |
|
723 g_free(store_account_key); |
|
724 gchar* escaped_store_account_name = gconf_escape_key(store_account_name, strlen(store_account_name)); |
|
725 g_free(store_account_name); |
|
726 |
|
727 gchar* protocol_key = g_strconcat(MODESTENGINE_SERVER_ACCOUNT_NAMESPACE, "/", escaped_store_account_name, "/", MODESTENGINE_ACCOUNT_PROTOCOL, NULL); |
|
728 gchar* account_protocol = gconf_client_get_string(m_gconfclient, protocol_key, NULL); |
|
729 if (QString("pop") == account_protocol) { |
|
730 protocol = EmailProtocolPop3; |
|
731 } else if (QString("imap") == account_protocol) { |
|
732 protocol = EmailProtocolIMAP; |
|
733 } |
|
734 g_free(account_protocol); |
|
735 g_free(protocol_key); |
|
736 |
|
737 g_free(escaped_store_account_name); |
|
738 |
|
739 return protocol; |
|
740 } |
|
741 |
|
742 bool ModestEngine::accountExists(const QMessageAccountId& accountId) const |
|
743 { |
|
744 bool retVal = false; |
|
745 |
|
746 QString modestAccountId = escapeString(modestAccountIdFromAccountId(accountId)); |
|
747 gchar* account_key = g_strconcat(MODESTENGINE_ACCOUNT_NAMESPACE, "/", modestAccountId.toUtf8().data(), NULL); |
|
748 retVal = gconf_client_dir_exists(m_gconfclient, account_key, NULL); |
|
749 g_free(account_key); |
|
750 |
|
751 return retVal; |
|
752 } |
|
753 |
|
754 QString ModestEngine::accountEmailProtocolAsString(const QMessageAccountId& accountId) const |
|
755 { |
|
756 QString protocol; |
|
757 |
|
758 QString modestAccountId = escapeString(modestAccountIdFromAccountId(accountId)); |
|
759 |
|
760 gchar* store_account_key = g_strconcat(MODESTENGINE_ACCOUNT_NAMESPACE, "/", modestAccountId.toUtf8().data(), "/", MODESTENGINE_ACCOUNT_STORE_ACCOUNT, NULL); |
|
761 gchar* store_account_name = gconf_client_get_string(m_gconfclient, store_account_key, NULL); |
|
762 g_free(store_account_key); |
|
763 gchar* escaped_store_account_name = gconf_escape_key(store_account_name, strlen(store_account_name)); |
|
764 g_free(store_account_name); |
|
765 |
|
766 gchar* protocol_key = g_strconcat(MODESTENGINE_SERVER_ACCOUNT_NAMESPACE, "/", escaped_store_account_name, "/", MODESTENGINE_ACCOUNT_PROTOCOL, NULL); |
|
767 gchar* account_protocol = gconf_client_get_string(m_gconfclient, protocol_key, NULL); |
|
768 protocol = QString::fromUtf8(account_protocol); |
|
769 g_free(account_protocol); |
|
770 g_free(protocol_key); |
|
771 |
|
772 g_free(escaped_store_account_name); |
|
773 |
|
774 return protocol; |
|
775 } |
|
776 |
|
777 QString ModestEngine::accountUsername(QMessageAccountId& accountId) const |
|
778 { |
|
779 QString username; |
|
780 |
|
781 QString modestAccountId = escapeString(modestAccountIdFromAccountId(accountId)); |
|
782 |
|
783 gchar* store_account_key = g_strconcat(MODESTENGINE_ACCOUNT_NAMESPACE, "/", modestAccountId.toUtf8().data(), "/", MODESTENGINE_ACCOUNT_STORE_ACCOUNT, NULL); |
|
784 gchar* store_account_name = gconf_client_get_string(m_gconfclient, store_account_key, NULL); |
|
785 g_free(store_account_key); |
|
786 gchar* escaped_store_account_name = gconf_escape_key(store_account_name, strlen(store_account_name)); |
|
787 g_free(store_account_name); |
|
788 |
|
789 gchar* username_key = g_strconcat(MODESTENGINE_SERVER_ACCOUNT_NAMESPACE, "/", escaped_store_account_name, "/", MODESTENGINE_ACCOUNT_USERNAME, NULL); |
|
790 gchar* account_username = gconf_client_get_string(m_gconfclient, username_key, NULL); |
|
791 username = QString::fromUtf8(account_username); |
|
792 g_free(account_username); |
|
793 g_free(username_key); |
|
794 |
|
795 g_free(escaped_store_account_name); |
|
796 |
|
797 return username; |
|
798 } |
|
799 |
|
800 QString ModestEngine::accountHostname(QMessageAccountId& accountId) const |
|
801 { |
|
802 QString host; |
|
803 |
|
804 QString modestAccountId = escapeString(modestAccountIdFromAccountId(accountId)); |
|
805 |
|
806 gchar* store_account_key = g_strconcat(MODESTENGINE_ACCOUNT_NAMESPACE, "/", modestAccountId.toUtf8().data(), "/", MODESTENGINE_ACCOUNT_STORE_ACCOUNT, NULL); |
|
807 gchar* store_account_name = gconf_client_get_string(m_gconfclient, store_account_key, NULL); |
|
808 g_free(store_account_key); |
|
809 gchar* escaped_store_account_name = gconf_escape_key(store_account_name, strlen(store_account_name)); |
|
810 g_free(store_account_name); |
|
811 |
|
812 gchar* host_key = g_strconcat(MODESTENGINE_SERVER_ACCOUNT_NAMESPACE, "/", escaped_store_account_name, "/", MODESTENGINE_ACCOUNT_HOSTNAME, NULL); |
|
813 gchar* account_host = gconf_client_get_string(m_gconfclient, host_key, NULL); |
|
814 host = QString::fromUtf8(account_host); |
|
815 g_free(account_host); |
|
816 g_free(host_key); |
|
817 |
|
818 g_free(escaped_store_account_name); |
|
819 |
|
820 return host; |
|
821 } |
|
822 |
|
823 void ModestEngine::foldersFromModest(QList<MessagingModestFolder>& folders) const |
|
824 { |
|
825 if (!m_QtmPluginDBusInterface->isValid() || iAccounts.isEmpty()) { |
|
826 return; |
|
827 } |
|
828 |
|
829 QDBusPendingCall pendingCall = m_QtmPluginDBusInterface->asyncCall("GetFolders"); |
|
830 QDBusPendingCallWatcher pendingCallWatcher(pendingCall); |
|
831 pendingCallWatcher.waitForFinished(); |
|
832 |
|
833 QDBusMessage msg = pendingCallWatcher.reply(); |
|
834 |
|
835 if (msg.type() == QDBusMessage::ReplyMessage) { |
|
836 QVariant variant = msg.arguments()[0]; |
|
837 QDBusArgument argument = variant.value<QDBusArgument>(); |
|
838 argument >> folders; |
|
839 } |
|
840 } |
|
841 |
|
842 QMessageFolderIdList ModestEngine::queryFolders(const QMessageFolderFilter &filter, const QMessageFolderSortOrder &sortOrder, |
|
843 uint limit, uint offset, bool &isFiltered, bool &isSorted) const |
|
844 { |
|
845 Q_UNUSED(sortOrder) |
|
846 Q_UNUSED(limit) |
|
847 Q_UNUSED(offset) |
|
848 |
|
849 QMessageFolderIdList folderIds; |
|
850 |
|
851 if (!m_QtmPluginDBusInterface->isValid()) { |
|
852 return folderIds; |
|
853 } |
|
854 |
|
855 updateEmailAccounts(); |
|
856 |
|
857 if (iAccounts.isEmpty()) { |
|
858 return folderIds; |
|
859 } |
|
860 |
|
861 m_folderCache.clear(); |
|
862 |
|
863 QList<MessagingModestFolder> modestFolders; |
|
864 foldersFromModest(modestFolders); |
|
865 |
|
866 if (modestFolders.count() > 0) { |
|
867 foreach (QMessageAccount value, iAccounts) { |
|
868 QMessageAccountId accountId = value.id(); |
|
869 // Add folder to cache |
|
870 QString modestAccountId = modestAccountIdFromAccountId(accountId); |
|
871 for (int j=0; j < modestFolders.count(); j++) { |
|
872 if (modestFolders[j].parentAccountId == modestAccountId) { |
|
873 MessagingModestFolder folder = modestFolders[j]; |
|
874 QString id = accountId.toString()+"&"+accountEmailProtocolAsString(accountId)+"&"+folder.modestId; |
|
875 folder.id = id; |
|
876 m_folderCache.insert(id, folder); |
|
877 |
|
878 folderIds.append(QMessageFolderId(id)); |
|
879 } |
|
880 } |
|
881 for (int j=0; j < modestFolders.count(); j++) { |
|
882 if (modestFolders[j].parentAccountId == "local_folders") { |
|
883 MessagingModestFolder folder = modestFolders[j]; |
|
884 QString id = accountId.toString()+"&"+"maildir"+"&"+folder.modestId; |
|
885 folder.id = id; |
|
886 m_folderCache.insert(id, folder); |
|
887 |
|
888 folderIds.append(QMessageFolderId(id)); |
|
889 } |
|
890 } |
|
891 } |
|
892 } else { |
|
893 QFileInfoList localFolders = this->localFolders(); |
|
894 QString localRootFolder = this->localRootFolder(); |
|
895 |
|
896 foreach (QMessageAccount value, iAccounts) { |
|
897 QMessageAccountId accountId = value.id(); |
|
898 QString rootFolder = accountRootFolder(accountId); |
|
899 QFileInfoList folders = this->accountFolders(accountId); |
|
900 |
|
901 for (int i=0; i < folders.count(); i++) { |
|
902 QString filePath = folders[i].absoluteFilePath(); |
|
903 QString modestId = filePath.right(filePath.size()-rootFolder.size()-1); |
|
904 modestId = modestId.remove("/subfolders"); |
|
905 QString id = accountId.toString()+"&"+accountEmailProtocolAsString(accountId)+"&"+modestId; |
|
906 folderIds.append(QMessageFolderId(id)); |
|
907 |
|
908 // Add folder to cache |
|
909 MessagingModestFolder folder; |
|
910 folder.id = id; |
|
911 folder.modestId = modestId; |
|
912 if (modestId.lastIndexOf('/') == -1) { |
|
913 // Folder does not have subfolders |
|
914 folder.name = modestId; |
|
915 if ((accountEmailProtocolAsString(accountId) == "pop") && (folder.name == "cache")) { |
|
916 folder.name = "Inbox"; |
|
917 } |
|
918 } else { |
|
919 // Folder has subfolders |
|
920 folder.name = modestId.right(modestId.length()-modestId.lastIndexOf('/')-1); |
|
921 folder.parentFolderId = modestId.left(modestId.lastIndexOf('/')); |
|
922 } |
|
923 folder.parentAccountId = modestAccountIdFromAccountId(accountId); |
|
924 folder.type = MessagingModestFolderTypeUnknown; |
|
925 m_folderCache.insert(id, folder); |
|
926 } |
|
927 |
|
928 // Each account sees local folders as account folders |
|
929 for (int i=0; i < localFolders.count(); i++) { |
|
930 QString filePath = localFolders[i].absoluteFilePath(); |
|
931 QString modestId = filePath.right(filePath.size()-localRootFolder.size()-1); |
|
932 QString id = accountId.toString()+"&"+"maildir"+"&"+modestId; |
|
933 folderIds.append(QMessageFolderId(id)); |
|
934 |
|
935 // Add folder to cache |
|
936 MessagingModestFolder folder; |
|
937 folder.id = id; |
|
938 folder.modestId = modestId; |
|
939 if (modestId.lastIndexOf('/') == -1) { |
|
940 // Folder does not have subfolders |
|
941 folder.name = modestId; |
|
942 if ((accountEmailProtocolAsString(accountId) == "pop") && (folder.name == "cache")) { |
|
943 folder.name = "Inbox"; |
|
944 } |
|
945 } else { |
|
946 // Folder has subfolders |
|
947 folder.name = modestId.right(modestId.length()-modestId.lastIndexOf('/')-1); |
|
948 folder.parentFolderId = modestId.left(modestId.lastIndexOf('/')); |
|
949 } |
|
950 folder.parentAccountId = "local_folders"; |
|
951 folder.type = MessagingModestFolderTypeUnknown; |
|
952 m_folderCache.insert(id, folder); |
|
953 } |
|
954 } |
|
955 } |
|
956 |
|
957 MessagingHelper::filterFolders(folderIds, filter); |
|
958 isFiltered = true; |
|
959 isSorted = false; |
|
960 return folderIds; |
|
961 } |
|
962 |
|
963 int ModestEngine::countFolders(const QMessageFolderFilter &filter) const |
|
964 { |
|
965 bool isFiltered, isSorted; |
|
966 return queryFolders(filter, QMessageFolderSortOrder(), 0, 0, isFiltered, isSorted).count(); |
|
967 } |
|
968 |
|
969 QMessageFolder ModestEngine::folder(const QMessageFolderId &id) const |
|
970 { |
|
971 QMessageFolder folder; |
|
972 |
|
973 QString idString = id.toString(); |
|
974 if (m_folderCache.contains(idString)) { |
|
975 MessagingModestFolder modestFolder = m_folderCache.value(idString); |
|
976 int endOfAccountId = idString.indexOf('&'); |
|
977 QString accountId = idString.left(endOfAccountId); |
|
978 QString folderPath = idString.right(idString.length()-idString.lastIndexOf('&')-1); |
|
979 QMessageFolderId parentId; |
|
980 QString name; |
|
981 if (folderPath.lastIndexOf('/') != -1) { |
|
982 // Folder has subfolders |
|
983 parentId = idString.left(idString.lastIndexOf('/')); |
|
984 } |
|
985 |
|
986 if (modestFolder.localizedName.isEmpty()) { |
|
987 folder = QMessageFolderPrivate::from(id, |
|
988 QMessageAccountId(accountId), |
|
989 parentId, |
|
990 modestFolder.name, |
|
991 folderPath); |
|
992 } else { |
|
993 folder = QMessageFolderPrivate::from(id, |
|
994 QMessageAccountId(accountId), |
|
995 parentId, |
|
996 modestFolder.localizedName, |
|
997 folderPath); |
|
998 } |
|
999 } |
|
1000 |
|
1001 return folder; |
|
1002 } |
|
1003 |
|
1004 bool ModestEngine::startObservingModestFolder(const QMessageFolderId& folderId) const |
|
1005 { |
|
1006 if (!m_QtmPluginDBusInterface->isValid() || iAccounts.isEmpty()) { |
|
1007 return false; |
|
1008 } |
|
1009 |
|
1010 if (!m_observed_folders.contains(folderId)) { |
|
1011 QDBusPendingCall pendingCall = m_QtmPluginDBusInterface->asyncCall("AddFolderObserver", |
|
1012 QVariant::fromValue(modestAccountIdFromFolderId(folderId)), |
|
1013 QVariant::fromValue(modestFolderIdFromFolderId(folderId))); |
|
1014 QDBusPendingCallWatcher pendingCallWatcher(pendingCall); |
|
1015 pendingCallWatcher.waitForFinished(); |
|
1016 |
|
1017 QDBusMessage msg = pendingCallWatcher.reply(); |
|
1018 |
|
1019 if (msg.type() == QDBusMessage::ReplyMessage) { |
|
1020 if (m_observed_folders.count() == 0) { |
|
1021 m_QtmPluginDBusInterface->connection().connect(MODESTENGINE_QTM_PLUGIN_NAME, |
|
1022 MODESTENGINE_QTM_PLUGIN_PATH, |
|
1023 MODESTENGINE_QTM_PLUGIN_NAME, |
|
1024 "FolderContentsChanged", |
|
1025 (ModestEngine*)this, |
|
1026 SLOT(modestFolderContentsChangedSlot(QDBusMessage))); |
|
1027 } |
|
1028 |
|
1029 m_observed_folders.append(folderId); |
|
1030 |
|
1031 return true; |
|
1032 } |
|
1033 } else { |
|
1034 return true; |
|
1035 } |
|
1036 |
|
1037 return false; |
|
1038 } |
|
1039 |
|
1040 bool ModestEngine::stopObservingModestFolder(const QMessageFolderId& folderId) const |
|
1041 { |
|
1042 if (!m_QtmPluginDBusInterface->isValid() || iAccounts.isEmpty()) { |
|
1043 return false; |
|
1044 } |
|
1045 |
|
1046 if (m_observed_folders.contains(folderId)) { |
|
1047 QDBusPendingCall pendingCall = m_QtmPluginDBusInterface->asyncCall("RemoveFolderObserver", |
|
1048 QVariant::fromValue(modestAccountIdFromFolderId(folderId)), |
|
1049 QVariant::fromValue(modestFolderIdFromFolderId(folderId))); |
|
1050 QDBusPendingCallWatcher pendingCallWatcher(pendingCall); |
|
1051 pendingCallWatcher.waitForFinished(); |
|
1052 |
|
1053 QDBusMessage msg = pendingCallWatcher.reply(); |
|
1054 |
|
1055 if (msg.type() == QDBusMessage::ReplyMessage) { |
|
1056 m_observed_folders.removeOne(folderId); |
|
1057 |
|
1058 if (m_observed_folders.count() == 0) { |
|
1059 m_QtmPluginDBusInterface->connection().disconnect(MODESTENGINE_QTM_PLUGIN_NAME, |
|
1060 MODESTENGINE_QTM_PLUGIN_PATH, |
|
1061 MODESTENGINE_QTM_PLUGIN_NAME, |
|
1062 "FolderContentsChanged", |
|
1063 (ModestEngine*)this, |
|
1064 SLOT(modestFolderContentsChangedSlot(QDBusMessage))); |
|
1065 } |
|
1066 |
|
1067 return true; |
|
1068 } |
|
1069 } |
|
1070 |
|
1071 return false; |
|
1072 } |
|
1073 |
|
1074 void ModestEngine::modestFolderContentsChangedSlot(QDBusMessage msg) |
|
1075 { |
|
1076 QList<QVariant> arguments = msg.arguments(); |
|
1077 |
|
1078 QString modestAccountId = arguments.takeFirst().toString(); |
|
1079 QString modestFolderId = arguments.takeFirst().toString(); |
|
1080 QMessageAccountId accountId = accountIdFromModestAccountId(modestAccountId); |
|
1081 QString protocol = accountEmailProtocolAsString(accountId); |
|
1082 if ((protocol == "pop") && (modestFolderId == "INBOX")) { |
|
1083 modestFolderId = "cache"; |
|
1084 } |
|
1085 QString folderId = accountId.toString()+"&"+accountEmailProtocolAsString(accountId)+"&"+modestFolderId; |
|
1086 |
|
1087 qlonglong change = arguments.takeFirst().toLongLong(); |
|
1088 QVariant variant = arguments.takeFirst(); |
|
1089 QList<QString> messageIds = variant.toStringList(); |
|
1090 if (change == 4) { // Headers added |
|
1091 for (int i = 0; i < messageIds.count(); i++) { |
|
1092 QMessageId messageId = folderId+"/"+messageIds[i]; |
|
1093 notification(messageId, ModestEngine::Added); |
|
1094 } |
|
1095 }/* else if (change == 8) { // Headers removed |
|
1096 for (int i = 0; i < messageIds.count(); i++) { |
|
1097 QMessageId messageId = folderId+"/"+messageIds[i]; |
|
1098 notification(messageId, ModestEngine::Removed); |
|
1099 } |
|
1100 }*/ |
|
1101 } |
|
1102 |
|
1103 void ModestEngine::watchAllKnownEmailFolders() |
|
1104 { |
|
1105 QFileInfoList localFolders = this->localFolders(); |
|
1106 |
|
1107 // Changes in local Email folders can be monitored using directory |
|
1108 // monitoring. <=> All messages are stored as individual files. |
|
1109 for (int i=0; i < localFolders.count(); i++) { |
|
1110 m_MailFoldersWatcher.addDirectory(localFolders[i].absoluteFilePath()+"/cur", IN_MOVED_TO | IN_DELETE); |
|
1111 } |
|
1112 |
|
1113 // Monitor changes also in root folder to see if new folders are added |
|
1114 m_MailFoldersWatcher.addDirectory(localRootFolder(), IN_CREATE); |
|
1115 |
|
1116 // Changes in remote Email folders must be monitored using file monitoring. |
|
1117 // That's because message headers are stored into summary.mmap file (and summary.mmap |
|
1118 // file maybe the only place that contains message information). |
|
1119 // => summary.mmap files will be monitored |
|
1120 foreach (QMessageAccount value, iAccounts) { |
|
1121 QMessageAccountId accountId = value.id(); |
|
1122 QString rootFolder = accountRootFolder(accountId); |
|
1123 EmailProtocol protocol = accountEmailProtocol(accountId); |
|
1124 QFileInfoList folders = this->accountFolders(accountId); |
|
1125 |
|
1126 for (int i=0; i < folders.count(); i++) { |
|
1127 if (protocol == ModestEngine::EmailProtocolPop3) { |
|
1128 QString folder = folders[i].absoluteFilePath(); |
|
1129 m_MailFoldersWatcher.addDirectory(folder, IN_CREATE); |
|
1130 } else if (protocol == ModestEngine::EmailProtocolIMAP) { |
|
1131 m_MailFoldersWatcher.addDirectory(folders[i].absoluteFilePath(), IN_MOVED_TO | IN_DELETE); |
|
1132 } |
|
1133 } |
|
1134 |
|
1135 } |
|
1136 } |
|
1137 |
|
1138 void ModestEngine::fileChangedSlot(int watchDescriptor, QString filePath, uint events) |
|
1139 { |
|
1140 Q_UNUSED(watchDescriptor) |
|
1141 |
|
1142 if (events & IN_CREATE) { |
|
1143 if (QFileInfo(filePath).isDir()) { |
|
1144 // New directory was added |
|
1145 // => Start watching new folder |
|
1146 QString newDirPath = QString(filePath.toUtf8()); |
|
1147 m_MailFoldersWatcher.addDirectory(newDirPath + "/cur"); |
|
1148 } |
|
1149 } |
|
1150 |
|
1151 int filenameBegin = filePath.lastIndexOf('/')+1; |
|
1152 QString fileName = filePath.mid(filenameBegin,filePath.lastIndexOf('.')-filenameBegin); |
|
1153 if (!fileName.endsWith("summary")) { |
|
1154 if (events & (IN_MOVED_TO | IN_CREATE)) { |
|
1155 if (events != (IN_MOVED_TO | IN_MOVED_FROM)) { |
|
1156 // Wait a moment to make sure that Modest has finished adding message |
|
1157 QEventLoop eventLoop; |
|
1158 QTimer::singleShot(100, &eventLoop, SLOT(quit())); |
|
1159 eventLoop.exec(); |
|
1160 notification(messageIdFromModestMessageFilePath(filePath), ModestEngine::Added); |
|
1161 } |
|
1162 } else if (events & IN_DELETE) { |
|
1163 notification(messageIdFromModestMessageFilePath(filePath), ModestEngine::Removed); |
|
1164 } |
|
1165 } |
|
1166 } |
|
1167 |
|
1168 bool ModestEngine::sendEmail(QMessage &message) |
|
1169 { |
|
1170 if (!m_QtmPluginDBusInterface->isValid() || iAccounts.isEmpty()) { |
|
1171 return false; |
|
1172 } |
|
1173 |
|
1174 ModestStringMap senderInfo; |
|
1175 ModestStringMap recipients; |
|
1176 ModestStringMap messageData; |
|
1177 ModestStringMapList attachments; |
|
1178 ModestStringMapList images; |
|
1179 uint priority = 0; |
|
1180 ModestStringMap headers; |
|
1181 |
|
1182 senderInfo = getModestSenderInfo(message); |
|
1183 |
|
1184 if (senderInfo.isEmpty()) { |
|
1185 return false; |
|
1186 } |
|
1187 |
|
1188 recipients = getModestRecipients(message); |
|
1189 |
|
1190 if (recipients.isEmpty()) { |
|
1191 return false; |
|
1192 } |
|
1193 |
|
1194 messageData = getModestMessageData(message); |
|
1195 attachments = getModestAttachments(message); |
|
1196 images = getModestImages(message); |
|
1197 priority = getModestPriority(message); |
|
1198 headers = getModestHeaders(message); |
|
1199 |
|
1200 qDebug() << "Sending D-BUS message"; |
|
1201 |
|
1202 QDBusPendingCall call = m_QtmPluginDBusInterface->asyncCall ( |
|
1203 "SendEmail", |
|
1204 QVariant::fromValue (senderInfo), |
|
1205 QVariant::fromValue (recipients), |
|
1206 QVariant::fromValue (messageData), |
|
1207 QVariant::fromValue (attachments), |
|
1208 QVariant::fromValue (images), |
|
1209 priority, |
|
1210 QVariant::fromValue (headers)); |
|
1211 |
|
1212 qDebug() << "Message sent"; |
|
1213 |
|
1214 if (call.isError()) { |
|
1215 qWarning() << "Call failed! " << call.error(); |
|
1216 return false; |
|
1217 } |
|
1218 |
|
1219 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher (call, this); |
|
1220 |
|
1221 connect (watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), |
|
1222 this, SLOT(sendEmailCallEnded(QDBusPendingCallWatcher*))); |
|
1223 |
|
1224 return true; |
|
1225 } |
|
1226 |
|
1227 bool ModestEngine::composeEmail(const QMessage &message) |
|
1228 { |
|
1229 QString mailString("mailto:"); |
|
1230 QList<QMessageAddress> list(message.to()); |
|
1231 if (!list.empty()){ |
|
1232 for (int i = 0; i < list.size(); ++i) { |
|
1233 if (i == 0) { |
|
1234 mailString += list.at(i).addressee(); |
|
1235 } else { |
|
1236 mailString += QString("%2C%20"); |
|
1237 mailString += list.at(i).addressee(); |
|
1238 } |
|
1239 } |
|
1240 } |
|
1241 |
|
1242 bool firstParameter = true; |
|
1243 |
|
1244 QString subject = message.subject(); |
|
1245 if (!subject.isEmpty()) { |
|
1246 if (firstParameter) { |
|
1247 mailString += QString("?"); |
|
1248 firstParameter = false; |
|
1249 } else { |
|
1250 mailString += QString("&"); |
|
1251 } |
|
1252 mailString += QString("subject="); |
|
1253 mailString += subject; |
|
1254 } |
|
1255 |
|
1256 QString body = message.textContent(); |
|
1257 if (!body.isEmpty()) { |
|
1258 if (firstParameter) { |
|
1259 mailString += QString("?"); |
|
1260 firstParameter = false; |
|
1261 } else { |
|
1262 mailString += QString("&"); |
|
1263 } |
|
1264 mailString += QString("body="); |
|
1265 mailString += QString(body); |
|
1266 } |
|
1267 |
|
1268 QUrl url(mailString); |
|
1269 |
|
1270 QDBusInterface dbusif(MODEST_DBUS_SERVICE, MODEST_DBUS_OBJECT, MODEST_DBUS_IFACE); |
|
1271 QDBusMessage msg = dbusif.call(MODEST_DBUS_METHOD_MAIL_TO, url.toString()); |
|
1272 |
|
1273 return true; |
|
1274 } |
|
1275 |
|
1276 bool ModestEngine::showMessage(const QMessageId &id) |
|
1277 { |
|
1278 QMessage msg = message(id, false); |
|
1279 QMessagePrivate* privateMessage = QMessagePrivate::implementation(msg); |
|
1280 if (privateMessage->_url.isEmpty()) { |
|
1281 return false; |
|
1282 } else { |
|
1283 m_ModestDBusInterface->call(MODEST_DBUS_METHOD_OPEN_MESSAGE, |
|
1284 privateMessage->_url); |
|
1285 } |
|
1286 return true; |
|
1287 } |
|
1288 |
|
1289 bool ModestEngine::exportUpdates(const QMessageAccountId &id) |
|
1290 { |
|
1291 Q_UNUSED(id) // Modest does not offer Account specific updates |
|
1292 |
|
1293 m_ModestDBusInterface->call(MODEST_DBUS_METHOD_SEND_RECEIVE); |
|
1294 return true; |
|
1295 } |
|
1296 |
|
1297 QMessage ModestEngine::message(const QMessageId &id, bool useCache) const |
|
1298 { |
|
1299 if (useCache) { |
|
1300 QMessage message = m_messageCache.value(id.toString()); |
|
1301 if (message.type() != QMessage::NoType) { |
|
1302 return message; |
|
1303 } |
|
1304 } |
|
1305 |
|
1306 QString modestAccountId = modestAccountIdFromMessageId(id); |
|
1307 QString modestFolderId = modestFolderIdFromMessageId(id); |
|
1308 QString modestMessageId = modestMessageIdFromMessageId(id); |
|
1309 |
|
1310 MessagingModestMessage modestMessage = messageFromModest(modestAccountId, |
|
1311 modestFolderId, |
|
1312 modestMessageId); |
|
1313 |
|
1314 if (modestMessage.flags & MessagingModestMessageDeleted) { |
|
1315 return QMessage(); |
|
1316 } |
|
1317 |
|
1318 if (modestMessage.accountId.isEmpty()) { |
|
1319 return QMessage(); |
|
1320 } |
|
1321 |
|
1322 return messageFromModestMessage(modestMessage, accountIdFromMessageId(id)); |
|
1323 } |
|
1324 |
|
1325 QMessage::StandardFolder ModestEngine::standardFolderFromModestFolderId(const QString& modestFolderId) const |
|
1326 { |
|
1327 if (!QString::compare(modestFolderId, "INBOX", Qt::CaseInsensitive)) { |
|
1328 return QMessage::InboxFolder; |
|
1329 } else if (!QString::compare(modestFolderId, "drafts", Qt::CaseInsensitive)) { |
|
1330 return QMessage::DraftsFolder; |
|
1331 } else if (!QString::compare(modestFolderId, "sent", Qt::CaseInsensitive)) { |
|
1332 return QMessage::SentFolder; |
|
1333 } |
|
1334 |
|
1335 return QMessage::DraftsFolder; |
|
1336 } |
|
1337 |
|
1338 QString ModestEngine::modestFolderIdFromStandardFolder(QMessage::StandardFolder standardFolder) const |
|
1339 { |
|
1340 switch (standardFolder) { |
|
1341 case QMessage::InboxFolder: return "INBOX"; |
|
1342 case QMessage::DraftsFolder: return "drafts"; |
|
1343 case QMessage::SentFolder: return "sent"; |
|
1344 case QMessage::OutboxFolder: return "outbox"; |
|
1345 case QMessage::TrashFolder: return "thrash"; |
|
1346 } |
|
1347 return "drafts"; |
|
1348 } |
|
1349 |
|
1350 QMessage ModestEngine::messageFromModestMessage(const MessagingModestMessage& modestMessage, |
|
1351 QMessageAccountId accountId) const |
|
1352 { |
|
1353 QMessage message; |
|
1354 QMessagePrivate* privateMessage = QMessagePrivate::implementation(message); |
|
1355 QMessageContentContainerPrivate* container = QMessagePrivate::containerImplementation(message); |
|
1356 |
|
1357 // Type |
|
1358 message.setType(QMessage::Email); |
|
1359 |
|
1360 // Parent Account Id |
|
1361 QMessageAccountId parentAccountId; |
|
1362 if (accountId.isValid()) { |
|
1363 parentAccountId = accountId; |
|
1364 } else { |
|
1365 parentAccountId = realAccountId(modestMessage); |
|
1366 } |
|
1367 message.setParentAccountId(parentAccountId); |
|
1368 |
|
1369 // Parent Folder Id |
|
1370 QMessageFolderId folderId; |
|
1371 if (modestMessage.accountId == "local_folders") { |
|
1372 folderId = folderIdFromModestFolderId(parentAccountId, true, modestMessage.folderId); |
|
1373 } else { |
|
1374 // Since Message is not in local folder, message status can be set to Incoming |
|
1375 privateMessage->_status = privateMessage->_status | QMessage::Incoming; |
|
1376 folderId = folderIdFromModestFolderId(parentAccountId, false, modestMessage.folderId); |
|
1377 } |
|
1378 privateMessage->_parentFolderId = folderId; |
|
1379 |
|
1380 // Message Id |
|
1381 QMessageId messageId = QMessageId(folderId.toString()+"/"+modestMessage.id); |
|
1382 privateMessage->_id = messageId; |
|
1383 |
|
1384 // Dates |
|
1385 message.setDate(QDateTime::fromTime_t(modestMessage.dateSent)); |
|
1386 message.setReceivedDate(QDateTime::fromTime_t(modestMessage.dateReceived)); |
|
1387 |
|
1388 // Priority |
|
1389 switch (modestMessage.priority) { |
|
1390 case QtMobility::MessagingModestMessageHighPriority: |
|
1391 message.setPriority(QMessage::HighPriority); |
|
1392 break; |
|
1393 case QtMobility::MessagingModestMessageNormalPriority: |
|
1394 message.setPriority(QMessage::NormalPriority); |
|
1395 break; |
|
1396 case QtMobility::MessagingModestMessageLowPriority: |
|
1397 message.setPriority(QMessage::LowPriority); |
|
1398 break; |
|
1399 } |
|
1400 |
|
1401 // Message MIME type |
|
1402 QString fullMimeType = modestMessage.mimeType; |
|
1403 int slashIndex = fullMimeType.indexOf('/'); |
|
1404 QByteArray mimeType = fullMimeType.left(slashIndex).toAscii(); |
|
1405 QByteArray mimeSubType = fullMimeType.mid(slashIndex+1).toAscii(); |
|
1406 container->_type = mimeType.data(); |
|
1407 container->_subType = mimeSubType.data(); |
|
1408 |
|
1409 // Standard Folder |
|
1410 QMessagePrivate::setStandardFolder(message, |
|
1411 standardFolderFromModestFolderId(modestMessage.folderId)); |
|
1412 |
|
1413 // Body & Attachments handling |
|
1414 for (int i=0; i < modestMessage.mimeParts.count(); i++) { |
|
1415 if (!modestMessage.mimeParts[i].isAttachment) { |
|
1416 // Body |
|
1417 QByteArray fullMimeType = modestMessage.mimeParts[i].mimeType.toUtf8(); |
|
1418 QString contentId = modestMessage.mimeParts[i].contentId; |
|
1419 QByteArray fileName = modestMessage.mimeParts[i].fileName.toAscii(); |
|
1420 |
|
1421 QByteArray mainType("text"); |
|
1422 QByteArray subType("plain"); |
|
1423 QByteArray charset; |
|
1424 |
|
1425 int index = fullMimeType.indexOf("/"); |
|
1426 if (index != -1) { |
|
1427 mainType = fullMimeType.left(index).trimmed(); |
|
1428 |
|
1429 subType = fullMimeType.mid(index + 1).trimmed(); |
|
1430 index = subType.indexOf(";"); |
|
1431 if (index != -1) { |
|
1432 QString remainder = subType.mid(index + 1); |
|
1433 subType = subType.left(index).trimmed(); |
|
1434 |
|
1435 QRegExp charsetPattern("charset=(\\S+)"); |
|
1436 index = charsetPattern.indexIn(remainder); |
|
1437 if (index != -1) { |
|
1438 charset = charsetPattern.cap(1).toLatin1().toUpper(); |
|
1439 } |
|
1440 } |
|
1441 } |
|
1442 |
|
1443 if (charset.isEmpty()) { |
|
1444 charset = "UTF-8"; |
|
1445 } |
|
1446 |
|
1447 // Accept only text type Body |
|
1448 if (mainType.toLower() == "text") { |
|
1449 QMessageContentContainerId existingBodyId(message.bodyId()); |
|
1450 if (existingBodyId.isValid()) { |
|
1451 if (existingBodyId == QMessageContentContainerPrivate::bodyContentId()) { |
|
1452 // The body content is in the message itself |
|
1453 container->_containingMessageId = messageId.toString(); |
|
1454 container->_attachmentId = contentId; |
|
1455 container->_name = fileName; |
|
1456 container->_type = mainType; |
|
1457 container->_subType = subType; |
|
1458 container->_charset = charset; |
|
1459 container->_size = 0; |
|
1460 container->_available = true; |
|
1461 } else { |
|
1462 // The body content is in the first attachment |
|
1463 QMessageContentContainerPrivate *attachmentContainer(QMessageContentContainerPrivate::implementation(*container->attachment(existingBodyId))); |
|
1464 attachmentContainer->_containingMessageId = messageId.toString(); |
|
1465 attachmentContainer->_attachmentId = contentId; |
|
1466 attachmentContainer->_name = fileName; |
|
1467 attachmentContainer->_type = mainType; |
|
1468 attachmentContainer->_subType = subType; |
|
1469 attachmentContainer->_charset = charset; |
|
1470 attachmentContainer->_size = 0; |
|
1471 attachmentContainer->_available = true; |
|
1472 } |
|
1473 } else { |
|
1474 if (container->_attachments.isEmpty()) { |
|
1475 // Put the content directly into the message |
|
1476 container->_containingMessageId = messageId.toString(); |
|
1477 container->_attachmentId = contentId; |
|
1478 container->_name = fileName; |
|
1479 container->_type = mainType; |
|
1480 container->_subType = subType; |
|
1481 container->_charset = charset; |
|
1482 container->_size = 0; |
|
1483 container->_available = true; |
|
1484 privateMessage->_bodyId = QMessageContentContainerPrivate::bodyContentId(); |
|
1485 } else { |
|
1486 // Add the body as the first attachment |
|
1487 QMessageContentContainer newBody; |
|
1488 QMessageContentContainerPrivate *attachmentContainer = QMessageContentContainerPrivate::implementation(newBody); |
|
1489 attachmentContainer->_containingMessageId = messageId.toString(); |
|
1490 attachmentContainer->_attachmentId = contentId; |
|
1491 attachmentContainer->_name = fileName; |
|
1492 attachmentContainer->_type = mainType; |
|
1493 attachmentContainer->_subType = subType; |
|
1494 attachmentContainer->_charset = charset; |
|
1495 attachmentContainer->_size = 0; |
|
1496 attachmentContainer->_available = true; |
|
1497 privateMessage->_bodyId = container->prependContent(newBody); |
|
1498 } |
|
1499 } |
|
1500 } |
|
1501 } else { |
|
1502 // Attachment |
|
1503 QString fullMimeType = modestMessage.mimeParts[i].mimeType; |
|
1504 QString contentId = modestMessage.mimeParts[i].contentId; |
|
1505 int slashIndex = fullMimeType.indexOf('/'); |
|
1506 QByteArray mimeType = fullMimeType.left(slashIndex).toAscii(); |
|
1507 QByteArray mimeSubType = fullMimeType.mid(slashIndex+1).toAscii(); |
|
1508 // TODO: Attachment size |
|
1509 QByteArray fileName = modestMessage.mimeParts[i].fileName.toAscii(); |
|
1510 fileName = fileName.mid(fileName.lastIndexOf('/')+1); |
|
1511 QString msgId = messageId.toString(); |
|
1512 QMessageContentContainer attachment = |
|
1513 QMessageContentContainerPrivate::from(msgId, |
|
1514 contentId, |
|
1515 fileName, |
|
1516 mimeType, |
|
1517 mimeSubType, |
|
1518 0); |
|
1519 appendAttachmentToMessage(message, attachment); |
|
1520 } |
|
1521 } |
|
1522 |
|
1523 // From |
|
1524 if (modestMessage.from.size() > 0) { |
|
1525 message.setFrom(QMessageAddress(QMessageAddress::Email, modestMessage.from)); |
|
1526 QMessagePrivate::setSenderName(message, modestMessage.from); |
|
1527 } |
|
1528 |
|
1529 // To |
|
1530 if (modestMessage.to.size() > 0) { |
|
1531 QMessageAddressList toAddresses; |
|
1532 foreach (const QString &element, modestMessage.to.split(",", QString::SkipEmptyParts)) { |
|
1533 QMessageAddress addr; |
|
1534 addr.setType(QMessageAddress::Email); |
|
1535 addr.setAddressee(element.trimmed()); |
|
1536 toAddresses.append(addr); |
|
1537 } |
|
1538 message.setTo(toAddresses); |
|
1539 } |
|
1540 |
|
1541 // Cc |
|
1542 if (modestMessage.cc.size() > 0) { |
|
1543 QMessageAddressList ccAddresses; |
|
1544 foreach (const QString &element, modestMessage.cc.split(",", QString::SkipEmptyParts)) { |
|
1545 QMessageAddress addr; |
|
1546 addr.setType(QMessageAddress::Email); |
|
1547 addr.setAddressee(element.trimmed()); |
|
1548 ccAddresses.append(addr); |
|
1549 } |
|
1550 message.setCc(ccAddresses); |
|
1551 } |
|
1552 |
|
1553 // Bcc |
|
1554 if (modestMessage.bcc.size() > 0) { |
|
1555 QMessageAddressList bccAddresses; |
|
1556 foreach (const QString &element, modestMessage.bcc.split(",", QString::SkipEmptyParts)) { |
|
1557 QMessageAddress addr; |
|
1558 addr.setType(QMessageAddress::Email); |
|
1559 addr.setAddressee(element.trimmed()); |
|
1560 bccAddresses.append(addr); |
|
1561 } |
|
1562 message.setBcc(bccAddresses); |
|
1563 } |
|
1564 |
|
1565 // Subject |
|
1566 message.setSubject(modestMessage.subject); |
|
1567 |
|
1568 // Size |
|
1569 privateMessage->_size = modestMessage.size; |
|
1570 |
|
1571 // Read Status |
|
1572 if (modestMessage.flags & MessagingModestMessageSeen) { |
|
1573 privateMessage->_status = privateMessage->_status | QMessage::Read; |
|
1574 } |
|
1575 |
|
1576 // Attachments Status |
|
1577 if (modestMessage.flags & MessagingModestMessageAttachments) { |
|
1578 privateMessage->_status = privateMessage->_status | QMessage::HasAttachments; |
|
1579 } |
|
1580 |
|
1581 // Modest specific url |
|
1582 privateMessage->_url = modestMessage.url; |
|
1583 |
|
1584 // Modified flag |
|
1585 privateMessage->_modified = false; |
|
1586 |
|
1587 return message; |
|
1588 } |
|
1589 |
|
1590 void ModestEngine::appendAttachmentToMessage(QMessage& message, QMessageContentContainer& attachment) const |
|
1591 { |
|
1592 QMessagePrivate* privateMessage = QMessagePrivate::implementation(message); |
|
1593 QMessageContentContainerPrivate* container = QMessagePrivate::containerImplementation(message); |
|
1594 |
|
1595 if (container->_attachments.isEmpty()) { |
|
1596 QMessageContentContainerId existingBodyId(message.bodyId()); |
|
1597 if (existingBodyId == QMessageContentContainerPrivate::bodyContentId()) { |
|
1598 // The body content is in the message itself - move it to become the first attachment |
|
1599 QMessageContentContainer newBody(message); |
|
1600 QMessageContentContainerPrivate::implementation(newBody)->setDerivedMessage(0); |
|
1601 |
|
1602 container->setContentType("multipart", "mixed", ""); |
|
1603 privateMessage->_bodyId = container->prependContent(newBody); |
|
1604 } else { |
|
1605 // This message is now multipart |
|
1606 container->setContentType("multipart", "mixed", ""); |
|
1607 } |
|
1608 |
|
1609 container->_available = true; |
|
1610 } |
|
1611 |
|
1612 container->appendContent(attachment); |
|
1613 |
|
1614 bool haveAttachments = !container->_attachments.isEmpty(); |
|
1615 message.setStatus(QMessage::HasAttachments,haveAttachments); |
|
1616 |
|
1617 privateMessage->_modified = true; |
|
1618 } |
|
1619 |
|
1620 bool ModestEngine::addMessage(QMessage &message) |
|
1621 { |
|
1622 if (!m_QtmPluginDBusInterface->isValid() || iAccounts.isEmpty()) { |
|
1623 return false; |
|
1624 } |
|
1625 |
|
1626 QString modestFolder; |
|
1627 ModestStringMap senderInfo; |
|
1628 ModestStringMap recipients; |
|
1629 ModestStringMap messageData; |
|
1630 ModestStringMapList attachments; |
|
1631 ModestStringMapList images; |
|
1632 uint priority = 0; |
|
1633 ModestStringMap headers; |
|
1634 |
|
1635 qDebug() << __PRETTY_FUNCTION__; |
|
1636 |
|
1637 senderInfo = getModestSenderInfo (message); |
|
1638 recipients = getModestRecipients (message); |
|
1639 messageData = getModestMessageData (message); |
|
1640 attachments = getModestAttachments (message); |
|
1641 images = getModestImages (message); |
|
1642 priority = getModestPriority (message); |
|
1643 headers = getModestHeaders (message); |
|
1644 |
|
1645 QString accountName; |
|
1646 if (message.parentFolderId().isValid()) { |
|
1647 modestFolder = modestFolderIdFromFolderId (message.parentFolderId()); |
|
1648 accountName = modestAccountIdFromFolderId(message.parentFolderId()); |
|
1649 } else { |
|
1650 modestFolder = modestFolderIdFromStandardFolder(message.standardFolder()); |
|
1651 if (message.standardFolder() == QMessage::DraftsFolder) { |
|
1652 accountName = "local_folders"; |
|
1653 } else { |
|
1654 accountName = modestAccountIdFromAccountId(message.parentAccountId()); |
|
1655 } |
|
1656 } |
|
1657 senderInfo["account-name"] = accountName; |
|
1658 |
|
1659 QList<QVariant> arguments; |
|
1660 arguments << modestFolder; |
|
1661 arguments << QVariant::fromValue(senderInfo); |
|
1662 arguments << QVariant::fromValue(recipients); |
|
1663 arguments << QVariant::fromValue(messageData); |
|
1664 arguments << QVariant::fromValue(attachments); |
|
1665 arguments << QVariant::fromValue(images); |
|
1666 arguments << priority; |
|
1667 arguments << QVariant::fromValue(headers); |
|
1668 |
|
1669 QDBusPendingCall pendingCall = m_QtmPluginDBusInterface->asyncCallWithArgumentList("AddMessage", |
|
1670 arguments); |
|
1671 |
|
1672 if (pendingCall.isError()) { |
|
1673 qWarning() << "DBus call failed! " << pendingCall.error(); |
|
1674 return false; |
|
1675 } |
|
1676 |
|
1677 QDBusPendingCallWatcher pendingCallWatcher(pendingCall); |
|
1678 pendingCallWatcher.waitForFinished(); |
|
1679 QDBusMessage msg = pendingCallWatcher.reply(); |
|
1680 if (msg.type() == QDBusMessage::ErrorMessage) { |
|
1681 qWarning() << "Failed to add message via modest: " << msg.errorMessage(); |
|
1682 return false; |
|
1683 } |
|
1684 |
|
1685 QMessagePrivate* privateMessage = QMessagePrivate::implementation(message); |
|
1686 QString messageId; |
|
1687 if (message.parentFolderId().isValid()) { |
|
1688 messageId = message.parentFolderId().toString()+"/"+msg.arguments()[0].toString(); |
|
1689 } else if (accountName == "local_folders") { |
|
1690 messageId = message.parentAccountId().toString()+ |
|
1691 "&maildir&"+modestFolder+"/"+msg.arguments()[0].toString(); |
|
1692 } else { |
|
1693 messageId = message.parentAccountId().toString()+"&"+ |
|
1694 accountEmailProtocolAsString(message.parentAccountId())+ |
|
1695 "&"+modestFolder+"/"+msg.arguments()[0].toString(); |
|
1696 } |
|
1697 privateMessage->_id = QMessageId(messageId); |
|
1698 |
|
1699 // Use update functionality to set Priority & Read status |
|
1700 // <=> Modest Plugin can not set Priority & Read status |
|
1701 // immediately after message creation in add call |
|
1702 updateMessage(message); |
|
1703 |
|
1704 return true; |
|
1705 } |
|
1706 |
|
1707 bool ModestEngine::updateMessage(QMessage &message) |
|
1708 { |
|
1709 if (!m_QtmPluginDBusInterface->isValid() || iAccounts.isEmpty()) { |
|
1710 return false; |
|
1711 } |
|
1712 |
|
1713 if (!message.id().isValid()) { |
|
1714 return false; |
|
1715 } |
|
1716 |
|
1717 QString modestAccountId = modestAccountIdFromMessageId(message.id()); |
|
1718 QString modestFolderId = modestFolderIdFromMessageId(message.id()); |
|
1719 QString modestMessageId = modestMessageIdFromMessageId(message.id()); |
|
1720 |
|
1721 QString modestFolder; |
|
1722 ModestStringMap senderInfo; |
|
1723 ModestStringMap recipients; |
|
1724 ModestStringMap messageData; |
|
1725 ModestStringMapList attachments; |
|
1726 ModestStringMapList images; |
|
1727 uint priority = 0; |
|
1728 ModestStringMap headers; |
|
1729 |
|
1730 qDebug() << __PRETTY_FUNCTION__; |
|
1731 |
|
1732 // Only read status & priority can be updated using Modest |
|
1733 if (message.status() & QMessage::Read) { |
|
1734 messageData["read"] = ""; |
|
1735 } |
|
1736 priority = getModestPriority (message); |
|
1737 |
|
1738 QList<QVariant> arguments; |
|
1739 arguments << QVariant::fromValue(modestAccountId); |
|
1740 arguments << QVariant::fromValue(modestFolderId); |
|
1741 arguments << QVariant::fromValue(modestMessageId); |
|
1742 arguments << QVariant::fromValue(senderInfo); |
|
1743 arguments << QVariant::fromValue(recipients); |
|
1744 arguments << QVariant::fromValue(messageData); |
|
1745 arguments << QVariant::fromValue(attachments); |
|
1746 arguments << QVariant::fromValue(images); |
|
1747 arguments << priority; |
|
1748 arguments << QVariant::fromValue(headers); |
|
1749 |
|
1750 QDBusPendingCall pendingCall = m_QtmPluginDBusInterface->asyncCallWithArgumentList("UpdateMessage", |
|
1751 arguments); |
|
1752 |
|
1753 if (pendingCall.isError()) { |
|
1754 qWarning() << "DBus call failed! " << pendingCall.error(); |
|
1755 return false; |
|
1756 } |
|
1757 |
|
1758 QDBusPendingCallWatcher pendingCallWatcher(pendingCall); |
|
1759 pendingCallWatcher.waitForFinished(); |
|
1760 QDBusMessage msg = pendingCallWatcher.reply(); |
|
1761 if (msg.type() == QDBusMessage::ErrorMessage) { |
|
1762 qWarning() << "Failed to update message via modest: " << msg.errorMessage(); |
|
1763 return false; |
|
1764 } |
|
1765 |
|
1766 return true; |
|
1767 } |
|
1768 |
|
1769 bool ModestEngine::removeMessage(const QMessageId &id, QMessageManager::RemovalOption option) |
|
1770 { |
|
1771 Q_UNUSED(option) // TODO: |
|
1772 |
|
1773 QMessage msg = message(id, false); |
|
1774 QMessagePrivate* privateMessage = QMessagePrivate::implementation(msg); |
|
1775 if (privateMessage->_url.isEmpty()) { |
|
1776 return false; |
|
1777 } else { |
|
1778 m_ModestDBusInterface->call(MODEST_DBUS_METHOD_DELETE_MESSAGE, |
|
1779 privateMessage->_url); |
|
1780 // Make sure that there will instant notification about removed message |
|
1781 notification(id, ModestEngine::Removed); |
|
1782 } |
|
1783 return true; |
|
1784 } |
|
1785 |
|
1786 bool ModestEngine::filterMessage(const QMessage& message, QMessageFilterPrivate::SortedMessageFilterList filterList, int start) const |
|
1787 { |
|
1788 if (filterList.count() > start) { |
|
1789 for (int j=start; j < filterList.count(); j++) { |
|
1790 QMessageFilterPrivate* pf = QMessageFilterPrivate::implementation(filterList[j]); |
|
1791 if (!pf->filter(message)) { |
|
1792 return false; |
|
1793 } |
|
1794 } |
|
1795 } |
|
1796 return true; |
|
1797 } |
|
1798 |
|
1799 QMessageIdList ModestEngine::queryMessagesSync(const QMessageFilter &filter, const QMessageSortOrder &sortOrder, |
|
1800 uint limit, uint offset, bool &isFiltered, bool &isSorted) const |
|
1801 { |
|
1802 QMessageIdList ids; |
|
1803 |
|
1804 if (!m_QtmPluginDBusInterface->isValid() || iAccounts.isEmpty()) { |
|
1805 return ids; |
|
1806 } |
|
1807 |
|
1808 QMessageServicePrivate* privateService = QMessageServicePrivate::implementation(m_service); |
|
1809 if (privateService->queryMessages(m_service, filter, sortOrder, limit, offset, |
|
1810 QMessageServicePrivate::EnginesToCallModest)) { |
|
1811 QObject::connect(&m_service, SIGNAL(stateChanged(QMessageService::State)), |
|
1812 this, SLOT(stateChanged(QMessageService::State))); |
|
1813 |
|
1814 m_eventLoop.exec(); |
|
1815 |
|
1816 isSorted = m_isSorted; |
|
1817 isFiltered = m_isFiltered; |
|
1818 ids = m_ids; |
|
1819 m_ids.clear(); |
|
1820 } |
|
1821 |
|
1822 return ids; |
|
1823 } |
|
1824 |
|
1825 QMessageIdList ModestEngine::queryMessagesSync(const QMessageFilter &filter, const QString &body, |
|
1826 QMessageDataComparator::MatchFlags matchFlags, |
|
1827 const QMessageSortOrder &sortOrder, uint limit, uint offset, |
|
1828 bool &isFiltered, bool &isSorted) const |
|
1829 { |
|
1830 QMessageIdList ids; |
|
1831 |
|
1832 if (!m_QtmPluginDBusInterface->isValid() || iAccounts.isEmpty()) { |
|
1833 return ids; |
|
1834 } |
|
1835 |
|
1836 QMessageServicePrivate* privateService = QMessageServicePrivate::implementation(m_service); |
|
1837 if (privateService->queryMessages(m_service, filter, body, matchFlags, |
|
1838 sortOrder, limit, offset, |
|
1839 QMessageServicePrivate::EnginesToCallModest)) { |
|
1840 QObject::connect(&m_service, SIGNAL(stateChanged(QMessageService::State)), |
|
1841 this, SLOT(stateChanged(QMessageService::State))); |
|
1842 |
|
1843 m_eventLoop.exec(); |
|
1844 |
|
1845 isSorted = m_isSorted; |
|
1846 isFiltered = m_isFiltered; |
|
1847 ids = m_ids; |
|
1848 m_ids.clear(); |
|
1849 } |
|
1850 |
|
1851 return ids; |
|
1852 } |
|
1853 |
|
1854 int ModestEngine::countMessagesSync(const QMessageFilter &filter) const |
|
1855 { |
|
1856 int count; |
|
1857 |
|
1858 if (!m_QtmPluginDBusInterface->isValid() || iAccounts.isEmpty()) { |
|
1859 return 0; |
|
1860 } |
|
1861 |
|
1862 QMessageServicePrivate* privateService = QMessageServicePrivate::implementation(m_service); |
|
1863 if (privateService->countMessages(m_service, filter, QMessageServicePrivate::EnginesToCallModest)) { |
|
1864 QObject::connect(&m_service, SIGNAL(stateChanged(QMessageService::State)), |
|
1865 this, SLOT(stateChanged(QMessageService::State))); |
|
1866 |
|
1867 m_eventLoop.exec(); |
|
1868 |
|
1869 count = m_count; |
|
1870 } |
|
1871 |
|
1872 return count; |
|
1873 } |
|
1874 |
|
1875 void ModestEngine::stateChanged(QMessageService::State newState) |
|
1876 { |
|
1877 if (newState == QMessageService::FinishedState) { |
|
1878 QMessageServicePrivate* privateService = QMessageServicePrivate::implementation(m_service); |
|
1879 |
|
1880 m_ids = privateService->_ids; |
|
1881 m_isSorted = privateService->_sorted; |
|
1882 m_isFiltered = privateService->_filtered; |
|
1883 m_count = privateService->_count; |
|
1884 |
|
1885 m_eventLoop.quit(); |
|
1886 } |
|
1887 } |
|
1888 |
|
1889 bool ModestEngine::queryMessages(QMessageService& messageService, const QMessageFilter &filter, const QMessageSortOrder &sortOrder, uint limit, uint offset) const |
|
1890 { |
|
1891 return queryMessages(messageService, filter, QString(), 0, sortOrder, limit, offset); |
|
1892 } |
|
1893 |
|
1894 bool ModestEngine::countMessages(QMessageService& messageService, const QMessageFilter &filter) |
|
1895 { |
|
1896 if (!m_QtmPluginDBusInterface->isValid() || iAccounts.isEmpty()) { |
|
1897 return false; |
|
1898 } |
|
1899 |
|
1900 m_pendingMessageQueries.append(MessageQueryInfo()); |
|
1901 |
|
1902 MessageQueryInfo &queryInfo = m_pendingMessageQueries[m_pendingMessageQueries.count()-1]; |
|
1903 |
|
1904 queryInfo.filter = filter; |
|
1905 queryInfo.limit = 0; |
|
1906 queryInfo.offset = 0; |
|
1907 queryInfo.privateService = QMessageServicePrivate::implementation(messageService); |
|
1908 queryInfo.currentFilterListIndex = 0; |
|
1909 queryInfo.handledFiltersCount = 0; |
|
1910 queryInfo.isQuery = false; |
|
1911 queryInfo.returnWithSingleShot = false; |
|
1912 |
|
1913 if (!startQueryingAndFilteringMessages(m_pendingMessageQueries[m_pendingMessageQueries.count()-1])) { |
|
1914 QMessageServicePrivate::implementation(messageService)->setFinished(false); |
|
1915 m_pendingMessageQueries.removeAt(m_pendingMessageQueries.count()-1); |
|
1916 return false; |
|
1917 } |
|
1918 |
|
1919 return true; |
|
1920 } |
|
1921 |
|
1922 bool ModestEngine::queryMessages(QMessageService& messageService, const QMessageFilter &filter, const QString &body, |
|
1923 QMessageDataComparator::MatchFlags matchFlags, const QMessageSortOrder &sortOrder, |
|
1924 uint limit, uint offset) const |
|
1925 { |
|
1926 if (!m_QtmPluginDBusInterface->isValid() || iAccounts.isEmpty()) { |
|
1927 return false; |
|
1928 } |
|
1929 |
|
1930 m_pendingMessageQueries.append(MessageQueryInfo()); |
|
1931 |
|
1932 MessageQueryInfo &queryInfo = m_pendingMessageQueries[m_pendingMessageQueries.count()-1]; |
|
1933 |
|
1934 queryInfo.body = body; |
|
1935 queryInfo.matchFlags = matchFlags; |
|
1936 queryInfo.filter = filter; |
|
1937 queryInfo.sortOrder = sortOrder; |
|
1938 queryInfo.limit = limit; |
|
1939 queryInfo.offset = offset; |
|
1940 queryInfo.privateService = QMessageServicePrivate::implementation(messageService); |
|
1941 queryInfo.currentFilterListIndex = 0; |
|
1942 queryInfo.handledFiltersCount = 0; |
|
1943 queryInfo.isQuery = true; |
|
1944 queryInfo.returnWithSingleShot = false; |
|
1945 |
|
1946 if (!startQueryingAndFilteringMessages(m_pendingMessageQueries[m_pendingMessageQueries.count()-1])) { |
|
1947 m_pendingMessageQueries.removeAt(m_pendingMessageQueries.count()-1); |
|
1948 if (m_pendingMessageQueries.count() == 0) { |
|
1949 // This was last query in pending queries queue |
|
1950 // => Disconnect from "GetHeaders" request related DBus signals |
|
1951 // Note: Disconnecting signals is done to optimize signal handling |
|
1952 // <=> Disconnecting prevents unnecessary handling of signals |
|
1953 // which have been sent from other applications using |
|
1954 // Qt Mobility Messaging API |
|
1955 m_QtmPluginDBusInterface->connection().disconnect(MODESTENGINE_QTM_PLUGIN_NAME, |
|
1956 MODESTENGINE_QTM_PLUGIN_PATH, |
|
1957 MODESTENGINE_QTM_PLUGIN_NAME, |
|
1958 "HeadersReceived", |
|
1959 (ModestEngine*)this, |
|
1960 SLOT(searchMessagesHeadersReceivedSlot(QDBusMessage))); |
|
1961 |
|
1962 m_QtmPluginDBusInterface->connection().disconnect(MODESTENGINE_QTM_PLUGIN_NAME, |
|
1963 MODESTENGINE_QTM_PLUGIN_PATH, |
|
1964 MODESTENGINE_QTM_PLUGIN_NAME, |
|
1965 "HeadersFetched", |
|
1966 (ModestEngine*)this, |
|
1967 SLOT(searchMessagesHeadersFetchedSlot(QDBusMessage))); |
|
1968 } |
|
1969 return false; |
|
1970 } |
|
1971 |
|
1972 return true; |
|
1973 } |
|
1974 |
|
1975 bool ModestEngine::startQueryingAndFilteringMessages(MessageQueryInfo &msgQueryInfo) const |
|
1976 { |
|
1977 QMessageFilterPrivate* pf = QMessageFilterPrivate::implementation(msgQueryInfo.filter); |
|
1978 if (pf->_filterList.count() == 0) { |
|
1979 if ((pf->_field == QMessageFilterPrivate::None) && |
|
1980 (pf->_filterList.count() == 0) && |
|
1981 (pf->_notFilter)) { |
|
1982 // There is only one filter: empty ~QMessageFilter() |
|
1983 // => return empty QMessageIdList |
|
1984 msgQueryInfo.ids.clear(); |
|
1985 msgQueryInfo.returnWithSingleShot = true; |
|
1986 QTimer::singleShot(0, (ModestEngine*)this, SLOT(returnQueryResultsSlot())); |
|
1987 return true; |
|
1988 } else { |
|
1989 // One single filter to be handled |
|
1990 QMessageFilter newFilter; |
|
1991 QMessageFilterPrivate* pfNew = QMessageFilterPrivate::implementation(newFilter); |
|
1992 pfNew->_filterList.append(QMessageFilterPrivate::SortedMessageFilterList()); |
|
1993 pfNew->_filterList[0] << msgQueryInfo.filter; |
|
1994 msgQueryInfo.filter = newFilter; |
|
1995 } |
|
1996 } |
|
1997 |
|
1998 return queryAndFilterMessages(msgQueryInfo); |
|
1999 } |
|
2000 |
|
2001 void ModestEngine::returnQueryResultsSlot() |
|
2002 { |
|
2003 for (int i=m_pendingMessageQueries.count()-1; i >= 0; i--) { |
|
2004 if (m_pendingMessageQueries[i].returnWithSingleShot) { |
|
2005 if (m_pendingMessageQueries[i].isQuery) { |
|
2006 m_pendingMessageQueries[i].privateService->messagesFound(m_pendingMessageQueries[i].ids, true, true); |
|
2007 } else { |
|
2008 m_pendingMessageQueries[i].privateService->messagesCounted(m_pendingMessageQueries[i].ids.count()); |
|
2009 } |
|
2010 m_pendingMessageQueries.removeAt(i); |
|
2011 } |
|
2012 } |
|
2013 } |
|
2014 |
|
2015 bool ModestEngine::queryAndFilterMessages(MessageQueryInfo &msgQueryInfo) const |
|
2016 { |
|
2017 QStringList accountIds; |
|
2018 QStringList folderUris; |
|
2019 QDateTime startTimeStamp; |
|
2020 QDateTime endTimeStamp; |
|
2021 QDateTime startReceptionTimeStamp; |
|
2022 QDateTime endReceptionTimeStamp; |
|
2023 |
|
2024 QMessageFilterPrivate* pf = QMessageFilterPrivate::implementation(msgQueryInfo.filter); |
|
2025 |
|
2026 // Filters have been sorted into matrix of filters: |
|
2027 // - there is AND operation between every filter in one row |
|
2028 // - there is OR operation between every row |
|
2029 // => Every row can be handled individually |
|
2030 // => Final result set can be created by combining result sets |
|
2031 // from individual row based queries |
|
2032 QMessageFilterPrivate::SortedMessageFilterList filters = pf->_filterList[msgQueryInfo.currentFilterListIndex]; |
|
2033 |
|
2034 msgQueryInfo.realAccountId = QString(); |
|
2035 |
|
2036 int handledFiltersCount = 0; |
|
2037 pf = QMessageFilterPrivate::implementation(filters[handledFiltersCount]); |
|
2038 if ((filters.count() == 1) && |
|
2039 (pf->_field == QMessageFilterPrivate::None) && |
|
2040 (pf->_filterList.count() == 0)) { |
|
2041 if (pf->_notFilter) { |
|
2042 // There is only one filter: empty ~QMessageFilter() |
|
2043 // => this query results empty QMessageIdList |
|
2044 // => Skip to next query round |
|
2045 int index = -1; |
|
2046 for (int i=0; i < m_pendingMessageQueries.count(); i++) { |
|
2047 if (m_pendingMessageQueries[i].queryId == msgQueryInfo.queryId) { |
|
2048 index = i; |
|
2049 break; |
|
2050 } |
|
2051 } |
|
2052 if (index >= 0) { |
|
2053 handleQueryFinished(index); |
|
2054 } |
|
2055 return true; |
|
2056 } else { |
|
2057 // There is only one filter: empty QMessageFilter() |
|
2058 // => return all messages |
|
2059 handledFiltersCount++; |
|
2060 } |
|
2061 } |
|
2062 |
|
2063 bool handled = true; |
|
2064 while (handledFiltersCount < filters.count() && handled) { |
|
2065 handled = false; |
|
2066 pf = QMessageFilterPrivate::implementation(filters[handledFiltersCount]); |
|
2067 switch (pf->_field) { |
|
2068 case QMessageFilterPrivate::Id: |
|
2069 break; |
|
2070 case QMessageFilterPrivate::ParentAccountId: |
|
2071 { |
|
2072 if (pf->_comparatorType == QMessageFilterPrivate::Equality) { |
|
2073 if (accountIds.count()) { |
|
2074 // Only one account/one query can be used |
|
2075 break; |
|
2076 } |
|
2077 QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue)); |
|
2078 if (cmp == QMessageDataComparator::Equal) { |
|
2079 if (pf->_value.toString().length() > 0) { |
|
2080 accountIds.append(modestAccountIdFromAccountId(pf->_value.toString())); |
|
2081 // Local folders are not account specific |
|
2082 // => Make sure that account specific messages are searched from local_folders account |
|
2083 accountIds.append("local_folders"); |
|
2084 handled = true; |
|
2085 } |
|
2086 } |
|
2087 } |
|
2088 break; |
|
2089 } |
|
2090 case QMessageFilterPrivate::ParentFolderId: |
|
2091 { |
|
2092 if (pf->_comparatorType == QMessageFilterPrivate::Equality) { |
|
2093 QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue)); |
|
2094 if (cmp == QMessageDataComparator::Equal) { |
|
2095 if (pf->_value.toString().length() > 0) { |
|
2096 folderUris.append(modestFolderIdFromFolderId(pf->_value.toString())); |
|
2097 if (accountIds.count() == 0) { |
|
2098 accountIds.append(modestAccountIdFromFolderId(pf->_value.toString())); |
|
2099 |
|
2100 // Note: Even though local folders belong to "local_folders" account |
|
2101 // inside Modest, local folders can belong to any "real" |
|
2102 // POP3 or IMAP account in Qt Mobility Messaging side |
|
2103 // <=> Qt Mobility Messaging does not have "Local Folders" |
|
2104 // account |
|
2105 // If folder is local folder, "local_folders" accountId will be |
|
2106 // added to accountIds list to enable correct filtering inside |
|
2107 // Modest Plugin |
|
2108 accountIds.append("local_folders"); |
|
2109 |
|
2110 // realAccountId will contain id of Qt Mobility Messaging account |
|
2111 // (AccountId can be found from the beginning of folderId string) |
|
2112 // <=> realAccountId will not ever be "local_folders" |
|
2113 msgQueryInfo.realAccountId = accountIdFromFolderId(pf->_value.toString()).toString(); |
|
2114 } |
|
2115 handled = true; |
|
2116 } |
|
2117 } |
|
2118 } |
|
2119 break; |
|
2120 } |
|
2121 case QMessageFilterPrivate::AncestorFolderIds: |
|
2122 break; |
|
2123 case QMessageFilterPrivate::Type: |
|
2124 break; |
|
2125 case QMessageFilterPrivate::StandardFolder: |
|
2126 if (pf->_comparatorType == QMessageFilterPrivate::Equality) { |
|
2127 QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue)); |
|
2128 if (cmp == QMessageDataComparator::Equal) { |
|
2129 QMessage::StandardFolder standardFolder = static_cast<QMessage::StandardFolder>(pf->_value.toInt()); |
|
2130 if (standardFolder == QMessage::SentFolder) { |
|
2131 // Possible "real" accountIds can be ignored in this phase |
|
2132 // because messages are searched from "local_folders" account |
|
2133 // <=> Actual account filtering is done when search from Modest |
|
2134 // has finished |
|
2135 accountIds.clear(); |
|
2136 |
|
2137 accountIds.append("local_folders"); |
|
2138 folderUris.append("sent"); |
|
2139 } else if (standardFolder == QMessage::DraftsFolder) { |
|
2140 // Possible "real" accountIds can be ignored in this phase |
|
2141 // because messages are searched from "local_folders" account |
|
2142 // <=> Actual account filtering is done when search from Modest |
|
2143 // has finished |
|
2144 accountIds.clear(); |
|
2145 |
|
2146 accountIds.append("local_folders"); |
|
2147 folderUris.append("drafts"); |
|
2148 } |
|
2149 handled = true; |
|
2150 } |
|
2151 } |
|
2152 break; |
|
2153 case QMessageFilterPrivate::ParentAccountIdFilter: |
|
2154 break; |
|
2155 case QMessageFilterPrivate::ParentFolderIdFilter: |
|
2156 break; |
|
2157 case QMessageFilterPrivate::TimeStamp: |
|
2158 { |
|
2159 if (pf->_comparatorType == QMessageFilterPrivate::Equality) { |
|
2160 QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue)); |
|
2161 if (cmp == QMessageDataComparator::Equal) { |
|
2162 endTimeStamp = pf->_value.toDateTime(); |
|
2163 startTimeStamp = pf->_value.toDateTime(); |
|
2164 handled = true; |
|
2165 } |
|
2166 } |
|
2167 if (pf->_comparatorType == QMessageFilterPrivate::Relation) { |
|
2168 QMessageDataComparator::RelationComparator cmp(static_cast<QMessageDataComparator::RelationComparator>(pf->_comparatorValue)); |
|
2169 if (cmp == QMessageDataComparator::LessThan) { |
|
2170 endTimeStamp = pf->_value.toDateTime(); |
|
2171 handled = true; |
|
2172 } else if (cmp == QMessageDataComparator::LessThanEqual) { |
|
2173 endTimeStamp = pf->_value.toDateTime(); |
|
2174 handled = true; |
|
2175 } else if (cmp == QMessageDataComparator::GreaterThan) { |
|
2176 startTimeStamp = pf->_value.toDateTime(); |
|
2177 handled = true; |
|
2178 } if (cmp == QMessageDataComparator::GreaterThanEqual) { |
|
2179 startTimeStamp = pf->_value.toDateTime(); |
|
2180 handled = true; |
|
2181 } |
|
2182 } |
|
2183 break; |
|
2184 } |
|
2185 case QMessageFilterPrivate::ReceptionTimeStamp: |
|
2186 { |
|
2187 if (pf->_comparatorType == QMessageFilterPrivate::Equality) { |
|
2188 QMessageDataComparator::EqualityComparator cmp(static_cast<QMessageDataComparator::EqualityComparator>(pf->_comparatorValue)); |
|
2189 if (cmp == QMessageDataComparator::Equal) { |
|
2190 endReceptionTimeStamp = pf->_value.toDateTime(); |
|
2191 startReceptionTimeStamp = pf->_value.toDateTime(); |
|
2192 handled = true; |
|
2193 } |
|
2194 } |
|
2195 if (pf->_comparatorType == QMessageFilterPrivate::Relation) { |
|
2196 QMessageDataComparator::RelationComparator cmp(static_cast<QMessageDataComparator::RelationComparator>(pf->_comparatorValue)); |
|
2197 if (cmp == QMessageDataComparator::LessThan) { |
|
2198 endReceptionTimeStamp = pf->_value.toDateTime(); |
|
2199 handled = true; |
|
2200 } else if (cmp == QMessageDataComparator::LessThanEqual) { |
|
2201 endReceptionTimeStamp = pf->_value.toDateTime(); |
|
2202 handled = true; |
|
2203 } else if (cmp == QMessageDataComparator::GreaterThan) { |
|
2204 startReceptionTimeStamp = pf->_value.toDateTime(); |
|
2205 handled = true; |
|
2206 } if (cmp == QMessageDataComparator::GreaterThanEqual) { |
|
2207 startReceptionTimeStamp = pf->_value.toDateTime(); |
|
2208 handled = true; |
|
2209 } |
|
2210 } |
|
2211 break; |
|
2212 } |
|
2213 case QMessageFilterPrivate::Sender: |
|
2214 break; |
|
2215 case QMessageFilterPrivate::Recipients: |
|
2216 break; |
|
2217 case QMessageFilterPrivate::Subject: |
|
2218 break; |
|
2219 case QMessageFilterPrivate::Status: |
|
2220 break; |
|
2221 case QMessageFilterPrivate::Priority: |
|
2222 break; |
|
2223 case QMessageFilterPrivate::Size: |
|
2224 break; |
|
2225 case QMessageFilterPrivate::None: |
|
2226 break; |
|
2227 } |
|
2228 handledFiltersCount++; |
|
2229 } |
|
2230 |
|
2231 msgQueryInfo.handledFiltersCount = 0; // Do filtering also for filters which has been handled above |
|
2232 |
|
2233 return searchMessages(msgQueryInfo, accountIds, folderUris, msgQueryInfo.body, startTimeStamp, |
|
2234 endTimeStamp, startReceptionTimeStamp, endReceptionTimeStamp); |
|
2235 } |
|
2236 |
|
2237 bool ModestEngine::searchMessages(MessageQueryInfo &msgQueryInfo, const QStringList& accountIds, |
|
2238 const QStringList& folderUris, const QString& body, |
|
2239 const QDateTime& startTimeStamp, const QDateTime& endTimeStamp, |
|
2240 const QDateTime& startReceptionTimeStamp, const QDateTime& endReceptionTimeStamp) const |
|
2241 { |
|
2242 Q_UNUSED(body) //TODO: Body search |
|
2243 |
|
2244 qulonglong sDate = 0; |
|
2245 if (startTimeStamp.isValid() && startReceptionTimeStamp.isValid()) { |
|
2246 if (startTimeStamp < startReceptionTimeStamp) { |
|
2247 sDate = startTimeStamp.toTime_t(); |
|
2248 } else { |
|
2249 sDate = startReceptionTimeStamp.toTime_t(); |
|
2250 } |
|
2251 } else { |
|
2252 if (startTimeStamp.isValid()) { |
|
2253 sDate = startTimeStamp.toTime_t(); |
|
2254 } else if (startReceptionTimeStamp.isValid()) { |
|
2255 sDate = startReceptionTimeStamp.toTime_t(); |
|
2256 } |
|
2257 } |
|
2258 |
|
2259 |
|
2260 qulonglong eDate = 0; |
|
2261 if (endTimeStamp.isValid() && endReceptionTimeStamp.isValid()) { |
|
2262 if (endTimeStamp > endReceptionTimeStamp) { |
|
2263 eDate = endTimeStamp.toTime_t(); |
|
2264 } else { |
|
2265 eDate = endReceptionTimeStamp.toTime_t(); |
|
2266 } |
|
2267 } else { |
|
2268 if (endTimeStamp.isValid()) { |
|
2269 eDate = endTimeStamp.toTime_t(); |
|
2270 } else if (endReceptionTimeStamp.isValid()) { |
|
2271 eDate = endReceptionTimeStamp.toTime_t(); |
|
2272 } |
|
2273 } |
|
2274 |
|
2275 if (m_pendingMessageQueries.count() == 1) { |
|
2276 // This is the first query in pending queries queue |
|
2277 // => connect to signals |
|
2278 m_QtmPluginDBusInterface->connection().connect(MODESTENGINE_QTM_PLUGIN_NAME, |
|
2279 MODESTENGINE_QTM_PLUGIN_PATH, |
|
2280 MODESTENGINE_QTM_PLUGIN_NAME, |
|
2281 "HeadersReceived", |
|
2282 (ModestEngine*)this, |
|
2283 SLOT(searchMessagesHeadersReceivedSlot(QDBusMessage))); |
|
2284 |
|
2285 m_QtmPluginDBusInterface->connection().connect(MODESTENGINE_QTM_PLUGIN_NAME, |
|
2286 MODESTENGINE_QTM_PLUGIN_PATH, |
|
2287 MODESTENGINE_QTM_PLUGIN_NAME, |
|
2288 "HeadersFetched", |
|
2289 (ModestEngine*)this, |
|
2290 SLOT(searchMessagesHeadersFetchedSlot(QDBusMessage))); |
|
2291 } |
|
2292 |
|
2293 QDBusMessage reply = m_QtmPluginDBusInterface->call("GetHeaders", |
|
2294 accountIds, |
|
2295 folderUris, |
|
2296 sDate, |
|
2297 eDate, |
|
2298 false); |
|
2299 if (reply.type() != QDBusMessage::ErrorMessage) { |
|
2300 m_messageCache.clear(); |
|
2301 msgQueryInfo.queryId = reply.arguments().takeFirst().toInt(); |
|
2302 } else { |
|
2303 return false; |
|
2304 } |
|
2305 |
|
2306 return true; |
|
2307 } |
|
2308 |
|
2309 void ModestEngine::searchMessagesHeadersReceivedSlot(QDBusMessage msg) |
|
2310 { |
|
2311 QList<QVariant> arguments = msg.arguments(); |
|
2312 int queryId = arguments.takeFirst().toInt(); |
|
2313 |
|
2314 int index = -1; |
|
2315 for (int i=0; i < m_pendingMessageQueries.count(); i++) { |
|
2316 if (m_pendingMessageQueries[i].queryId == queryId) { |
|
2317 index = i; |
|
2318 break; |
|
2319 } |
|
2320 } |
|
2321 if (index == -1) { |
|
2322 // Received DBus Message is not reply for the DBus query |
|
2323 // that was sent from this process/instance of modest engine |
|
2324 // => Continue waiting |
|
2325 return; |
|
2326 } |
|
2327 |
|
2328 MessageQueryInfo &queryInfo = m_pendingMessageQueries[index]; |
|
2329 |
|
2330 QString reportedAccountId = arguments.takeFirst().toString(); |
|
2331 QString accountId; |
|
2332 if (!queryInfo.realAccountId.isEmpty()) { |
|
2333 // Search was done to Modest "local_folders" account |
|
2334 // => Correct Qt Mobility Messaging AccountId |
|
2335 // can be taken realAccountId field |
|
2336 // => Transform Messaging AccountId to Modest accountId |
|
2337 // by removing "MO_" from the beginning of accountId string |
|
2338 accountId = queryInfo.realAccountId; |
|
2339 accountId.remove(0,3); |
|
2340 } else { |
|
2341 accountId = reportedAccountId.remove("_store"); |
|
2342 } |
|
2343 |
|
2344 QString folderId = arguments.takeFirst().toString(); |
|
2345 QVariant variant = arguments.takeFirst(); |
|
2346 QDBusArgument argument = variant.value<QDBusArgument>(); |
|
2347 QList<QMap<QString, QVariant> > messages; |
|
2348 argument >> messages; |
|
2349 |
|
2350 QMessageFilterPrivate::SortedMessageFilterList filters; |
|
2351 int firstUnhandledFilterIndex = 0; |
|
2352 |
|
2353 QMessageFilterPrivate* pf = QMessageFilterPrivate::implementation(queryInfo.filter); |
|
2354 if (pf->_filterList.count() == 0) { |
|
2355 filters.append(queryInfo.filter); |
|
2356 } else { |
|
2357 if (queryInfo.handledFiltersCount < pf->_filterList[queryInfo.currentFilterListIndex].count()) { |
|
2358 filters = pf->_filterList[queryInfo.currentFilterListIndex]; |
|
2359 } |
|
2360 } |
|
2361 firstUnhandledFilterIndex = queryInfo.handledFiltersCount; |
|
2362 |
|
2363 for (int i=0; i < messages.count(); i++) { |
|
2364 MessagingModestMessage modestMessage; |
|
2365 modestMessage.accountId = accountId; |
|
2366 modestMessage.folderId = folderId; |
|
2367 modestMessage.dateReceived = 0; |
|
2368 modestMessage.dateSent = 0; |
|
2369 modestMessage.size = 0; |
|
2370 modestMessage.flags = MessagingModestMessageNotDefined; |
|
2371 modestMessage.priority = MessagingModestMessagePriorityNotDefined; |
|
2372 |
|
2373 QMapIterator<QString, QVariant> j(messages[i]); |
|
2374 while (j.hasNext()) { |
|
2375 j.next(); |
|
2376 if (j.key() == "url") { |
|
2377 modestMessage.url = j.value().toString(); |
|
2378 } else if (j.key() == "message-uid") { |
|
2379 modestMessage.id = j.value().toString(); |
|
2380 } else if (j.key() == "from") { |
|
2381 modestMessage.from = j.value().toString(); |
|
2382 } else if (j.key() == "to") { |
|
2383 modestMessage.to = j.value().toString(); |
|
2384 } else if (j.key() == "cc") { |
|
2385 modestMessage.cc = j.value().toString(); |
|
2386 } else if (j.key() == "bcc") { |
|
2387 modestMessage.bcc = j.value().toString(); |
|
2388 } else if (j.key() == "replyto") { |
|
2389 modestMessage.replyTo = j.value().toString(); |
|
2390 } else if (j.key() == "subject") { |
|
2391 modestMessage.subject = j.value().toString(); |
|
2392 } else if (j.key() == "date-received") { |
|
2393 modestMessage.dateReceived = j.value().toLongLong(); |
|
2394 } else if (j.key() == "date-sent") { |
|
2395 modestMessage.dateSent = j.value().toLongLong(); |
|
2396 } else if (j.key() == "size") { |
|
2397 modestMessage.size = j.value().toLongLong(); |
|
2398 } else if (j.key() == "flags") { |
|
2399 qlonglong flags = j.value().toUInt(); |
|
2400 qlonglong priority = flags & MessagingModestMessageHasPriority; |
|
2401 modestMessage.priority = static_cast<MessagingModestMessagePriority>(priority); |
|
2402 modestMessage.flags = static_cast<MessagingModestMessageFlags>(flags); |
|
2403 } |
|
2404 } |
|
2405 |
|
2406 QMessage message = messageFromModestMessage(modestMessage); |
|
2407 if (reportedAccountId == "local_folders") { |
|
2408 QMessagePrivate* privateMessage = QMessagePrivate::implementation(message); |
|
2409 QString id = privateMessage->_id.toString(); |
|
2410 QString newProtocol = "maildir"; |
|
2411 replaceProtocol(id, newProtocol); |
|
2412 privateMessage->_id = QMessageId(id); |
|
2413 id = privateMessage->_parentFolderId.toString(); |
|
2414 replaceProtocol(id, newProtocol); |
|
2415 privateMessage->_parentFolderId = QMessageFolderId(id); |
|
2416 } |
|
2417 if (filterMessage(message, filters, 0)) { |
|
2418 if (!queryInfo.ids.contains(message.id())) { |
|
2419 if (m_messageCache.size() < maxCacheSize) { |
|
2420 m_messageCache.insert(message.id().toString(), message); |
|
2421 } |
|
2422 queryInfo.ids.append(message.id()); |
|
2423 } |
|
2424 } |
|
2425 } |
|
2426 } |
|
2427 |
|
2428 void ModestEngine::searchMessagesHeadersFetchedSlot(QDBusMessage msg) |
|
2429 { |
|
2430 QList<QVariant> arguments = msg.arguments(); |
|
2431 int queryId = arguments.takeFirst().toInt(); |
|
2432 |
|
2433 int index = -1; |
|
2434 for (int i=0; i < m_pendingMessageQueries.count(); i++) { |
|
2435 if (m_pendingMessageQueries[i].queryId == queryId) { |
|
2436 index = i; |
|
2437 break; |
|
2438 } |
|
2439 } |
|
2440 if (index == -1) { |
|
2441 // Received DBus Message is not reply for the DBus query |
|
2442 // that was sent from this process/instance of modest engine |
|
2443 // => Continue waiting |
|
2444 return; |
|
2445 } |
|
2446 |
|
2447 handleQueryFinished(index); |
|
2448 } |
|
2449 |
|
2450 void ModestEngine::handleQueryFinished(int index) const |
|
2451 { |
|
2452 MessageQueryInfo &queryInfo = m_pendingMessageQueries[index]; |
|
2453 |
|
2454 queryInfo.currentFilterListIndex++; |
|
2455 QMessageFilterPrivate* pf = QMessageFilterPrivate::implementation(queryInfo.filter); |
|
2456 if (queryInfo.currentFilterListIndex < pf->_filterList.count()) { |
|
2457 if (queryAndFilterMessages(queryInfo)) { |
|
2458 // Continue searching |
|
2459 return; |
|
2460 } |
|
2461 } |
|
2462 |
|
2463 MessagingHelper::orderMessages(queryInfo.ids, queryInfo.sortOrder); |
|
2464 MessagingHelper::applyOffsetAndLimitToMessageIdList(queryInfo.ids, queryInfo.limit, queryInfo.offset); |
|
2465 |
|
2466 // Search finished |
|
2467 if (queryInfo.isQuery) { |
|
2468 queryInfo.privateService->messagesFound(queryInfo.ids, true, true); |
|
2469 } else { |
|
2470 queryInfo.privateService->messagesCounted(queryInfo.ids.count()); |
|
2471 } |
|
2472 m_pendingMessageQueries.removeAt(index); |
|
2473 |
|
2474 if (m_pendingMessageQueries.count() == 0) { |
|
2475 // This was last query in pending queries queue |
|
2476 // => Disconnect from "GetHeaders" request related DBus signals |
|
2477 // Note: Disconnecting signals is done to optimize signal handling |
|
2478 // <=> Disconnecting prevents unnecessary handling of signals |
|
2479 // which have been sent from other applications using |
|
2480 // Qt Mobility Messaging API |
|
2481 m_QtmPluginDBusInterface->connection().disconnect(MODESTENGINE_QTM_PLUGIN_NAME, |
|
2482 MODESTENGINE_QTM_PLUGIN_PATH, |
|
2483 MODESTENGINE_QTM_PLUGIN_NAME, |
|
2484 "HeadersReceived", |
|
2485 (ModestEngine*)this, |
|
2486 SLOT(searchMessagesHeadersReceivedSlot(QDBusMessage))); |
|
2487 |
|
2488 m_QtmPluginDBusInterface->connection().disconnect(MODESTENGINE_QTM_PLUGIN_NAME, |
|
2489 MODESTENGINE_QTM_PLUGIN_PATH, |
|
2490 MODESTENGINE_QTM_PLUGIN_NAME, |
|
2491 "HeadersFetched", |
|
2492 (ModestEngine*)this, |
|
2493 SLOT(searchMessagesHeadersFetchedSlot(QDBusMessage))); |
|
2494 } |
|
2495 } |
|
2496 |
|
2497 void |
|
2498 ModestEngine::sendEmailCallEnded(QDBusPendingCallWatcher *watcher) |
|
2499 { |
|
2500 if (watcher->isError ()) { |
|
2501 // TODO: Emit a failure |
|
2502 qWarning() << "Failed to send email via modest: " << watcher->error(); |
|
2503 } else { |
|
2504 // TODO: Emit a success (or put to outbox) |
|
2505 qDebug() << "Message should be outboxed now..."; |
|
2506 } |
|
2507 } |
|
2508 |
|
2509 void |
|
2510 ModestEngine::addMessageCallEnded(QDBusPendingCallWatcher *watcher) |
|
2511 { |
|
2512 QDBusPendingReply<QString> reply = *watcher; |
|
2513 if (reply.isError ()) { |
|
2514 // TODO: Emit a failure |
|
2515 qWarning() << "Failed to add message via modest: " << reply.error(); |
|
2516 } else { |
|
2517 QString id = reply.argumentAt<0>(); |
|
2518 // TODO: Emit a success ... with message's id? |
|
2519 qDebug() << "Message with id" << id << "should be added now"; |
|
2520 } |
|
2521 } |
|
2522 |
|
2523 void ModestEngine::folderUpdatedSlot(QDBusMessage msg) |
|
2524 { |
|
2525 QList<QVariant> arguments = msg.arguments(); |
|
2526 QString modestAccountId = arguments.takeFirst().toString(); |
|
2527 QString modestFolderId = arguments.takeFirst().toString(); |
|
2528 QMessageFolderId updatedFolderId; |
|
2529 |
|
2530 if (modestAccountId == "local_folders") { |
|
2531 updatedFolderId = QMessageFolderId("MO_LOCAL&maildir&"+modestFolderId); |
|
2532 } else { |
|
2533 QMessageAccountId accountId = QMessageAccountId("MO_"+escapeString(modestAccountId)); |
|
2534 QString protocol = accountEmailProtocolAsString(accountId); |
|
2535 if ((protocol == "pop") && (modestFolderId == "INBOX")) { |
|
2536 modestFolderId = "cache"; |
|
2537 } |
|
2538 updatedFolderId = QMessageFolderId(accountId.toString()+"&"+protocol+"&"+modestFolderId); |
|
2539 } |
|
2540 |
|
2541 int messagesPerAccount = 5; |
|
2542 QDBusPendingCall pendingCall = m_ModestDBusInterface->asyncCall(MODEST_DBUS_METHOD_GET_UNREAD_MESSAGES, |
|
2543 messagesPerAccount); |
|
2544 QDBusPendingCallWatcher* pendingCallWatcher = new QDBusPendingCallWatcher(pendingCall); |
|
2545 pendingCallWatcher->setProperty("folderId", updatedFolderId.toString()); |
|
2546 connect(pendingCallWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), |
|
2547 this, SLOT(pendingGetUnreadMessagesFinishedSlot(QDBusPendingCallWatcher*))); |
|
2548 } |
|
2549 |
|
2550 void ModestEngine::pendingGetUnreadMessagesFinishedSlot(QDBusPendingCallWatcher* pendingCallWatcher) |
|
2551 { |
|
2552 if (pendingCallWatcher->isError()) { |
|
2553 return; |
|
2554 } |
|
2555 |
|
2556 QDBusMessage msg = pendingCallWatcher->reply(); |
|
2557 if (msg.arguments().count() == 0) { |
|
2558 return; |
|
2559 } |
|
2560 |
|
2561 QVariant variant = msg.arguments().takeFirst(); |
|
2562 QDBusArgument argument = variant.value<QDBusArgument>(); |
|
2563 QList<ModestAccountsUnreadMessagesDBusStruct> accountsWithUnreadMessages; |
|
2564 argument >> accountsWithUnreadMessages; |
|
2565 |
|
2566 bool setOnlyDates = false; |
|
2567 if (pendingCallWatcher->property("setOnlyDates").isValid()) { |
|
2568 setOnlyDates = true; |
|
2569 } |
|
2570 QMessageFolderId folderId; |
|
2571 if (pendingCallWatcher->property("folderId").isValid()) { |
|
2572 folderId = QMessageFolderId(pendingCallWatcher->property("folderId").toString()); |
|
2573 } |
|
2574 |
|
2575 for (int i=0; i < accountsWithUnreadMessages.count(); i++) { |
|
2576 QDateTime newLatestTimeStamp; |
|
2577 QDateTime latestTimeStamp = accountsLatestTimestamp.take(accountsWithUnreadMessages[i].accountId); |
|
2578 for (int j=0; j < accountsWithUnreadMessages[i].unreadMessages.count(); j++) { |
|
2579 ModestUnreadMessageDBusStruct unreadMessage = accountsWithUnreadMessages[i].unreadMessages[j]; |
|
2580 QDateTime time = QDateTime::fromTime_t(unreadMessage.timeStamp); |
|
2581 if (time > newLatestTimeStamp) { |
|
2582 newLatestTimeStamp = time; |
|
2583 } |
|
2584 if (!setOnlyDates) { |
|
2585 if (time > latestTimeStamp) { |
|
2586 searchNewMessages(unreadMessage.subject, QString(), time, time, MODEST_DBUS_SEARCH_SUBJECT, 0); |
|
2587 } |
|
2588 } |
|
2589 } |
|
2590 if (newLatestTimeStamp.isValid()) { |
|
2591 accountsLatestTimestamp.remove(accountsWithUnreadMessages[i].accountId); |
|
2592 accountsLatestTimestamp.insert(accountsWithUnreadMessages[i].accountId, newLatestTimeStamp); |
|
2593 } else { |
|
2594 accountsLatestTimestamp.insert(accountsWithUnreadMessages[i].accountId, QDateTime::currentDateTime()); |
|
2595 } |
|
2596 } |
|
2597 } |
|
2598 |
|
2599 void ModestEngine::searchNewMessages(const QString& searchString, const QString& folderToSearch, |
|
2600 const QDateTime& startDate, const QDateTime& endDate, |
|
2601 int searchflags, uint minimumMessageSize) const |
|
2602 { |
|
2603 qlonglong sDate = 0; |
|
2604 if (startDate.isValid()) { |
|
2605 sDate = startDate.toTime_t(); |
|
2606 } |
|
2607 qlonglong eDate = 0; |
|
2608 if (endDate.isValid()) { |
|
2609 eDate = endDate.toTime_t(); |
|
2610 } |
|
2611 |
|
2612 QDBusInterface interface(MODEST_DBUS_SERVICE, MODEST_DBUS_OBJECT, MODEST_DBUS_IFACE); |
|
2613 QDBusPendingCall pendingCall = interface.asyncCall(MODEST_DBUS_METHOD_SEARCH, |
|
2614 searchString, |
|
2615 folderToSearch, |
|
2616 sDate, |
|
2617 eDate, |
|
2618 searchflags, |
|
2619 minimumMessageSize); |
|
2620 QDBusPendingCallWatcher* pendingCallWatcher = new QDBusPendingCallWatcher(pendingCall); |
|
2621 connect(pendingCallWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), |
|
2622 this, SLOT(pendingSearchFinishedSlot(QDBusPendingCallWatcher*))); |
|
2623 } |
|
2624 |
|
2625 void ModestEngine::pendingSearchFinishedSlot(QDBusPendingCallWatcher* pendingCallWatcher) |
|
2626 { |
|
2627 if (pendingCallWatcher->isError()) { |
|
2628 return; |
|
2629 } |
|
2630 |
|
2631 QDBusMessage msg = pendingCallWatcher->reply(); |
|
2632 if (msg.arguments().count() == 0) { |
|
2633 return; |
|
2634 } |
|
2635 |
|
2636 QVariant variant = msg.arguments().takeFirst(); |
|
2637 QDBusArgument argument = variant.value<QDBusArgument>(); |
|
2638 QList<ModestMessage> messages; |
|
2639 argument >> messages; |
|
2640 |
|
2641 for (int i=0; i < messages.count(); i++) { |
|
2642 notification(messageIdFromModestMessageId(messages[i].id), ModestEngine::Added); |
|
2643 } |
|
2644 } |
|
2645 |
|
2646 void ModestEngine::messageReadChangedSlot(QDBusMessage msg) |
|
2647 { |
|
2648 QString changedMessageId = msg.arguments().takeFirst().toString(); |
|
2649 notification(messageIdFromModestMessageId(changedMessageId), ModestEngine::Updated); |
|
2650 } |
|
2651 |
|
2652 QMessageManager::NotificationFilterId ModestEngine::registerNotificationFilter(QMessageStorePrivate& messageStore, |
|
2653 const QMessageFilter &filter, |
|
2654 QMessageManager::NotificationFilterId id) |
|
2655 { |
|
2656 m_messageStore = &messageStore; |
|
2657 |
|
2658 int filterId = id; |
|
2659 if (filterId == 0) { |
|
2660 filterId = ++m_filterId; |
|
2661 } |
|
2662 m_filters.insert(filterId, filter); |
|
2663 return filterId; |
|
2664 } |
|
2665 |
|
2666 void ModestEngine::unregisterNotificationFilter(QMessageManager::NotificationFilterId notificationFilterId) |
|
2667 { |
|
2668 m_filters.remove(notificationFilterId); |
|
2669 } |
|
2670 |
|
2671 QByteArray ModestEngine::getMimePart (const QMessageId &id, const QString &attachmentId) |
|
2672 { |
|
2673 QByteArray result; |
|
2674 |
|
2675 QString modestAccountId = modestAccountIdFromMessageId(id); |
|
2676 QString modestFolderId = modestFolderIdFromMessageId(id); |
|
2677 QString modestMessageId = modestMessageIdFromMessageId(id); |
|
2678 |
|
2679 QString filePath, mimeType; |
|
2680 int mimeSize = -1; |
|
2681 bool expunge = false, isAttachment = false; |
|
2682 |
|
2683 QDBusPendingReply<QString, QString, int, bool, bool> reply = |
|
2684 m_QtmPluginDBusInterface->asyncCall( |
|
2685 "GetMimePart", |
|
2686 QVariant::fromValue(modestAccountId), |
|
2687 QVariant::fromValue(modestFolderId), |
|
2688 QVariant::fromValue(modestMessageId), |
|
2689 QVariant::fromValue(attachmentId)); |
|
2690 |
|
2691 reply.waitForFinished(); |
|
2692 |
|
2693 if (reply.isError()) { |
|
2694 return result; |
|
2695 } |
|
2696 |
|
2697 filePath = reply.argumentAt<0>(); |
|
2698 mimeType = reply.argumentAt<1>(); |
|
2699 mimeSize = reply.argumentAt<2>(); |
|
2700 isAttachment = reply.argumentAt<3>(); |
|
2701 expunge = reply.argumentAt<4>(); |
|
2702 |
|
2703 if (filePath.isEmpty()) { |
|
2704 qWarning() << "Received empty file path!"; |
|
2705 return result; |
|
2706 } |
|
2707 |
|
2708 QFile file(filePath); |
|
2709 |
|
2710 QIODevice::OpenMode openMode = QIODevice::ReadOnly; |
|
2711 if (expunge) { |
|
2712 openMode = QIODevice::ReadWrite; |
|
2713 } |
|
2714 |
|
2715 if (file.open(openMode) == false) { |
|
2716 qWarning() << "Failed to open file" << filePath << ": " |
|
2717 << file.errorString(); |
|
2718 return result; |
|
2719 } |
|
2720 |
|
2721 result = file.readAll(); |
|
2722 |
|
2723 if (expunge) { |
|
2724 file.remove(); |
|
2725 } else { |
|
2726 file.close(); |
|
2727 } |
|
2728 |
|
2729 return result; |
|
2730 } |
|
2731 |
|
2732 bool ModestEngine::retrieveBody(QMessageService& messageService, const QMessageId &id) |
|
2733 { |
|
2734 if (!id.isValid()) return false; |
|
2735 |
|
2736 QMessage msg = message(id, true); |
|
2737 QMessageContentContainerId attachmentId = msg.bodyId(); |
|
2738 |
|
2739 //if (!attachmentId.isValid()) return false; |
|
2740 |
|
2741 return retrieve(messageService, id, attachmentId, &msg); |
|
2742 } |
|
2743 |
|
2744 bool ModestEngine::retrieve(QMessageService& messageService, const QMessageId &id, |
|
2745 const QMessageContentContainerId &attachmentId, QMessage *msg) |
|
2746 { |
|
2747 QByteArray result; |
|
2748 |
|
2749 if (!id.isValid()) return false; |
|
2750 //if (!attachmentId.isValid()) return false; |
|
2751 |
|
2752 QString modestAccountId = modestAccountIdFromMessageId(id); |
|
2753 QString modestFolderId = modestFolderIdFromMessageId(id); |
|
2754 QString modestMessageId = modestMessageIdFromMessageId(id); |
|
2755 QString modestAttachmentId; |
|
2756 int opId = -1; |
|
2757 |
|
2758 QMessage message; |
|
2759 |
|
2760 if (msg != 0) { |
|
2761 message = *msg; |
|
2762 } else { |
|
2763 message = this->message(id, true); |
|
2764 } |
|
2765 |
|
2766 QMessageContentContainer cont = message.find(attachmentId); |
|
2767 QMessageContentContainerPrivate *contPrivate = QMessageContentContainerPrivate::implementation(cont); |
|
2768 |
|
2769 if (contPrivate != 0) { |
|
2770 modestAttachmentId = contPrivate->_attachmentId; |
|
2771 } |
|
2772 |
|
2773 if (m_pending_downloads.count() == 0) { |
|
2774 m_QtmPluginDBusInterface->connection().connect(MODESTENGINE_QTM_PLUGIN_NAME, |
|
2775 MODESTENGINE_QTM_PLUGIN_PATH, |
|
2776 MODESTENGINE_QTM_PLUGIN_NAME, |
|
2777 "PartDownloadFinished", |
|
2778 (ModestEngine*)this, |
|
2779 SLOT(mimePartDownloadFinishedSlot(QDBusMessage))); |
|
2780 } |
|
2781 |
|
2782 QDBusPendingReply<int> reply = m_QtmPluginDBusInterface->asyncCall("DownloadMimePart", |
|
2783 QVariant::fromValue(modestAccountId), |
|
2784 QVariant::fromValue(modestFolderId), |
|
2785 QVariant::fromValue(modestMessageId), |
|
2786 QVariant::fromValue(modestAttachmentId)); |
|
2787 |
|
2788 reply.waitForFinished(); |
|
2789 |
|
2790 if (reply.isError()) { |
|
2791 if (m_pending_downloads.count() == 0) { |
|
2792 m_QtmPluginDBusInterface->connection().disconnect(MODESTENGINE_QTM_PLUGIN_NAME, |
|
2793 MODESTENGINE_QTM_PLUGIN_PATH, |
|
2794 MODESTENGINE_QTM_PLUGIN_NAME, |
|
2795 "PartDownloadFinished", |
|
2796 (ModestEngine*)this, |
|
2797 SLOT(mimePartDownloadFinishedSlot(QDBusMessage))); |
|
2798 } |
|
2799 return false; |
|
2800 } |
|
2801 |
|
2802 opId = reply.argumentAt<0>(); |
|
2803 |
|
2804 QMessageServicePrivate* privateService = QMessageServicePrivate::implementation(messageService); |
|
2805 m_pending_downloads.insert(opId, privateService); |
|
2806 |
|
2807 return true; |
|
2808 } |
|
2809 |
|
2810 void ModestEngine::mimePartDownloadFinishedSlot(QDBusMessage msg) |
|
2811 { |
|
2812 QList<QVariant> arguments = msg.arguments(); |
|
2813 int operationId = arguments.takeFirst().toInt(); |
|
2814 |
|
2815 if (m_pending_downloads.contains(operationId)) { |
|
2816 QMessageServicePrivate* privateService = m_pending_downloads.take(operationId); |
|
2817 |
|
2818 privateService->_pendingRequestCount--; |
|
2819 |
|
2820 bool success = arguments.takeFirst().toBool(); |
|
2821 if (success) { |
|
2822 privateService->setFinished(true); |
|
2823 } else { |
|
2824 privateService->setFinished(false); |
|
2825 } |
|
2826 |
|
2827 if (m_pending_downloads.count() == 0) { |
|
2828 m_QtmPluginDBusInterface->connection().disconnect(MODESTENGINE_QTM_PLUGIN_NAME, |
|
2829 MODESTENGINE_QTM_PLUGIN_PATH, |
|
2830 MODESTENGINE_QTM_PLUGIN_NAME, |
|
2831 "PartDownloadFinished", |
|
2832 (ModestEngine*)this, |
|
2833 SLOT(mimePartDownloadFinishedSlot(QDBusMessage))); |
|
2834 } |
|
2835 } |
|
2836 } |
|
2837 |
|
2838 void ModestEngine::notification(const QMessageId& messageId, NotificationType notificationType) const |
|
2839 { |
|
2840 QMessageId realMessageId = messageId; |
|
2841 QString modestAccountId = modestAccountIdFromMessageId(messageId); |
|
2842 QString modestFolderId = modestFolderIdFromMessageId(messageId); |
|
2843 QString modestMessageId = modestMessageIdFromMessageId(messageId); |
|
2844 |
|
2845 // Make sure that there will not be many Added or Removed notifications |
|
2846 // in a row for the same message |
|
2847 // Make also sure that there will not be updated notification for a |
|
2848 // message that has already been notified to be removed. |
|
2849 QString searchId; |
|
2850 if (notificationType == ModestEngine::Added) { |
|
2851 searchId = "A"+modestAccountId+modestFolderId+modestMessageId; |
|
2852 } else { |
|
2853 searchId = "D"+modestAccountId+modestFolderId+modestMessageId; |
|
2854 } |
|
2855 if (!m_latestAddOrRemoveNotifications.contains(searchId)) { |
|
2856 if ((notificationType == ModestEngine::Added) || (notificationType == ModestEngine::Removed)) { |
|
2857 // Only Added & Removed notification will be checked |
|
2858 if (m_latestAddOrRemoveNotifications.count() > 10) { |
|
2859 // Remove the oldest notification from the beginning of the list |
|
2860 m_latestAddOrRemoveNotifications.removeFirst(); |
|
2861 } |
|
2862 // Append new notification |
|
2863 m_latestAddOrRemoveNotifications.append(searchId); |
|
2864 } |
|
2865 } else { |
|
2866 // Add or Remove notification for the message was already handled! |
|
2867 // => Skip unwanted notification |
|
2868 return; |
|
2869 } |
|
2870 |
|
2871 QMessageManager::NotificationFilterIdSet matchingFilters; |
|
2872 |
|
2873 // Copy the filter map to protect against modification during traversal |
|
2874 QMap<int, QMessageFilter> filters(m_filters); |
|
2875 QMap<int, QMessageFilter>::const_iterator it = filters.begin(), end = filters.end(); |
|
2876 QMessage message; |
|
2877 bool messageRetrieved = false; |
|
2878 for ( ; it != end; ++it) { |
|
2879 const QMessageFilter &filter(it.value()); |
|
2880 |
|
2881 if (!messageRetrieved) { |
|
2882 MessagingModestMessage modestMessage = messageFromModest(modestAccountId, |
|
2883 modestFolderId, |
|
2884 modestMessageId); |
|
2885 |
|
2886 if (modestMessage.accountId.isEmpty()) { |
|
2887 return; |
|
2888 } |
|
2889 |
|
2890 if (modestMessage.flags & MessagingModestMessageDeleted) { |
|
2891 notificationType = ModestEngine::Removed; |
|
2892 } |
|
2893 if (modestMessage.size == 0) { |
|
2894 notificationType = ModestEngine::Removed; |
|
2895 } |
|
2896 |
|
2897 message = messageFromModestMessage(modestMessage); |
|
2898 realMessageId =message.id(); |
|
2899 messageRetrieved = true; |
|
2900 } |
|
2901 |
|
2902 if (filter.isEmpty()) { |
|
2903 // Empty filter matches to all messages |
|
2904 matchingFilters.insert(it.key()); |
|
2905 } else { |
|
2906 if (message.type() == QMessage::NoType) { |
|
2907 continue; |
|
2908 } |
|
2909 QMessageFilterPrivate* privateMessageFilter = QMessageFilterPrivate::implementation(filter); |
|
2910 if (privateMessageFilter->filter(message)) { |
|
2911 matchingFilters.insert(it.key()); |
|
2912 } |
|
2913 } |
|
2914 } |
|
2915 |
|
2916 if (matchingFilters.count() > 0) { |
|
2917 if (notificationType == ModestEngine::Added) { |
|
2918 m_messageStore->messageNotification(QMessageStorePrivate::Added, realMessageId, matchingFilters); |
|
2919 } else if (notificationType == ModestEngine::Updated) { |
|
2920 m_messageStore->messageNotification(QMessageStorePrivate::Updated, realMessageId, matchingFilters); |
|
2921 } else if (notificationType == ModestEngine::Removed) { |
|
2922 m_messageStore->messageNotification(QMessageStorePrivate::Removed, realMessageId, matchingFilters); |
|
2923 } |
|
2924 } |
|
2925 } |
|
2926 |
|
2927 QMessageAccountId ModestEngine::accountIdFromModestMessageId(const QString& modestMessageId) const |
|
2928 { |
|
2929 // Modest messageId format is following: |
|
2930 // <email protocol>://<username>@<hostname>:<port>... |
|
2931 QMessageAccountId accountId; |
|
2932 |
|
2933 int usernameBegin = modestMessageId.indexOf("//")+2; |
|
2934 int usernameEnd = modestMessageId.indexOf("@"); |
|
2935 QString username = QUrl::fromPercentEncoding(modestMessageId.mid(usernameBegin, usernameEnd-usernameBegin).toUtf8()); |
|
2936 int hostnameBegin = usernameEnd+1; |
|
2937 int hostnameEnd = modestMessageId.indexOf(':',hostnameBegin); |
|
2938 QString hostname = QUrl::fromPercentEncoding(modestMessageId.mid(hostnameBegin, hostnameEnd-hostnameBegin).toUtf8()); |
|
2939 |
|
2940 foreach (QMessageAccount value, iAccounts) { |
|
2941 QMessageAccountId accId = value.id(); |
|
2942 if ((accountUsername(accId) == username) && |
|
2943 (accountHostname(accId) == hostname)) { |
|
2944 accountId = accId; |
|
2945 } |
|
2946 } |
|
2947 |
|
2948 if (!accountId.isValid()) { |
|
2949 if (modestMessageId.left(modestMessageId.indexOf(':')) == "maildir") { |
|
2950 accountId = QMessageAccountId("MO_LOCAL"); |
|
2951 } |
|
2952 } |
|
2953 |
|
2954 return accountId; |
|
2955 } |
|
2956 |
|
2957 QMessageFolderId ModestEngine::folderIdFromModestMessageId(const QString& modestMessageId, |
|
2958 const QMessageAccountId accountId) const |
|
2959 { |
|
2960 // Modest messageId format is following: |
|
2961 // <email protocol>://<username>@<hostname>:<port>... |
|
2962 QMessageFolderId folderId; |
|
2963 QString folderIdAsString; |
|
2964 |
|
2965 if (!accountId.isValid()) { |
|
2966 folderIdAsString = accountIdFromModestMessageId(modestMessageId).toString(); |
|
2967 } else { |
|
2968 folderIdAsString = accountId.toString(); |
|
2969 } |
|
2970 |
|
2971 int protocolEnd = modestMessageId.indexOf(':'); |
|
2972 QString protocol = modestMessageId.left(protocolEnd); |
|
2973 folderIdAsString += "&" + protocol; |
|
2974 if (protocol == "pop") { |
|
2975 folderIdAsString += "&cache"; |
|
2976 } else if (protocol == "imap") { |
|
2977 int pathBegin = modestMessageId.indexOf('/',modestMessageId.lastIndexOf(':'))+1; |
|
2978 int pathEnd = modestMessageId.lastIndexOf('/'); |
|
2979 folderIdAsString += "&" + modestMessageId.mid(pathBegin, pathEnd-pathBegin); |
|
2980 } else if (protocol == "maildir") { |
|
2981 int pathBegin = modestMessageId.indexOf('#')+1; |
|
2982 int pathEnd = modestMessageId.lastIndexOf('/'); |
|
2983 folderIdAsString += "&" + modestMessageId.mid(pathBegin, pathEnd-pathBegin); |
|
2984 } |
|
2985 folderId = QMessageFolderId(QUrl::fromPercentEncoding(folderIdAsString.toUtf8())); |
|
2986 |
|
2987 return folderId; |
|
2988 } |
|
2989 |
|
2990 QString ModestEngine::modestAccountIdFromAccountId(const QMessageAccountId& accountId) const |
|
2991 { |
|
2992 // Just remove "MO_" prefix from the beginning of id string |
|
2993 return accountId.toString().remove(0,3); |
|
2994 } |
|
2995 |
|
2996 QString ModestEngine::modestFolderIdFromFolderId(const QMessageFolderId& folderId) const |
|
2997 { |
|
2998 QString modestFolderId; |
|
2999 |
|
3000 QString folderIdString = folderId.toString(); |
|
3001 int protocolBegin = folderIdString.indexOf('&'); |
|
3002 int protocolEnd = folderIdString.lastIndexOf('&'); |
|
3003 |
|
3004 modestFolderId = folderIdString.mid(protocolEnd+1); |
|
3005 QString protocol = folderIdString.mid(protocolBegin+1,protocolEnd-protocolBegin-1); |
|
3006 if ((protocol == "pop") && (modestFolderId == "cache")) { |
|
3007 modestFolderId = "INBOX"; |
|
3008 } |
|
3009 |
|
3010 return modestFolderId; |
|
3011 } |
|
3012 |
|
3013 QString ModestEngine::modestFolderUriFromFolderId(const QMessageFolderId& folderId) const |
|
3014 { |
|
3015 Q_UNUSED(folderId) //TODO: |
|
3016 return QString(); |
|
3017 } |
|
3018 |
|
3019 QString ModestEngine::modestAccountIdFromMessageId(const QMessageId& messageId, |
|
3020 bool checkProtocol) const |
|
3021 { |
|
3022 QString id = messageId.toString(); |
|
3023 int protocolBegin = id.indexOf('&'); |
|
3024 int protocolEnd = id.lastIndexOf('&'); |
|
3025 QString protocol = id.mid(protocolBegin+1,protocolEnd-protocolBegin-1); |
|
3026 if (checkProtocol && protocol == "maildir") { |
|
3027 return "local_folders"; |
|
3028 } |
|
3029 |
|
3030 return unescapeString(id.left(protocolBegin).remove(0,3)); |
|
3031 } |
|
3032 |
|
3033 QMessageAccountId ModestEngine::accountIdFromFolderId(const QMessageFolderId& folderId) const |
|
3034 { |
|
3035 QString id = folderId.toString(); |
|
3036 int protocolBegin = id.indexOf('&'); |
|
3037 return QMessageAccountId(id.left(protocolBegin)); |
|
3038 } |
|
3039 |
|
3040 QMessageAccountId ModestEngine::accountIdFromMessageId(const QMessageId& messageId) const |
|
3041 { |
|
3042 QString id = messageId.toString(); |
|
3043 int protocolBegin = id.indexOf('&'); |
|
3044 return QMessageAccountId(id.left(protocolBegin)); |
|
3045 } |
|
3046 |
|
3047 QString ModestEngine::modestAccountIdFromFolderId(const QMessageFolderId& folderId, |
|
3048 bool checkProtocol) const |
|
3049 { |
|
3050 QString id = folderId.toString(); |
|
3051 int protocolBegin = id.indexOf('&'); |
|
3052 int protocolEnd = id.lastIndexOf('&'); |
|
3053 QString protocol = id.mid(protocolBegin+1,protocolEnd-protocolBegin-1); |
|
3054 if (checkProtocol && protocol == "maildir") { |
|
3055 return "local_folders"; |
|
3056 } |
|
3057 |
|
3058 return unescapeString(id.left(protocolBegin).remove(0,3)); |
|
3059 } |
|
3060 |
|
3061 QString ModestEngine::modestFolderIdFromMessageId(const QMessageId& messageId) const |
|
3062 { |
|
3063 QString id = messageId.toString(); |
|
3064 |
|
3065 int protocolBegin = id.indexOf('&'); |
|
3066 int protocolEnd = id.lastIndexOf('&'); |
|
3067 int folderEnd = id.lastIndexOf('/'); |
|
3068 |
|
3069 QString protocol = id.mid(protocolBegin+1,protocolEnd-protocolBegin-1); |
|
3070 id = id.mid(protocolEnd+1,folderEnd-protocolEnd-1); |
|
3071 if ((protocol == "pop") && (id == "cache")) { |
|
3072 id = "INBOX"; |
|
3073 } |
|
3074 |
|
3075 return id; |
|
3076 } |
|
3077 |
|
3078 void ModestEngine::replaceProtocol(QString& id, const QString& newProtocol) const |
|
3079 { |
|
3080 int protocolBegin = id.indexOf('&'); |
|
3081 int protocolEnd = id.lastIndexOf('&'); |
|
3082 id.remove(protocolBegin+1,protocolEnd-protocolBegin-1); |
|
3083 id.insert(protocolBegin+1, newProtocol); |
|
3084 } |
|
3085 |
|
3086 QMessageAccountId ModestEngine::realAccountId(const MessagingModestMessage& modestMessage) const |
|
3087 { |
|
3088 QMessageAccountId accountId; |
|
3089 |
|
3090 if (modestMessage.accountId == "local_folders") { |
|
3091 QString accountIdString; |
|
3092 // Message is in local foldar, but message can be linked |
|
3093 // to actual account using 'From', 'To', 'Cc' or 'Bcc' fields |
|
3094 foreach (QMessageAccount value, iAccounts) { |
|
3095 QMessageAccountPrivate* privAccount = QMessageAccountPrivate::implementation(value); |
|
3096 if (modestMessage.from.contains(privAccount->_address.addressee())) { |
|
3097 accountIdString = value.id().toString(); |
|
3098 break; |
|
3099 } else if (modestMessage.to.contains(privAccount->_address.addressee())) { |
|
3100 accountIdString = value.id().toString(); |
|
3101 break; |
|
3102 } else if (modestMessage.cc.contains(privAccount->_address.addressee())) { |
|
3103 accountIdString = value.id().toString(); |
|
3104 break; |
|
3105 } else if (modestMessage.bcc.contains(privAccount->_address.addressee())) { |
|
3106 accountIdString = value.id().toString(); |
|
3107 break; |
|
3108 } |
|
3109 } |
|
3110 if (!accountIdString.isEmpty()) { |
|
3111 accountId = QMessageAccountId(accountIdString); |
|
3112 } |
|
3113 } else { |
|
3114 accountId = accountIdFromModestAccountId(modestMessage.accountId); |
|
3115 } |
|
3116 |
|
3117 return accountId; |
|
3118 } |
|
3119 |
|
3120 QString ModestEngine::modestMessageIdFromMessageId(const QMessageId& messageId) const |
|
3121 { |
|
3122 QString id = messageId.toString(); |
|
3123 return id.mid(id.lastIndexOf('/')+1); |
|
3124 } |
|
3125 |
|
3126 QMessageAccountId ModestEngine::accountIdFromModestAccountId(const QString& accountId) const |
|
3127 { |
|
3128 // Just add "MO_" prefix to the beginning of id string & escape created Id |
|
3129 return QMessageAccountId(escapeString("MO_"+accountId)); |
|
3130 } |
|
3131 |
|
3132 QMessageFolderId ModestEngine::folderIdFromModestFolderId(const QMessageAccountId& accountId, |
|
3133 bool isLocalFolder, |
|
3134 const QString& modestFolderId) const |
|
3135 { |
|
3136 // Format: <accountId>&<email protocol>&<Modest folderId> |
|
3137 QMessageFolderId folderId; |
|
3138 |
|
3139 if (isLocalFolder) { |
|
3140 folderId = QMessageFolderId(accountId.toString()+"&maildir&"+modestFolderId); |
|
3141 } else { |
|
3142 QString protocol = accountEmailProtocolAsString(accountId); |
|
3143 if ((protocol == "pop") && (modestFolderId == "INBOX")) { |
|
3144 folderId = QMessageFolderId(accountId.toString()+"&"+protocol+"&cache"); |
|
3145 } else { |
|
3146 folderId = QMessageFolderId(accountId.toString()+"&"+protocol+"&"+modestFolderId); |
|
3147 } |
|
3148 } |
|
3149 |
|
3150 return folderId; |
|
3151 } |
|
3152 |
|
3153 QMessageId ModestEngine::messageIdFromModestMessageId(const QString& messageId) const |
|
3154 { |
|
3155 QString messageIdString = folderIdFromModestMessageId(messageId).toString(); |
|
3156 int idPartBegin = messageId.lastIndexOf('/'); |
|
3157 messageIdString += messageId.mid(idPartBegin, idPartBegin-messageId.length()); |
|
3158 return QMessageId(messageIdString); |
|
3159 } |
|
3160 |
|
3161 QMessageId ModestEngine::messageIdFromModestMessageFilePath(const QString& messageFilePath) const |
|
3162 { |
|
3163 QString messageIdString; |
|
3164 |
|
3165 QString filePath = messageFilePath; |
|
3166 QString localRootFolder = this->localRootFolder(); |
|
3167 if (filePath.startsWith(localRootFolder)) { |
|
3168 messageIdString = "MO_LOCAL&maildir&"; |
|
3169 filePath.remove(0,localRootFolder.length()+1); |
|
3170 filePath.remove("/cur"); |
|
3171 messageIdString += filePath.left(filePath.lastIndexOf('!')); |
|
3172 } else { |
|
3173 foreach (QMessageAccount value, iAccounts) { |
|
3174 QMessageAccountId accountId = value.id(); |
|
3175 QString rootFolder = accountRootFolder(accountId); |
|
3176 if (filePath.startsWith(rootFolder)) { |
|
3177 QString protocol = accountEmailProtocolAsString(accountId); |
|
3178 messageIdString = accountId.toString()+"&"+protocol+"&"; |
|
3179 filePath.remove(0,rootFolder.length()+1); |
|
3180 filePath.remove("/subfolders"); |
|
3181 messageIdString += filePath.left(filePath.lastIndexOf('.')); |
|
3182 if (protocol == "pop") { |
|
3183 QDir dir(messageFilePath); |
|
3184 dir.setFilter(QDir::AllEntries | QDir::NoDotAndDotDot); |
|
3185 QFileInfoList dirs = dir.entryInfoList(); |
|
3186 if (dirs.count() > 0) { |
|
3187 QString fileName = dirs[0].fileName(); |
|
3188 // Remove folder that contains actual message |
|
3189 messageIdString = messageIdString.left(messageIdString.lastIndexOf('/')+1); |
|
3190 // Add message name |
|
3191 messageIdString = messageIdString+fileName; |
|
3192 } |
|
3193 } |
|
3194 } |
|
3195 } |
|
3196 } |
|
3197 |
|
3198 return QMessageId(messageIdString); |
|
3199 } |
|
3200 |
|
3201 QString ModestEngine::unescapeString(const QString& string) |
|
3202 { |
|
3203 QString unescapedString; |
|
3204 |
|
3205 QByteArray str = string.toUtf8(); |
|
3206 gchar* unescaped_string = gconf_unescape_key(str.data(), str.length()); |
|
3207 unescapedString = QString::fromUtf8(unescaped_string); |
|
3208 g_free(unescaped_string); |
|
3209 |
|
3210 return unescapedString; |
|
3211 } |
|
3212 |
|
3213 QString ModestEngine::escapeString(const QString& string) |
|
3214 { |
|
3215 QString escapedString; |
|
3216 |
|
3217 QByteArray str = unescapeString(string).toUtf8(); |
|
3218 gchar* escaped_string = gconf_escape_key(str.data(), str.length()); |
|
3219 escapedString = QString::fromUtf8(escaped_string); |
|
3220 g_free(escaped_string); |
|
3221 |
|
3222 return escapedString; |
|
3223 } |
|
3224 |
|
3225 INotifyWatcher::INotifyWatcher() |
|
3226 { |
|
3227 // Initialize inotify instance |
|
3228 // => returned file descriptor is associated with |
|
3229 // a new inotify event queue |
|
3230 // O_CLOEXEC flag makes sure that file descriptor |
|
3231 // is closed if execution is transfered |
|
3232 // from this process to a new program |
|
3233 // (Check more info from 'execve' documentation) |
|
3234 #ifdef IN_CLOEXEC |
|
3235 m_inotifyFileDescriptor = inotify_init1(IN_CLOEXEC); |
|
3236 #else |
|
3237 m_inotifyFileDescriptor = inotify_init(); |
|
3238 if (m_inotifyFileDescriptor >= 0) { |
|
3239 ::fcntl(m_inotifyFileDescriptor, F_SETFD, FD_CLOEXEC); |
|
3240 } |
|
3241 #endif |
|
3242 if (m_inotifyFileDescriptor >= 0) { |
|
3243 // Change thread affinity for this object to this |
|
3244 // thread. |
|
3245 // => Event processing (for this objects events) will |
|
3246 // be done in this thread |
|
3247 moveToThread(this); |
|
3248 } |
|
3249 } |
|
3250 |
|
3251 INotifyWatcher::~INotifyWatcher() |
|
3252 { |
|
3253 // Tell the thread's event loop to exit |
|
3254 // => thread returns from the call to exec() |
|
3255 exit(); |
|
3256 |
|
3257 // Wait until this thread has finished execution |
|
3258 // <=> waits until thread returns from run() |
|
3259 wait(); |
|
3260 |
|
3261 clear(); |
|
3262 |
|
3263 // Close file descriptor that's referring to inotify instance |
|
3264 // => The underlying inotify object and its resources are freed |
|
3265 ::close(m_inotifyFileDescriptor); |
|
3266 } |
|
3267 |
|
3268 void INotifyWatcher::clear() |
|
3269 { |
|
3270 // Remove all watches from inotify instance watch list |
|
3271 QMapIterator<int, QString> i(m_dirs); |
|
3272 while (i.hasNext()) { |
|
3273 inotify_rm_watch(m_inotifyFileDescriptor, i.next().key()); |
|
3274 } |
|
3275 m_dirs.clear(); |
|
3276 |
|
3277 QMapIterator<int, QString> j(m_files); |
|
3278 while (j.hasNext()) { |
|
3279 inotify_rm_watch(m_inotifyFileDescriptor, j.next().key()); |
|
3280 } |
|
3281 m_files.clear(); |
|
3282 } |
|
3283 |
|
3284 void INotifyWatcher::run() |
|
3285 { |
|
3286 // Start listening inotify |
|
3287 QSocketNotifier socketNotifier(m_inotifyFileDescriptor, QSocketNotifier::Read, this); |
|
3288 connect(&socketNotifier, SIGNAL(activated(int)), SLOT(notifySlot())); |
|
3289 |
|
3290 // Enter the thread event loop |
|
3291 (void) exec(); |
|
3292 } |
|
3293 |
|
3294 int INotifyWatcher::addFile(const QString& path, uint eventsToWatch) |
|
3295 { |
|
3296 int watchDescriptor = 0; |
|
3297 QMutexLocker locker(&m_mutex); |
|
3298 |
|
3299 if (m_inotifyFileDescriptor >= 0) { |
|
3300 int watchDescriptor = 0; |
|
3301 if (eventsToWatch == 0) { |
|
3302 watchDescriptor = inotify_add_watch(m_inotifyFileDescriptor, |
|
3303 QFile::encodeName(path), |
|
3304 0 | IN_ATTRIB |
|
3305 | IN_MODIFY |
|
3306 | IN_MOVE |
|
3307 | IN_MOVE_SELF |
|
3308 | IN_DELETE_SELF); |
|
3309 } else { |
|
3310 watchDescriptor = inotify_add_watch(m_inotifyFileDescriptor, |
|
3311 QFile::encodeName(path), |
|
3312 eventsToWatch); |
|
3313 } |
|
3314 if (watchDescriptor > 0) { |
|
3315 m_files.insert(watchDescriptor, path); |
|
3316 } else { |
|
3317 watchDescriptor = 0; |
|
3318 } |
|
3319 } |
|
3320 |
|
3321 // Start thread (if thread is not already running) |
|
3322 start(); |
|
3323 |
|
3324 return watchDescriptor; |
|
3325 } |
|
3326 |
|
3327 int INotifyWatcher::addDirectory(const QString& path, uint eventsToWatch) |
|
3328 { |
|
3329 int watchDescriptor = 0; |
|
3330 QMutexLocker locker(&m_mutex); |
|
3331 |
|
3332 if (m_inotifyFileDescriptor >= 0) { |
|
3333 int watchDescriptor = 0; |
|
3334 if (eventsToWatch == 0) { |
|
3335 watchDescriptor = inotify_add_watch(m_inotifyFileDescriptor, |
|
3336 QFile::encodeName(path), |
|
3337 0 | IN_ATTRIB |
|
3338 | IN_MOVE |
|
3339 | IN_CREATE |
|
3340 | IN_DELETE |
|
3341 | IN_DELETE_SELF); |
|
3342 } else { |
|
3343 watchDescriptor = inotify_add_watch(m_inotifyFileDescriptor, |
|
3344 QFile::encodeName(path), |
|
3345 eventsToWatch); |
|
3346 } |
|
3347 if (watchDescriptor > 0) { |
|
3348 m_dirs.insert(watchDescriptor, path); |
|
3349 } else { |
|
3350 watchDescriptor = 0; |
|
3351 } |
|
3352 } |
|
3353 |
|
3354 // Start thread (if thread is not already running) |
|
3355 start(); |
|
3356 |
|
3357 return watchDescriptor; |
|
3358 } |
|
3359 |
|
3360 QStringList INotifyWatcher::directories() const |
|
3361 { |
|
3362 return m_dirs.values(); |
|
3363 } |
|
3364 |
|
3365 QStringList INotifyWatcher::files() const |
|
3366 { |
|
3367 return m_dirs.values(); |
|
3368 } |
|
3369 |
|
3370 void INotifyWatcher::notifySlot() |
|
3371 { |
|
3372 QMutexLocker locker(&m_mutex); |
|
3373 |
|
3374 int bufferSize = 0; |
|
3375 ioctl(m_inotifyFileDescriptor, FIONREAD, (char*) &bufferSize); |
|
3376 QVarLengthArray<char, 4096> buffer(bufferSize); |
|
3377 bufferSize = read(m_inotifyFileDescriptor, buffer.data(), bufferSize); |
|
3378 const char* at = buffer.data(); |
|
3379 const char* const end = at + bufferSize; |
|
3380 |
|
3381 QMap<int, INotifyEvent> eventsForWatchedFile; |
|
3382 QMap<QString, INotifyEvent> eventsForFileInWatchedDirectory; |
|
3383 while (at < end) { |
|
3384 const inotify_event *event = reinterpret_cast<const inotify_event *>(at); |
|
3385 if (m_files.contains(event->wd)) { |
|
3386 // File event handling |
|
3387 if (eventsForWatchedFile.contains(event->wd)) { |
|
3388 // There is already unhandled event for this file in queue |
|
3389 // => Mask is ORed to existing event |
|
3390 eventsForWatchedFile[event->wd].mask |= event->mask; |
|
3391 } else { |
|
3392 // There is no event for this file in queue |
|
3393 // => New event is created |
|
3394 INotifyEvent inotifyEvent; |
|
3395 inotifyEvent.watchDescriptor = event->wd; |
|
3396 inotifyEvent.mask = event->mask; |
|
3397 inotifyEvent.fileName = QString::fromAscii(event->name, event->len); |
|
3398 eventsForWatchedFile.insert(event->wd, inotifyEvent); |
|
3399 } |
|
3400 } else { |
|
3401 // Directory event handling |
|
3402 QString changeForFileInDirectory = QString::fromAscii(event->name, event->len); |
|
3403 // Remove unnecessary postfix (starting with '!') from the file name |
|
3404 changeForFileInDirectory = changeForFileInDirectory.left(changeForFileInDirectory.lastIndexOf('!')); |
|
3405 if (!changeForFileInDirectory.isEmpty()) { |
|
3406 QString eventId = QString::number(event->wd)+changeForFileInDirectory; |
|
3407 if (eventsForFileInWatchedDirectory.contains(eventId)) { |
|
3408 // There is already unhandled event for this file in queue |
|
3409 // => Mask is ORed to existing event |
|
3410 eventsForFileInWatchedDirectory[eventId].mask |= event->mask; |
|
3411 } else { |
|
3412 // There is no event for this file in queue |
|
3413 // => New event is created |
|
3414 INotifyEvent inotifyEvent; |
|
3415 inotifyEvent.watchDescriptor = event->wd; |
|
3416 inotifyEvent.mask = event->mask; |
|
3417 inotifyEvent.fileName = QString::fromAscii(event->name, event->len); |
|
3418 eventsForFileInWatchedDirectory.insert(eventId, inotifyEvent); |
|
3419 } |
|
3420 } |
|
3421 } |
|
3422 at += sizeof(inotify_event) + event->len; |
|
3423 } |
|
3424 |
|
3425 QMap<int, INotifyEvent>::const_iterator it = eventsForWatchedFile.constBegin(); |
|
3426 while (it != eventsForWatchedFile.constEnd()) { |
|
3427 INotifyEvent event = *it; |
|
3428 QString file = m_files.value(event.watchDescriptor); |
|
3429 if (!file.isEmpty()) { |
|
3430 emit fileChanged(event.watchDescriptor, file, event.mask); |
|
3431 } |
|
3432 ++it; |
|
3433 } |
|
3434 |
|
3435 QMap<QString, INotifyEvent>::const_iterator jt = eventsForFileInWatchedDirectory.constBegin(); |
|
3436 while (jt != eventsForFileInWatchedDirectory.constEnd()) { |
|
3437 INotifyEvent event = *jt; |
|
3438 QString file = m_dirs.value(event.watchDescriptor)+"/"+event.fileName; |
|
3439 emit fileChanged(event.watchDescriptor, file, event.mask); |
|
3440 ++jt; |
|
3441 } |
|
3442 } |
|
3443 |
|
3444 ModestStringMap ModestEngine::getModestSenderInfo(QMessage &message) |
|
3445 { |
|
3446 QMessageAddress address; |
|
3447 ModestStringMap senderInfo; |
|
3448 QMessageAccountId accountId; |
|
3449 QString value; |
|
3450 |
|
3451 accountId = message.parentAccountId(); |
|
3452 if (accountId.isValid() == false) { |
|
3453 qWarning () << "Account ID is invalid"; |
|
3454 return ModestStringMap(); |
|
3455 } |
|
3456 |
|
3457 senderInfo["account-name"] = unescapeString(modestAccountIdFromAccountId(accountId)); |
|
3458 |
|
3459 QMessageAccount messageAccount = account(accountId); |
|
3460 QMessageAccountPrivate* privAccount = QMessageAccountPrivate::implementation(messageAccount); |
|
3461 address = privAccount->_address; |
|
3462 value = address.addressee(); |
|
3463 |
|
3464 if (value.isEmpty() == false && value.isNull() == false) { |
|
3465 senderInfo["from"] = value; |
|
3466 } |
|
3467 |
|
3468 return senderInfo; |
|
3469 } |
|
3470 |
|
3471 ModestStringMap ModestEngine::getModestRecipients(QMessage &message) |
|
3472 { |
|
3473 QMessageAddressList addresses; |
|
3474 QMessageAddress address; |
|
3475 ModestStringMap recipients; |
|
3476 QString value; |
|
3477 |
|
3478 addresses = message.to(); |
|
3479 value.clear(); |
|
3480 for (int i = 0; i < addresses.length(); i++) { |
|
3481 address = addresses[i]; |
|
3482 |
|
3483 if (value.isEmpty()) { |
|
3484 value = address.addressee(); |
|
3485 } else { |
|
3486 value.append (","); |
|
3487 value.append (address.addressee()); |
|
3488 } |
|
3489 } |
|
3490 |
|
3491 if (value.isEmpty() == false && value.isNull() == false) { |
|
3492 recipients["to"] = value; |
|
3493 } |
|
3494 |
|
3495 addresses = message.cc(); |
|
3496 value.clear(); |
|
3497 for (int i = 0; i < addresses.length(); i++) { |
|
3498 address = addresses[i]; |
|
3499 |
|
3500 if (value.isEmpty()) { |
|
3501 value = address.addressee(); |
|
3502 } else { |
|
3503 value.append (","); |
|
3504 value.append (address.addressee()); |
|
3505 } |
|
3506 } |
|
3507 |
|
3508 if (value.isEmpty() == false && value.isNull() == false) { |
|
3509 recipients["cc"] = value; |
|
3510 } |
|
3511 |
|
3512 addresses = message.bcc(); |
|
3513 value.clear(); |
|
3514 for (int i = 0; i < addresses.length(); i++) { |
|
3515 address = addresses[i]; |
|
3516 |
|
3517 if (value.isEmpty()) { |
|
3518 value = address.addressee(); |
|
3519 } else { |
|
3520 value.append (","); |
|
3521 value.append (address.addressee()); |
|
3522 } |
|
3523 } |
|
3524 |
|
3525 if (value.isEmpty() == false && value.isNull() == false) { |
|
3526 recipients["bcc"] = value; |
|
3527 } |
|
3528 |
|
3529 return recipients; |
|
3530 } |
|
3531 |
|
3532 ModestStringMap ModestEngine::getModestMessageData(QMessage &message) |
|
3533 { |
|
3534 QMessageContentContainerId bodyId; |
|
3535 QMessageContentContainer body; |
|
3536 ModestStringMap messageData; |
|
3537 QString value; |
|
3538 |
|
3539 value = message.subject(); |
|
3540 |
|
3541 if (value.isEmpty() == false && value.isNull() == false) { |
|
3542 messageData["subject"] = value; |
|
3543 } |
|
3544 |
|
3545 bodyId = message.bodyId(); |
|
3546 if (bodyId.isValid()) { |
|
3547 body = message.find (bodyId); |
|
3548 } else { |
|
3549 body = message; |
|
3550 } |
|
3551 |
|
3552 value = body.contentType(); |
|
3553 |
|
3554 if (value == "text") { |
|
3555 QString key, data; |
|
3556 bool hasContent = false; |
|
3557 |
|
3558 value = body.contentSubType(); |
|
3559 |
|
3560 if ((hasContent = body.isContentAvailable()) == true) { |
|
3561 data = body.textContent(); |
|
3562 } |
|
3563 |
|
3564 if (value == "plain") { |
|
3565 key = "plain-body"; |
|
3566 } else if (value == "html") { |
|
3567 key = "html-body"; |
|
3568 } |
|
3569 |
|
3570 if (key.isEmpty() == false && key.isNull() == false && hasContent) { |
|
3571 messageData[key] = data; |
|
3572 } |
|
3573 } |
|
3574 |
|
3575 if (message.status() & QMessage::Read) { |
|
3576 messageData["read"] = ""; |
|
3577 } |
|
3578 |
|
3579 return messageData; |
|
3580 } |
|
3581 |
|
3582 ModestStringMapList ModestEngine::getModestAttachments(QMessage &message) |
|
3583 { |
|
3584 QMessageContentContainerIdList attachmentIds; |
|
3585 ModestStringMapList attachments; |
|
3586 QMessage::StatusFlags messageStatus; |
|
3587 QString value; |
|
3588 |
|
3589 messageStatus = message.status(); |
|
3590 |
|
3591 if (messageStatus & QMessage::HasAttachments) { |
|
3592 attachmentIds = message.attachmentIds(); |
|
3593 |
|
3594 foreach (QMessageContentContainerId identifier, attachmentIds) { |
|
3595 ModestStringMap attachmentData; |
|
3596 QMessageContentContainer attachmentCont; |
|
3597 |
|
3598 if (identifier.isValid() == false) continue; |
|
3599 |
|
3600 attachmentCont = message.find (identifier); |
|
3601 |
|
3602 if (attachmentCont.isContentAvailable () == false) continue; |
|
3603 |
|
3604 attachmentData.clear(); |
|
3605 |
|
3606 value = attachmentCont.contentType(); |
|
3607 |
|
3608 if (value.isEmpty() == false) { |
|
3609 value.append("/"); |
|
3610 value.append (attachmentCont.contentSubType()); |
|
3611 attachmentData["mime-type"] = value; |
|
3612 |
|
3613 qDebug() << "mime-type: " << value; |
|
3614 } |
|
3615 |
|
3616 value = QMessageContentContainerPrivate::attachmentFilename ( |
|
3617 attachmentCont); |
|
3618 |
|
3619 if (value.isEmpty() == false) { |
|
3620 attachmentData["filename"] = value; |
|
3621 qDebug() << "filename: " << value; |
|
3622 } |
|
3623 |
|
3624 qDebug() << "Charset: " << attachmentCont.contentCharset(); |
|
3625 qDebug() << "Headers: " << attachmentCont.headerFields(); |
|
3626 |
|
3627 if (attachmentData.isEmpty() == false) { |
|
3628 attachmentData["content-id"] = identifier.toString(); |
|
3629 attachments.append (attachmentData); |
|
3630 } |
|
3631 } |
|
3632 } |
|
3633 |
|
3634 return attachments; |
|
3635 } |
|
3636 |
|
3637 ModestStringMapList ModestEngine::getModestImages(QMessage &message) |
|
3638 { |
|
3639 Q_UNUSED(message); |
|
3640 // Don't know if this even makes sense. Modest expects inlined images |
|
3641 // to be in a separate list, but that doesn't make much sense? |
|
3642 return ModestStringMapList(); |
|
3643 } |
|
3644 |
|
3645 uint ModestEngine::getModestPriority(QMessage &message) |
|
3646 { |
|
3647 uint priority = 0; |
|
3648 |
|
3649 switch (message.priority()) { |
|
3650 case QMessage::HighPriority: |
|
3651 priority = MODESTENGINE_HIGH_PRIORITY; |
|
3652 break; |
|
3653 |
|
3654 default: |
|
3655 case QMessage::NormalPriority: |
|
3656 priority = MODESTENGINE_NORMAL_PRIORITY; |
|
3657 break; |
|
3658 |
|
3659 case QMessage::LowPriority: |
|
3660 priority = MODESTENGINE_LOW_PRIORITY; |
|
3661 break; |
|
3662 } |
|
3663 |
|
3664 return priority; |
|
3665 } |
|
3666 |
|
3667 ModestStringMap ModestEngine::getModestHeaders(QMessage &message) |
|
3668 { |
|
3669 Q_UNUSED(message); |
|
3670 return ModestStringMap(); // stub |
|
3671 } |
|
3672 |
|
3673 void ModestEngine::clearHeaderCache() |
|
3674 { |
|
3675 m_messageCache.clear(); |
|
3676 } |
|
3677 |
|
3678 #include "moc_modestengine_maemo_p.cpp" |
|
3679 |
|
3680 QTM_END_NAMESPACE |