Merge lp:~phablet-team/telephony-service/async_send_message into lp:telephony-service

Proposed by Gustavo Pichorim Boiko
Status: Superseded
Proposed branch: lp:~phablet-team/telephony-service/async_send_message
Merge into: lp:telephony-service
Diff against target: 2249 lines (+1179/-423)
31 files modified
.bzrignore (+1/-0)
approver/TelephonyServiceApprover.client (+0/-1)
approver/approver.cpp (+5/-3)
handler/CMakeLists.txt (+3/-0)
handler/Handler.xml (+3/-12)
handler/TelephonyServiceHandler.client (+2/-7)
handler/chatstartingjob.cpp (+149/-0)
handler/chatstartingjob.h (+64/-0)
handler/handlerdbus.cpp (+25/-10)
handler/handlerdbus.h (+8/-4)
handler/main.cpp (+1/-3)
handler/messagejob.cpp (+82/-0)
handler/messagejob.h (+68/-0)
handler/messagesendingjob.cpp (+375/-0)
handler/messagesendingjob.h (+87/-0)
handler/texthandler.cpp (+53/-331)
handler/texthandler.h (+7/-18)
indicator/TelephonyServiceIndicator.client (+0/-5)
indicator/textchannelobserver.cpp (+7/-2)
libtelephonyservice/accountentry.cpp (+33/-0)
libtelephonyservice/accountentry.h (+16/-0)
libtelephonyservice/chatentry.cpp (+64/-1)
libtelephonyservice/chatentry.h (+14/-0)
libtelephonyservice/chatmanager.cpp (+58/-14)
libtelephonyservice/chatmanager.h (+2/-3)
libtelephonyservice/telepathyhelper.cpp (+12/-0)
libtelephonyservice/telepathyhelper.h (+9/-0)
tests/common/mock/connection.cpp (+7/-1)
tests/handler/handlercontroller.cpp (+9/-2)
tests/libtelephonyservice/ChatEntryTest.cpp (+4/-2)
tests/libtelephonyservice/ChatManagerTest.cpp (+11/-4)
To merge this branch: bzr merge lp:~phablet-team/telephony-service/async_send_message
Reviewer Review Type Date Requested Status
Ubuntu Phablet Team Pending
Review via email: mp+295528@code.launchpad.net

This proposal has been superseded by a proposal from 2016-05-24.

Commit message

Make it possible to send messages asynchronously and still report the results.

Description of the change

Make it possible to send messages asynchronously and still report the results.

To post a comment you must log in.
1204. By Gustavo Pichorim Boiko

Fix some problems, remove some code not needed anymore and add some debug.

1205. By Gustavo Pichorim Boiko

Remove empty spaces.

1206. By Gustavo Pichorim Boiko

Change ChatEntry to fetch channels from ChatManager and to send messages using the new asynchronous API.

1207. By Gustavo Pichorim Boiko

Merge parent branch

1208. By Gustavo Pichorim Boiko

Implement channel matching.

1209. By Gustavo Pichorim Boiko

Expose the chatentry to QML.

1210. By Gustavo Pichorim Boiko

Make it possible to set the chat type

1211. By Gustavo Pichorim Boiko

Finish implementing the message sending job and make use of it in chatentry.

1212. By Gustavo Pichorim Boiko

Watch for new channels.

1213. By Gustavo Pichorim Boiko

Do not pass the interface when registering the jobs, it is already present in
the adaptor.

1214. By Gustavo Pichorim Boiko

Start chat with accounts that might have typing notifications.

1215. By Gustavo Pichorim Boiko

Ignore message sending job adaptor.

1216. By Gustavo Pichorim Boiko

Fix ChatManager tests.

1217. By Gustavo Pichorim Boiko

Fix handler tests

1218. By Gustavo Pichorim Boiko

Set also the threadId in properties so that the channel gets
created correctly.

1219. By Gustavo Pichorim Boiko

If no accountId is given, match channels from all accounts.

1220. By Gustavo Pichorim Boiko

Only set the accountId in properties if we are trying to match a chatroom

1221. By Gustavo Pichorim Boiko

We don't need to verify accounts here, it is done in a later stage if needed

1222. By Gustavo Pichorim Boiko

merge parent

1223. By Gustavo Pichorim Boiko

Do not delete the interface classes. They are destroyed together with the channel itself.

1224. By Gustavo Pichorim Boiko

Update copyright headers.

1225. By Gustavo Pichorim Boiko

Merge parent

1226. By Gustavo Pichorim Boiko

Expose chatstarting to dbus

1227. By Gustavo Pichorim Boiko

Make startChat return the job's objectPath

1228. By Gustavo Pichorim Boiko

Remove wrongly committed changelog.

1229. By Tiago Salem Herrmann

merge parent branch

1230. By Tiago Salem Herrmann

merge parent branch

1231. By Tiago Salem Herrmann

merge parent branch

1232. By Gustavo Pichorim Boiko

Handle channel invalidation.

1233. By Tiago Salem Herrmann

merge parent branch

1234. By Tiago Salem Herrmann

merge parent branch

1235. By Tiago Salem Herrmann

merge parent branch

1236. By Tiago Salem Herrmann

merge parent branch

1237. By Tiago Salem Herrmann

fix handler test

1238. By Tiago Salem Herrmann

merge parent branch

1239. By Tiago Salem Herrmann

merge parent branch

1240. By Gustavo Pichorim Boiko

Add a FIXME on a disabled test

1241. By Gustavo Pichorim Boiko

Merge parent

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2015-07-02 03:35:20 +0000
3+++ .bzrignore 2016-05-24 01:13:17 +0000
4@@ -57,3 +57,4 @@
5 tests/libtelephonyservice/GreeterContactsTestExe
6 tests/libtelephonyservice/GreeterContactsTestServerExe
7 tests/libtelephonyservice/*Mock
8+tests/indicator/NotificationsInterface.*
9
10=== modified file 'approver/TelephonyServiceApprover.client'
11--- approver/TelephonyServiceApprover.client 2013-07-17 17:50:32 +0000
12+++ approver/TelephonyServiceApprover.client 2016-05-24 01:13:17 +0000
13@@ -8,7 +8,6 @@
14
15 [org.freedesktop.Telepathy.Client.Approver.ApproverChannelFilter 1]
16 org.freedesktop.Telepathy.Channel.ChannelType s=org.freedesktop.Telepathy.Channel.Type.Text
17-org.freedesktop.Telepathy.Channel.TargetHandleType u=1
18
19 [org.freedesktop.Telepathy.Client.Approver.Capabilities]
20 org.freedesktop.Telepathy.Channel.Type.Call1/audio=true
21
22=== modified file 'approver/approver.cpp'
23--- approver/approver.cpp 2016-01-05 17:14:32 +0000
24+++ approver/approver.cpp 2016-05-24 01:13:17 +0000
25@@ -412,10 +412,12 @@
26 void Approver::onRejectMessage(Tp::ChannelDispatchOperationPtr dispatchOp, const char *action)
27 {
28 if (mRejectActions.contains(action)) {
29- QString targetId = dispatchOp->channels().first()->targetContact()->id();
30+ QVariantMap properties;
31+ properties["participantIds"] = QStringList() << dispatchOp->channels().first()->targetContact()->id();
32 ChatManager::instance()->sendMessage(dispatchOp->account()->uniqueIdentifier(),
33- QStringList() << targetId,
34- mRejectActions[action]);
35+ mRejectActions[action],
36+ QVariantMap(), // attachments
37+ properties);
38 }
39
40 onRejected(dispatchOp);
41
42=== modified file 'handler/CMakeLists.txt'
43--- handler/CMakeLists.txt 2016-03-18 19:02:50 +0000
44+++ handler/CMakeLists.txt 2016-05-24 01:13:17 +0000
45@@ -1,8 +1,11 @@
46
47 set(qt_SRCS
48 callhandler.cpp
49+ chatstartingjob.cpp
50 handler.cpp
51 handlerdbus.cpp
52+ messagejob.cpp
53+ messagesendingjob.cpp
54 texthandler.cpp
55 )
56
57
58=== modified file 'handler/Handler.xml'
59--- handler/Handler.xml 2015-12-07 16:26:20 +0000
60+++ handler/Handler.xml 2016-05-24 01:13:17 +0000
61@@ -16,13 +16,12 @@
62 Request to send a message to one or multiple recipients
63 ]]></dox:d>
64 <arg name="accountId" type="s" direction="in"/>
65- <arg name="recipients" type="as" direction="in"/>
66 <arg name="message" type="s" direction="in"/>
67 <arg name="attachments" type="a(sss)" direction="in"/>
68 <arg name="accountIdOut" type="s" direction="out"/>
69- <annotation name="org.qtproject.QtDBus.QtTypeName.In3" value="AttachmentList"/>
70+ <annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="AttachmentList"/>
71 <arg name="properties" type="a{sv}" direction="in"/>
72- <annotation name="org.qtproject.QtDBus.QtTypeName.In4" value="QVariantMap"/>
73+ <annotation name="org.qtproject.QtDBus.QtTypeName.In3" value="QVariantMap"/>
74 </method>
75 <method name="AcknowledgeMessages">
76 <dox:d><![CDATA[
77@@ -37,16 +36,8 @@
78 Start a chat with the given participants
79 ]]></dox:d>
80 <arg name="accountId" type="s" direction="in"/>
81- <arg name="participants" type="as" direction="in"/>
82- </method>
83- <method name="StartChatRoom">
84- <dox:d><![CDATA[
85- Start a chat room with the given properties
86- ]]></dox:d>
87- <arg name="accountId" type="s" direction="in"/>
88- <arg name="initialParticipants" type="as" direction="in"/>
89 <arg name="properties" type="a{sv}" direction="in"/>
90- <annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="QVariantMap"/>
91+ <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
92 </method>
93 <method name="AcknowledgeAllMessages">
94 <dox:d><![CDATA[
95
96=== modified file 'handler/TelephonyServiceHandler.client'
97--- handler/TelephonyServiceHandler.client 2014-11-19 17:39:57 +0000
98+++ handler/TelephonyServiceHandler.client 2016-05-24 01:13:17 +0000
99@@ -3,11 +3,6 @@
100
101 [org.freedesktop.Telepathy.Client.Handler.HandlerChannelFilter 0]
102 org.freedesktop.Telepathy.Channel.ChannelType s=org.freedesktop.Telepathy.Channel.Type.Text
103-org.freedesktop.Telepathy.Channel.TargetHandleType u=1
104-
105-[org.freedesktop.Telepathy.Client.Handler.HandlerChannelFilter 1]
106-org.freedesktop.Telepathy.Channel.ChannelType s=org.freedesktop.Telepathy.Channel.Type.Text
107-org.freedesktop.Telepathy.Channel.TargetHandleType u=0
108-
109-[org.freedesktop.Telepathy.Client.Handler.HandlerChannelFilter 2]
110+
111+[org.freedesktop.Telepathy.Client.Handler.HandlerChannelFilter 3]
112 org.freedesktop.Telepathy.Channel.ChannelType s=org.freedesktop.Telepathy.Channel.Type.Call1
113
114=== added file 'handler/chatstartingjob.cpp'
115--- handler/chatstartingjob.cpp 1970-01-01 00:00:00 +0000
116+++ handler/chatstartingjob.cpp 2016-05-24 01:13:17 +0000
117@@ -0,0 +1,149 @@
118+/*
119+ * Copyright (C) 2016 Canonical, Ltd.
120+ *
121+ * Authors:
122+ * Tiago Salem Herrmann <tiago.herrmann@canonical.com>
123+ * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com>
124+ *
125+ * This file is part of telephony-service.
126+ *
127+ * telephony-service is free software; you can redistribute it and/or modify
128+ * it under the terms of the GNU General Public License as published by
129+ * the Free Software Foundation; version 3.
130+ *
131+ * telephony-service is distributed in the hope that it will be useful,
132+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
133+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
134+ * GNU General Public License for more details.
135+ *
136+ * You should have received a copy of the GNU General Public License
137+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
138+ */
139+
140+#include "chatstartingjob.h"
141+#include "telepathyhelper.h"
142+#include "texthandler.h"
143+#include <TelepathyQt/PendingChannelRequest>
144+
145+ChatStartingJob::ChatStartingJob(TextHandler *textHandler, const QString &accountId, const QVariantMap &properties)
146+: MessageJob(textHandler), mAccountId(accountId), mProperties(properties)
147+{
148+}
149+
150+void ChatStartingJob::startJob()
151+{
152+ setStatus(Running);
153+
154+ // Request the contact to start chatting to
155+ // FIXME: make it possible to select which account to use, for now, pick the first one
156+ AccountEntry *account = TelepathyHelper::instance()->accountForId(mAccountId);
157+ if (!account || !account->connected()) {
158+ qCritical() << "The selected account does not have a connection. AccountId:" << mAccountId;
159+ setStatus(Failed);
160+ scheduleDeletion();
161+ return;
162+ }
163+
164+ switch(mProperties["chatType"].toUInt()) {
165+ case Tp::HandleTypeNone:
166+ case Tp::HandleTypeContact:
167+ startTextChat(account->account(), mProperties);
168+ break;
169+ case Tp::HandleTypeRoom:
170+ startTextChatRoom(account->account(), mProperties);
171+ break;
172+ default:
173+ qCritical() << "Chat type not supported";
174+ }
175+}
176+
177+void ChatStartingJob::startTextChat(const Tp::AccountPtr &account, const QVariantMap &properties)
178+{
179+ Tp::PendingChannelRequest *op = NULL;
180+ QStringList participants = properties["participantIds"].toStringList();
181+ switch(participants.size()) {
182+ case 0:
183+ qCritical() << "Error: No participant list provided";
184+ return;
185+ case 1:
186+ op = account->ensureTextChat(participants[0], QDateTime::currentDateTime(), TP_QT_IFACE_CLIENT + ".TelephonyServiceHandler");
187+ break;
188+ default:
189+ op = account->createConferenceTextChat(QList<Tp::ChannelPtr>(), participants, QDateTime::currentDateTime(), TP_QT_IFACE_CLIENT + ".TelephonyServiceHandler");
190+ }
191+
192+ if (!op) {
193+ setStatus(Failed);
194+ scheduleDeletion();
195+ return;
196+ }
197+
198+ connect(op, &Tp::PendingOperation::finished,
199+ this, &ChatStartingJob::onChannelRequestFinished);
200+}
201+
202+void ChatStartingJob::startTextChatRoom(const Tp::AccountPtr &account, const QVariantMap &properties)
203+{
204+ QString roomName = properties["threadId"].toString();
205+
206+ // these properties are still not used
207+ //QString server = properties["Server"].toString();
208+ //QString creator = properties["Creator"].toString();
209+
210+ QVariantMap request;
211+ Tp::PendingChannelRequest *op = NULL;
212+ if (roomName.isEmpty()) {
213+ request.insert(TP_QT_IFACE_CHANNEL + QLatin1String(".ChannelType"), TP_QT_IFACE_CHANNEL_TYPE_TEXT);
214+ request.insert(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandleType"), (uint) Tp::HandleTypeNone);
215+ QStringList initialInviteeIDs = properties["participantIds"].toStringList();
216+ if (!initialInviteeIDs.isEmpty()) {
217+ request.insert(TP_QT_IFACE_CHANNEL_INTERFACE_CONFERENCE + QLatin1String(".InitialInviteeIDs"), initialInviteeIDs);
218+ }
219+ // the presence of RoomName indicates the returned channel must be of type Room
220+ request.insert(TP_QT_IFACE_CHANNEL_INTERFACE_ROOM + QLatin1String(".RoomName"), QString());
221+
222+ // TODO use the instance returned by createChanne() to track when the channel creation is finished
223+ op = account->createChannel(request, QDateTime::currentDateTime(), TP_QT_IFACE_CLIENT + ".TelephonyServiceHandler");
224+ } else {
225+ op = account->ensureTextChatroom(roomName, QDateTime::currentDateTime(), TP_QT_IFACE_CLIENT + ".TelephonyServiceHandler", request);
226+ }
227+
228+ if (!op) {
229+ setStatus(Failed);
230+ scheduleDeletion();
231+ return;
232+ }
233+ connect(op, &Tp::PendingOperation::finished,
234+ this, &ChatStartingJob::onChannelRequestFinished);
235+}
236+
237+Tp::TextChannelPtr ChatStartingJob::textChannel() const
238+{
239+ return mTextChannel;
240+}
241+
242+void ChatStartingJob::setTextChannel(Tp::TextChannelPtr channel)
243+{
244+ mTextChannel = channel;
245+ Q_EMIT textChannelChanged();
246+}
247+
248+void ChatStartingJob::onChannelRequestFinished(Tp::PendingOperation *op)
249+{
250+ Status status;
251+ if (op->isError()) {
252+ status = Failed;
253+ } else {
254+ Tp::PendingChannelRequest *channelRequest = qobject_cast<Tp::PendingChannelRequest*>(op);
255+ if (!channelRequest) {
256+ status = Failed;
257+ } else {
258+ setTextChannel(Tp::TextChannelPtr::dynamicCast(channelRequest->channelRequest()->channel()));
259+ status = Finished;
260+ }
261+ }
262+
263+ setStatus(status);
264+ scheduleDeletion();
265+}
266+
267
268=== added file 'handler/chatstartingjob.h'
269--- handler/chatstartingjob.h 1970-01-01 00:00:00 +0000
270+++ handler/chatstartingjob.h 2016-05-24 01:13:17 +0000
271@@ -0,0 +1,64 @@
272+/*
273+ * Copyright (C) 2016 Canonical, Ltd.
274+ *
275+ * Authors:
276+ * Tiago Salem Herrmann <tiago.herrmann@canonical.com>
277+ * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com>
278+ *
279+ * This file is part of telephony-service.
280+ *
281+ * telephony-service is free software; you can redistribute it and/or modify
282+ * it under the terms of the GNU General Public License as published by
283+ * the Free Software Foundation; version 3.
284+ *
285+ * telephony-service is distributed in the hope that it will be useful,
286+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
287+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
288+ * GNU General Public License for more details.
289+ *
290+ * You should have received a copy of the GNU General Public License
291+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
292+ */
293+
294+#ifndef CHATSTARTINGJOB_H
295+#define CHATSTARTINGJOB_H
296+
297+#include <QObject>
298+#include "messagejob.h"
299+#include <TelepathyQt/Types>
300+#include <TelepathyQt/PendingOperation>
301+
302+class TextHandler;
303+
304+class ChatStartingJob : public MessageJob
305+{
306+ Q_OBJECT
307+ Q_PROPERTY(Tp::TextChannelPtr textChannel READ textChannel NOTIFY textChannelChanged)
308+public:
309+ ChatStartingJob(TextHandler *textHandler, const QString &accountId, const QVariantMap &properties);
310+
311+ Tp::TextChannelPtr textChannel() const;
312+
313+public Q_SLOTS:
314+ virtual void startJob();
315+
316+Q_SIGNALS:
317+ void textChannelChanged();
318+
319+
320+protected Q_SLOTS:
321+ void startTextChat(const Tp::AccountPtr &account, const QVariantMap &properties);
322+ void startTextChatRoom(const Tp::AccountPtr &account, const QVariantMap &properties);
323+ void setTextChannel(Tp::TextChannelPtr channel);
324+
325+ void onChannelRequestFinished(Tp::PendingOperation *op);
326+
327+private:
328+ TextHandler *mTextHandler;
329+ QString mAccountId;
330+ QVariantMap mProperties;
331+ Tp::TextChannelPtr mTextChannel;
332+
333+};
334+
335+#endif // CHATSTARTINGJOB_H
336
337=== modified file 'handler/handlerdbus.cpp'
338--- handler/handlerdbus.cpp 2015-12-07 16:26:20 +0000
339+++ handler/handlerdbus.cpp 2016-05-24 01:13:17 +0000
340@@ -81,6 +81,26 @@
341 Q_EMIT CallIndicatorVisibleChanged(visible);
342 }
343
344+QString HandlerDBus::registerObject(QObject *object, const QString &path)
345+{
346+ QString fullPath = QString("%1/%2").arg(DBUS_OBJECT_PATH, path);
347+ if (QDBusConnection::sessionBus().registerObject(fullPath, object)) {
348+ return fullPath;
349+ }
350+ return QString::null;
351+}
352+
353+void HandlerDBus::unregisterObject(const QString &path)
354+{
355+ QDBusConnection::sessionBus().unregisterObject(path);
356+}
357+
358+HandlerDBus *HandlerDBus::instance()
359+{
360+ static HandlerDBus *self = new HandlerDBus;
361+ return self;
362+}
363+
364 bool HandlerDBus::connectToBus()
365 {
366 bool ok = QDBusConnection::sessionBus().registerService(DBUS_SERVICE);
367@@ -93,9 +113,9 @@
368 return true;
369 }
370
371-QString HandlerDBus::SendMessage(const QString &accountId, const QStringList &recipients, const QString &message, const AttachmentList &attachments, const QVariantMap &properties)
372+QString HandlerDBus::SendMessage(const QString &accountId, const QString &message, const AttachmentList &attachments, const QVariantMap &properties)
373 {
374- return TextHandler::instance()->sendMessage(accountId, recipients, message, attachments, properties);
375+ return TextHandler::instance()->sendMessage(accountId, message, attachments, properties);
376 }
377
378 void HandlerDBus::AcknowledgeMessages(const QStringList &numbers, const QStringList &messageIds, const QString &accountId)
379@@ -103,14 +123,9 @@
380 TextHandler::instance()->acknowledgeMessages(numbers, messageIds, accountId);
381 }
382
383-void HandlerDBus::StartChat(const QString &accountId, const QStringList &participants)
384-{
385- TextHandler::instance()->startChat(participants, accountId);
386-}
387-
388-void HandlerDBus::StartChatRoom(const QString &accountId, const QStringList &initialParticipants, const QVariantMap &properties)
389-{
390- TextHandler::instance()->startChatRoom(accountId, initialParticipants, properties);
391+void HandlerDBus::StartChat(const QString &accountId, const QVariantMap &properties)
392+{
393+ TextHandler::instance()->startChat(accountId, properties);
394 }
395
396 void HandlerDBus::AcknowledgeAllMessages(const QStringList &numbers, const QString &accountId)
397
398=== modified file 'handler/handlerdbus.h'
399--- handler/handlerdbus.h 2015-12-07 16:26:20 +0000
400+++ handler/handlerdbus.h 2016-05-24 01:13:17 +0000
401@@ -30,7 +30,7 @@
402 #include "dbustypes.h"
403
404 /**
405- * DBus interface for the phone approver
406+ * DBus interface for the phone handler
407 */
408 class HandlerDBus : public QObject, protected QDBusContext
409 {
410@@ -51,14 +51,18 @@
411 bool callIndicatorVisible() const;
412 void setCallIndicatorVisible(bool visible);
413
414+ QString registerObject(QObject *object, const QString &path);
415+ void unregisterObject(const QString &path);
416+
417+ static HandlerDBus *instance();
418+
419 public Q_SLOTS:
420 bool connectToBus();
421
422 // messages related
423- QString SendMessage(const QString &accountId, const QStringList &recipients, const QString &message, const AttachmentList &attachments, const QVariantMap &properties);
424+ QString SendMessage(const QString &accountId, const QString &message, const AttachmentList &attachments, const QVariantMap &properties);
425 Q_NOREPLY void AcknowledgeMessages(const QStringList &numbers, const QStringList &messageIds, const QString &accountId);
426- Q_NOREPLY void StartChat(const QString &accountId, const QStringList &participants);
427- Q_NOREPLY void StartChatRoom(const QString &accountId, const QStringList &initialParticipants, const QVariantMap &properties);
428+ Q_NOREPLY void StartChat(const QString &accountId, const QVariantMap &properties);
429 Q_NOREPLY void AcknowledgeAllMessages(const QStringList &numbers, const QString &accountId);
430
431 // call related
432
433=== modified file 'handler/main.cpp'
434--- handler/main.cpp 2016-03-18 19:02:50 +0000
435+++ handler/main.cpp 2016-05-24 01:13:17 +0000
436@@ -54,10 +54,8 @@
437 QObject::connect(handler, SIGNAL(textChannelAvailable(Tp::TextChannelPtr)),
438 TextHandler::instance(), SLOT(onTextChannelAvailable(Tp::TextChannelPtr)));
439
440- HandlerDBus dbus;
441-
442 QObject::connect(TelepathyHelper::instance(), SIGNAL(setupReady()),
443- &dbus, SLOT(connectToBus()));
444+ HandlerDBus::instance(), SLOT(connectToBus()));
445
446 return app.exec();
447 }
448
449=== added file 'handler/messagejob.cpp'
450--- handler/messagejob.cpp 1970-01-01 00:00:00 +0000
451+++ handler/messagejob.cpp 2016-05-24 01:13:17 +0000
452@@ -0,0 +1,82 @@
453+/*
454+ * Copyright (C) 2016 Canonical, Ltd.
455+ *
456+ * Authors:
457+ * Tiago Salem Herrmann <tiago.herrmann@canonical.com>
458+ * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com>
459+ *
460+ * This file is part of telephony-service.
461+ *
462+ * telephony-service is free software; you can redistribute it and/or modify
463+ * it under the terms of the GNU General Public License as published by
464+ * the Free Software Foundation; version 3.
465+ *
466+ * telephony-service is distributed in the hope that it will be useful,
467+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
468+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
469+ * GNU General Public License for more details.
470+ *
471+ * You should have received a copy of the GNU General Public License
472+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
473+ */
474+
475+#include "messagejob.h"
476+#include <QCoreApplication>
477+#include <QTime>
478+#include <QTimer>
479+
480+MessageJob::MessageJob(QObject *parent)
481+: QObject(parent), mStatus(Pending), mFinished(false)
482+{
483+}
484+
485+MessageJob::~MessageJob()
486+{
487+}
488+
489+MessageJob::Status MessageJob::status() const
490+{
491+ return mStatus;
492+}
493+
494+bool MessageJob::isFinished() const
495+{
496+ return mFinished;
497+}
498+
499+void MessageJob::waitForFinished(int timeout)
500+{
501+ QTime time;
502+ time.start();
503+ while (!mFinished && time.elapsed() < timeout) {
504+ QCoreApplication::processEvents();
505+ }
506+}
507+
508+void MessageJob::startJob()
509+{
510+ // the default implementation just sets the status to Finished
511+ setStatus(Finished);
512+}
513+
514+void MessageJob::setStatus(MessageJob::Status status)
515+{
516+ mStatus = status;
517+ Q_EMIT statusChanged();
518+
519+ // update the isFinished property too
520+ bool wasFinished = mFinished;
521+ mFinished = mStatus == Finished || mStatus == Failed;
522+ if (wasFinished != mFinished) {
523+ Q_EMIT isFinishedChanged();
524+ }
525+ if (mFinished) {
526+ Q_EMIT finished();
527+ }
528+}
529+
530+void MessageJob::scheduleDeletion(int timeout)
531+{
532+ QTimer::singleShot(timeout, this, &QObject::deleteLater);
533+}
534+
535
536=== added file 'handler/messagejob.h'
537--- handler/messagejob.h 1970-01-01 00:00:00 +0000
538+++ handler/messagejob.h 2016-05-24 01:13:17 +0000
539@@ -0,0 +1,68 @@
540+/*
541+ * Copyright (C) 2016 Canonical, Ltd.
542+ *
543+ * Authors:
544+ * Tiago Salem Herrmann <tiago.herrmann@canonical.com>
545+ * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com>
546+ *
547+ * This file is part of telephony-service.
548+ *
549+ * telephony-service is free software; you can redistribute it and/or modify
550+ * it under the terms of the GNU General Public License as published by
551+ * the Free Software Foundation; version 3.
552+ *
553+ * telephony-service is distributed in the hope that it will be useful,
554+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
555+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
556+ * GNU General Public License for more details.
557+ *
558+ * You should have received a copy of the GNU General Public License
559+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
560+ */
561+
562+#ifndef MESSAGEJOB_H
563+#define MESSAGEJOB_H
564+
565+#include <QObject>
566+
567+class MessageJob : public QObject
568+{
569+ Q_OBJECT
570+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
571+ Q_PROPERTY(bool isFinished READ isFinished NOTIFY isFinishedChanged)
572+ Q_ENUMS(Status)
573+public:
574+ enum Status {
575+ Pending,
576+ Initialising,
577+ Running,
578+ Finished,
579+ Failed
580+ };
581+
582+ explicit MessageJob(QObject *parent = 0);
583+ virtual ~MessageJob();
584+
585+ Status status() const;
586+ bool isFinished() const;
587+
588+ void waitForFinished(int timeout = 10000);
589+
590+Q_SIGNALS:
591+ void statusChanged();
592+ void isFinishedChanged();
593+ void finished();
594+
595+public Q_SLOTS:
596+ virtual void startJob();
597+
598+protected:
599+ void setStatus(Status status);
600+ void scheduleDeletion(int timeout = 60000);
601+
602+private:
603+ Status mStatus;
604+ bool mFinished;
605+};
606+
607+#endif // MESSAGEJOB_H
608
609=== added file 'handler/messagesendingjob.cpp'
610--- handler/messagesendingjob.cpp 1970-01-01 00:00:00 +0000
611+++ handler/messagesendingjob.cpp 2016-05-24 01:13:17 +0000
612@@ -0,0 +1,375 @@
613+/*
614+ * Copyright (C) 2016 Canonical, Ltd.
615+ *
616+ * Authors:
617+ * Tiago Salem Herrmann <tiago.herrmann@canonical.com>
618+ * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com>
619+ *
620+ * This file is part of telephony-service.
621+ *
622+ * telephony-service is free software; you can redistribute it and/or modify
623+ * it under the terms of the GNU General Public License as published by
624+ * the Free Software Foundation; version 3.
625+ *
626+ * telephony-service is distributed in the hope that it will be useful,
627+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
628+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
629+ * GNU General Public License for more details.
630+ *
631+ * You should have received a copy of the GNU General Public License
632+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
633+ */
634+
635+#include "accountentry.h"
636+#include "chatstartingjob.h"
637+#include "handlerdbus.h"
638+#include "messagesendingjob.h"
639+#include "telepathyhelper.h"
640+#include "texthandler.h"
641+#include <TelepathyQt/ContactManager>
642+#include <TelepathyQt/PendingContacts>
643+#include <QImage>
644+
645+#define SMIL_TEXT_REGION "<region id=\"Text\" width=\"100%\" height=\"100%\" fit=\"scroll\" />"
646+#define SMIL_IMAGE_REGION "<region id=\"Image\" width=\"100%\" height=\"100%\" fit=\"meet\" />"
647+#define SMIL_VIDEO_REGION "<region id=\"Video\" width=\"100%\" height=\"100%\" fit=\"meet\" />"
648+#define SMIL_AUDIO_REGION "<region id=\"Audio\" width=\"100%\" height=\"100%\" fit=\"meet\" />"
649+#define SMIL_TEXT_PART "<par dur=\"3s\">\
650+ <text src=\"cid:%1\" region=\"Text\" />\
651+ </par>"
652+#define SMIL_IMAGE_PART "<par dur=\"5000ms\">\
653+ <img src=\"cid:%1\" region=\"Image\" />\
654+ </par>"
655+#define SMIL_VIDEO_PART "<par>\
656+ <video src=\"cid:%1\" region=\"Video\" />\
657+ </par>"
658+#define SMIL_AUDIO_PART "<par>\
659+ <audio src=\"cid:%1\" region=\"Audio\" />\
660+ </par>"
661+
662+#define SMIL_FILE "<smil>\
663+ <head>\
664+ <layout>\
665+ %1\
666+ </layout>\
667+ </head>\
668+ <body>\
669+ %2\
670+ </body>\
671+ </smil>"
672+
673+MessageSendingJob::MessageSendingJob(TextHandler *textHandler, PendingMessage message)
674+: MessageJob(textHandler), mMessage(message), mFinished(false)
675+{
676+ static ulong count = 0;
677+ // just to avoid overflowing
678+ if (count == ULONG_MAX) {
679+ count = 0;
680+ }
681+ mObjectPath = HandlerDBus::instance()->registerObject(this, QString("messagesendingjob%1").arg(count++));
682+}
683+
684+MessageSendingJob::~MessageSendingJob()
685+{
686+ HandlerDBus::instance()->unregisterObject(mObjectPath);
687+}
688+
689+QString MessageSendingJob::accountId() const
690+{
691+ return mAccountId;
692+}
693+
694+QString MessageSendingJob::channelObjectPath() const
695+{
696+ return mChannelObjectPath;
697+}
698+
699+QString MessageSendingJob::objectPath() const
700+{
701+ return mObjectPath;
702+}
703+
704+void MessageSendingJob::startJob()
705+{
706+ qDebug() << "Getting account for id:" << mMessage.accountId;
707+ AccountEntry *account = TelepathyHelper::instance()->accountForId(mMessage.accountId);
708+ if (!account) {
709+ setStatus(Failed);
710+ scheduleDeletion();
711+ }
712+
713+ setStatus(Running);
714+
715+ // check if the message should be sent via multimedia account
716+ // we just use fallback to 1-1 chats
717+ if (account->type() == AccountEntry::PhoneAccount) {
718+ Q_FOREACH(AccountEntry *newAccount, TelepathyHelper::instance()->accounts()) {
719+ // TODO: we have to find the multimedia account that matches the same phone number,
720+ // but for now we just pick any multimedia connected account
721+ if (newAccount->type() != AccountEntry::MultimediaAccount) {
722+ continue;
723+ }
724+ // FIXME: the fallback implementation needs to be changed to use protocol info and create a map of
725+ // accounts. Also, it needs to check connection capabilities to determine if we can send message
726+ // to offline contacts.
727+ bool shouldFallback = true;
728+ // if the account is offline, dont fallback to this account
729+ if (!newAccount->connected()) {
730+ continue;
731+ }
732+ QList<Tp::TextChannelPtr> channels = mTextHandler->existingChannels(newAccount->accountId(), mMessage.properties);
733+ // check if we have a channel for this contact already and get the contact pointer from there,
734+ // this way we avoid doing the while(op->isFinished()) all the time
735+ if (!channels.isEmpty()) {
736+ // FIXME: we need to re-evaluate the rules to fallback
737+ // if the contact is known, force fallback to this account
738+ Q_FOREACH(const Tp::ContactPtr &contact, channels.first()->groupContacts(false)) {
739+ Tp::Presence presence = contact->presence();
740+ shouldFallback = (presence.type() == Tp::ConnectionPresenceTypeAvailable ||
741+ presence.type() == Tp::ConnectionPresenceTypeOffline);
742+ if (!shouldFallback) {
743+ break;
744+ }
745+ }
746+ } else {
747+ QStringList participantIds = mMessage.properties["participantIds"].toStringList();
748+ Tp::PendingContacts *op = newAccount->account()->connection()->contactManager()->contactsForIdentifiers(participantIds);
749+ while (!op->isFinished()) {
750+ qApp->processEvents();
751+ }
752+ Q_FOREACH(const Tp::ContactPtr &contact, op->contacts()) {
753+ Tp::Presence presence = contact->presence();
754+ shouldFallback = (presence.type() == Tp::ConnectionPresenceTypeAvailable ||
755+ presence.type() == Tp::ConnectionPresenceTypeOffline);
756+ if (!shouldFallback) {
757+ break;
758+ }
759+ }
760+ }
761+ if (shouldFallback) {
762+ account = newAccount;
763+ break;
764+ }
765+ }
766+ }
767+
768+ // save the account
769+ mAccount = account;
770+ setAccountId(mAccount->accountId());
771+
772+ if (!account->connected()) {
773+ connect(account, &AccountEntry::connectedChanged, [this, account]() {
774+ if (account->connected()) {
775+ findOrCreateChannel();
776+ }
777+ });
778+ return;
779+ }
780+
781+ findOrCreateChannel();
782+}
783+
784+void MessageSendingJob::findOrCreateChannel()
785+{
786+ // now that we know what account to use, find existing channels or request a new one
787+ QList<Tp::TextChannelPtr> channels = mTextHandler->existingChannels(mAccount->accountId(), mMessage.properties);
788+ if (channels.isEmpty()) {
789+ ChatStartingJob *job = new ChatStartingJob(mTextHandler, mAccount->accountId(), mMessage.properties);
790+ connect(job, &MessageJob::finished, [this, job]() {
791+ if (job->status() == MessageJob::Failed) {
792+ setStatus(Failed);
793+ scheduleDeletion();
794+ return;
795+ }
796+
797+ mTextChannel = job->textChannel();
798+ sendMessage();
799+ });
800+ job->startJob();
801+ }
802+
803+ mTextChannel = channels.last();
804+ sendMessage();
805+}
806+
807+void MessageSendingJob::sendMessage()
808+{
809+ Tp::PendingSendMessage *op = mTextChannel->send(buildMessage(mMessage));
810+ connect(op, &Tp::PendingOperation::finished, [this, op]() {
811+ if (op->isError()) {
812+ setStatus(Failed);
813+ scheduleDeletion();
814+ return;
815+ }
816+
817+ setChannelObjectPath(mTextChannel->objectPath());
818+ setStatus(Finished);
819+ scheduleDeletion();
820+ });
821+}
822+
823+void MessageSendingJob::setAccountId(const QString &accountId)
824+{
825+ mAccountId = accountId;
826+ Q_EMIT accountIdChanged();
827+}
828+
829+void MessageSendingJob::setChannelObjectPath(const QString &objectPath)
830+{
831+ mChannelObjectPath = objectPath;
832+ Q_EMIT channelObjectPathChanged();
833+}
834+
835+Tp::MessagePartList MessageSendingJob::buildMessage(const PendingMessage &pendingMessage)
836+{
837+ Tp::MessagePartList message;
838+ Tp::MessagePart header;
839+ QString smil, regions, parts;
840+ bool hasImage = false, hasText = false, hasVideo = false, hasAudio = false, isMMS = false;
841+
842+ AccountEntry *account = TelepathyHelper::instance()->accountForId(pendingMessage.accountId);
843+ if (!account) {
844+ // account does not exist
845+ return Tp::MessagePartList();
846+ }
847+
848+ bool temporaryFiles = (pendingMessage.properties.contains("x-canonical-tmp-files") &&
849+ pendingMessage.properties["x-canonical-tmp-files"].toBool());
850+
851+ // add the remaining properties to the message header
852+ QVariantMap::const_iterator it = pendingMessage.properties.begin();
853+ for (; it != pendingMessage.properties.end(); ++it) {
854+ header[it.key()] = QDBusVariant(it.value());
855+ }
856+
857+ // check if this message should be sent as an MMS
858+ if (account->type() == AccountEntry::PhoneAccount) {
859+ isMMS = (pendingMessage.attachments.size() > 0 ||
860+ (header.contains("x-canonical-mms") && header["x-canonical-mms"].variant().toBool()) ||
861+ (pendingMessage.properties["participantIds"].toStringList().size() > 1 && TelepathyHelper::instance()->mmsGroupChat()));
862+ if (isMMS) {
863+ header["x-canonical-mms"] = QDBusVariant(true);
864+ }
865+ }
866+
867+ // this flag should not be in the message header, it's only useful for the handler
868+ header.remove("x-canonical-tmp-files");
869+ header.remove("chatType");
870+ header.remove("threadId");
871+ header.remove("participantIds");
872+
873+ header["message-type"] = QDBusVariant(0);
874+ message << header;
875+
876+ // convert AttachmentList struct into telepathy Message parts
877+ Q_FOREACH(const AttachmentStruct &attachment, pendingMessage.attachments) {
878+ QByteArray fileData;
879+ QString newFilePath = QString(attachment.filePath).replace("file://", "");
880+ QFile attachmentFile(newFilePath);
881+ if (!attachmentFile.open(QIODevice::ReadOnly)) {
882+ qWarning() << "fail to load attachment" << attachmentFile.errorString() << attachment.filePath;
883+ continue;
884+ }
885+ if (attachment.contentType.startsWith("image/")) {
886+ if (isMMS) {
887+ hasImage = true;
888+ parts += QString(SMIL_IMAGE_PART).arg(attachment.id);
889+ // check if we need to reduce de image size in case it's bigger than 300k
890+ // this check is only valid for MMS
891+ if (attachmentFile.size() > 307200) {
892+ QImage scaledImage(newFilePath);
893+ if (!scaledImage.isNull()) {
894+ QBuffer buffer(&fileData);
895+ buffer.open(QIODevice::WriteOnly);
896+ scaledImage.scaled(640, 640, Qt::KeepAspectRatio, Qt::SmoothTransformation).save(&buffer, "jpg");
897+ }
898+ } else {
899+ fileData = attachmentFile.readAll();
900+ }
901+ }
902+ } else if (attachment.contentType.startsWith("video/")) {
903+ if (isMMS) {
904+ hasVideo = true;
905+ parts += QString(SMIL_VIDEO_PART).arg(attachment.id);
906+ }
907+ } else if (attachment.contentType.startsWith("audio/")) {
908+ if (isMMS) {
909+ hasAudio = true;
910+ parts += QString(SMIL_AUDIO_PART).arg(attachment.id);
911+ }
912+ } else if (attachment.contentType.startsWith("text/plain")) {
913+ if (isMMS) {
914+ hasText = true;
915+ parts += QString(SMIL_TEXT_PART).arg(attachment.id);
916+ }
917+ } else if (attachment.contentType.startsWith("text/vcard") ||
918+ attachment.contentType.startsWith("text/x-vcard")) {
919+ } else if (isMMS) {
920+ // for MMS we just support the contentTypes above
921+ if (temporaryFiles) {
922+ attachmentFile.remove();
923+ }
924+ continue;
925+ }
926+
927+ if (fileData.isEmpty()) {
928+ fileData = attachmentFile.readAll();
929+ }
930+
931+ if (temporaryFiles) {
932+ attachmentFile.remove();
933+ }
934+
935+ if (hasVideo) {
936+ regions += QString(SMIL_VIDEO_REGION);
937+ }
938+
939+ if (hasAudio) {
940+ regions += QString(SMIL_AUDIO_REGION);
941+ }
942+
943+ if (hasText) {
944+ regions += QString(SMIL_TEXT_REGION);
945+ }
946+ if (hasImage) {
947+ regions += QString(SMIL_IMAGE_REGION);
948+ }
949+
950+ Tp::MessagePart part;
951+ part["content-type"] = QDBusVariant(attachment.contentType);
952+ part["identifier"] = QDBusVariant(attachment.id);
953+ part["content"] = QDBusVariant(fileData);
954+ part["size"] = QDBusVariant(fileData.size());
955+
956+ message << part;
957+ }
958+
959+ if (!pendingMessage.message.isEmpty()) {
960+ Tp::MessagePart part;
961+ QString tmpTextId("text_0.txt");
962+ part["content-type"] = QDBusVariant(QString("text/plain"));
963+ part["identifier"] = QDBusVariant(tmpTextId);
964+ part["content"] = QDBusVariant(pendingMessage.message);
965+ part["size"] = QDBusVariant(pendingMessage.message.size());
966+ if (isMMS) {
967+ parts += QString(SMIL_TEXT_PART).arg(tmpTextId);
968+ regions += QString(SMIL_TEXT_REGION);
969+ }
970+ message << part;
971+ }
972+
973+ if (isMMS) {
974+ Tp::MessagePart smilPart;
975+ smil = QString(SMIL_FILE).arg(regions).arg(parts);
976+ smilPart["content-type"] = QDBusVariant(QString("application/smil"));
977+ smilPart["identifier"] = QDBusVariant(QString("smil.xml"));
978+ smilPart["content"] = QDBusVariant(smil);
979+ smilPart["size"] = QDBusVariant(smil.size());
980+
981+ message << smilPart;
982+ }
983+
984+ return message;
985+}
986+
987+
988
989=== added file 'handler/messagesendingjob.h'
990--- handler/messagesendingjob.h 1970-01-01 00:00:00 +0000
991+++ handler/messagesendingjob.h 2016-05-24 01:13:17 +0000
992@@ -0,0 +1,87 @@
993+/*
994+ * Copyright (C) 2016 Canonical, Ltd.
995+ *
996+ * Authors:
997+ * Tiago Salem Herrmann <tiago.herrmann@canonical.com>
998+ * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com>
999+ *
1000+ * This file is part of telephony-service.
1001+ *
1002+ * telephony-service is free software; you can redistribute it and/or modify
1003+ * it under the terms of the GNU General Public License as published by
1004+ * the Free Software Foundation; version 3.
1005+ *
1006+ * telephony-service is distributed in the hope that it will be useful,
1007+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1008+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1009+ * GNU General Public License for more details.
1010+ *
1011+ * You should have received a copy of the GNU General Public License
1012+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1013+ */
1014+
1015+#ifndef MESSAGESENDINGJOB_H
1016+#define MESSAGESENDINGJOB_H
1017+
1018+#include <QObject>
1019+#include <QDBusContext>
1020+#include <TelepathyQt/Types>
1021+#include "dbustypes.h"
1022+#include "messagejob.h"
1023+
1024+class AccountEntry;
1025+class TextHandler;
1026+
1027+struct PendingMessage {
1028+ QString accountId;
1029+ QString message;
1030+ AttachmentList attachments;
1031+ QVariantMap properties;
1032+};
1033+Q_DECLARE_METATYPE(PendingMessage)
1034+
1035+class MessageSendingJob : public MessageJob, protected QDBusContext
1036+{
1037+ Q_OBJECT
1038+ Q_PROPERTY(QString accountId READ accountId NOTIFY accountIdChanged)
1039+ Q_PROPERTY(QString channelObjectPath READ channelObjectPath NOTIFY channelObjectPathChanged)
1040+ Q_PROPERTY(QString objectPath READ objectPath CONSTANT)
1041+
1042+public:
1043+ explicit MessageSendingJob(TextHandler *textHandler, PendingMessage message);
1044+ ~MessageSendingJob();
1045+
1046+ QString accountId() const;
1047+ QString channelObjectPath() const;
1048+ QString objectPath() const;
1049+
1050+Q_SIGNALS:
1051+ void accountIdChanged();
1052+ void channelObjectPathChanged();
1053+ void messageStatusChanged();
1054+
1055+public Q_SLOTS:
1056+ void startJob();
1057+
1058+protected Q_SLOTS:
1059+ void findOrCreateChannel();
1060+ void sendMessage();
1061+
1062+ void setAccountId(const QString &accountId);
1063+ void setChannelObjectPath(const QString &objectPath);
1064+
1065+private:
1066+ TextHandler *mTextHandler;
1067+ PendingMessage mMessage;
1068+ QString mAccountId;
1069+ AccountEntry *mAccount;
1070+ QString mChannelObjectPath;
1071+ Tp::TextChannelPtr mTextChannel;
1072+ QString mObjectPath;
1073+ bool mFinished;
1074+
1075+ Tp::MessagePartList buildMessage(const PendingMessage &pendingMessage);
1076+
1077+};
1078+
1079+#endif // MESSAGESENDINGJOB_H
1080
1081=== modified file 'handler/texthandler.cpp'
1082--- handler/texthandler.cpp 2016-03-01 18:17:57 +0000
1083+++ handler/texthandler.cpp 2016-05-24 01:13:17 +0000
1084@@ -26,38 +26,12 @@
1085 #include "config.h"
1086 #include "dbustypes.h"
1087 #include "accountentry.h"
1088+#include "chatstartingjob.h"
1089
1090 #include <QImage>
1091 #include <TelepathyQt/ContactManager>
1092 #include <TelepathyQt/PendingContacts>
1093-
1094-#define SMIL_TEXT_REGION "<region id=\"Text\" width=\"100%\" height=\"100%\" fit=\"scroll\" />"
1095-#define SMIL_IMAGE_REGION "<region id=\"Image\" width=\"100%\" height=\"100%\" fit=\"meet\" />"
1096-#define SMIL_VIDEO_REGION "<region id=\"Video\" width=\"100%\" height=\"100%\" fit=\"meet\" />"
1097-#define SMIL_AUDIO_REGION "<region id=\"Audio\" width=\"100%\" height=\"100%\" fit=\"meet\" />"
1098-#define SMIL_TEXT_PART "<par dur=\"3s\">\
1099- <text src=\"cid:%1\" region=\"Text\" />\
1100- </par>"
1101-#define SMIL_IMAGE_PART "<par dur=\"5000ms\">\
1102- <img src=\"cid:%1\" region=\"Image\" />\
1103- </par>"
1104-#define SMIL_VIDEO_PART "<par>\
1105- <video src=\"cid:%1\" region=\"Video\" />\
1106- </par>"
1107-#define SMIL_AUDIO_PART "<par>\
1108- <audio src=\"cid:%1\" region=\"Audio\" />\
1109- </par>"
1110-
1111-#define SMIL_FILE "<smil>\
1112- <head>\
1113- <layout>\
1114- %1\
1115- </layout>\
1116- </head>\
1117- <body>\
1118- %2\
1119- </body>\
1120- </smil>"
1121+#include <TelepathyQt/PendingChannelRequest>
1122
1123 TextHandler::TextHandler(QObject *parent)
1124 : QObject(parent)
1125@@ -93,7 +67,7 @@
1126 }
1127 bool found = false;
1128 // avoid adding twice the same list of participants
1129- Q_FOREACH(const QStringList &recipients, recipientsList) {
1130+/* Q_FOREACH(const QStringList &recipients, recipientsList) {
1131 if (recipients == pendingMessage.recipients) {
1132 found = true;
1133 break;
1134@@ -101,10 +75,9 @@
1135 }
1136 if (!found) {
1137 recipientsList << pendingMessage.recipients;
1138- }
1139- }
1140- Q_FOREACH(const QStringList& recipients, recipientsList) {
1141- startChat(recipients, accountId);
1142+ }*/
1143+ // TODO AVOID CALLING TWICE FOR SAME CHANNEL
1144+ startChat(accountId, pendingMessage.properties);
1145 }
1146 }
1147 }
1148@@ -115,271 +88,33 @@
1149 return handler;
1150 }
1151
1152-void TextHandler::startChat(const QStringList &recipients, const QString &accountId)
1153-{
1154- // Request the contact to start chatting to
1155- // FIXME: make it possible to select which account to use, for now, pick the first one
1156- AccountEntry *account = TelepathyHelper::instance()->accountForId(accountId);
1157- if (!account->connected()) {
1158- qCritical() << "The selected account does not have a connection. AccountId:" << accountId;
1159- return;
1160- }
1161-
1162- connect(account->account()->connection()->contactManager()->contactsForIdentifiers(recipients),
1163- SIGNAL(finished(Tp::PendingOperation*)),
1164- SLOT(onContactsAvailable(Tp::PendingOperation*)));
1165-}
1166-
1167-void TextHandler::startChatRoom(const QString &accountId, const QStringList &initialParticipants, const QVariantMap &properties)
1168-{
1169- Q_UNUSED(accountId)
1170- Q_UNUSED(initialParticipants)
1171- Q_UNUSED(properties)
1172- // FIXME: implement
1173-}
1174-
1175-void TextHandler::startChat(const Tp::AccountPtr &account, const Tp::Contacts &contacts)
1176-{
1177- if (contacts.size() == 1) {
1178- account->ensureTextChat(contacts.values()[0], QDateTime::currentDateTime(), TP_QT_IFACE_CLIENT + ".TelephonyServiceHandler");
1179- } else {
1180- account->createConferenceTextChat(QList<Tp::ChannelPtr>(), contacts.toList(), QDateTime::currentDateTime(), TP_QT_IFACE_CLIENT + ".TelephonyServiceHandler");
1181- }
1182- // start chatting to the contacts
1183- Q_FOREACH(Tp::ContactPtr contact, contacts) {
1184- // hold the ContactPtr to make sure its refcounting stays bigger than 0
1185- mContacts[account->uniqueIdentifier()][contact->id()] = contact;
1186- }
1187-}
1188-
1189-Tp::MessagePartList TextHandler::buildMessage(const PendingMessage &pendingMessage)
1190-{
1191- Tp::MessagePartList message;
1192- Tp::MessagePart header;
1193- QString smil, regions, parts;
1194- bool hasImage = false, hasText = false, hasVideo = false, hasAudio = false, isMMS = false;
1195-
1196- AccountEntry *account = TelepathyHelper::instance()->accountForId(pendingMessage.accountId);
1197- if (!account) {
1198- // account does not exist
1199- return Tp::MessagePartList();
1200- }
1201-
1202- bool temporaryFiles = (pendingMessage.properties.contains("x-canonical-tmp-files") &&
1203- pendingMessage.properties["x-canonical-tmp-files"].toBool());
1204-
1205- // add the remaining properties to the message header
1206- QVariantMap::const_iterator it = pendingMessage.properties.begin();
1207- for (; it != pendingMessage.properties.end(); ++it) {
1208- header[it.key()] = QDBusVariant(it.value());
1209- }
1210-
1211- // check if this message should be sent as an MMS
1212- if (account->type() == AccountEntry::PhoneAccount) {
1213- isMMS = (pendingMessage.attachments.size() > 0 ||
1214- (header.contains("x-canonical-mms") && header["x-canonical-mms"].variant().toBool()) ||
1215- (pendingMessage.recipients.size() > 1 && TelepathyHelper::instance()->mmsGroupChat()));
1216- if (isMMS) {
1217- header["x-canonical-mms"] = QDBusVariant(true);
1218- }
1219- }
1220-
1221- // this flag should not be in the message header, it's only useful for the handler
1222- header.remove("x-canonical-tmp-files");
1223-
1224- header["message-type"] = QDBusVariant(0);
1225- message << header;
1226-
1227- // convert AttachmentList struct into telepathy Message parts
1228- Q_FOREACH(const AttachmentStruct &attachment, pendingMessage.attachments) {
1229- QByteArray fileData;
1230- QString newFilePath = QString(attachment.filePath).replace("file://", "");
1231- QFile attachmentFile(newFilePath);
1232- if (!attachmentFile.open(QIODevice::ReadOnly)) {
1233- qWarning() << "fail to load attachment" << attachmentFile.errorString() << attachment.filePath;
1234- continue;
1235- }
1236- if (attachment.contentType.startsWith("image/")) {
1237- if (isMMS) {
1238- hasImage = true;
1239- parts += QString(SMIL_IMAGE_PART).arg(attachment.id);
1240- // check if we need to reduce de image size in case it's bigger than 300k
1241- // this check is only valid for MMS
1242- if (attachmentFile.size() > 307200) {
1243- QImage scaledImage(newFilePath);
1244- if (!scaledImage.isNull()) {
1245- QBuffer buffer(&fileData);
1246- buffer.open(QIODevice::WriteOnly);
1247- scaledImage.scaled(640, 640, Qt::KeepAspectRatio, Qt::SmoothTransformation).save(&buffer, "jpg");
1248- }
1249- } else {
1250- fileData = attachmentFile.readAll();
1251- }
1252- }
1253- } else if (attachment.contentType.startsWith("video/")) {
1254- if (isMMS) {
1255- hasVideo = true;
1256- parts += QString(SMIL_VIDEO_PART).arg(attachment.id);
1257- }
1258- } else if (attachment.contentType.startsWith("audio/")) {
1259- if (isMMS) {
1260- hasAudio = true;
1261- parts += QString(SMIL_AUDIO_PART).arg(attachment.id);
1262- }
1263- } else if (attachment.contentType.startsWith("text/plain")) {
1264- if (isMMS) {
1265- hasText = true;
1266- parts += QString(SMIL_TEXT_PART).arg(attachment.id);
1267- }
1268- } else if (attachment.contentType.startsWith("text/vcard") ||
1269- attachment.contentType.startsWith("text/x-vcard")) {
1270- } else if (isMMS) {
1271- // for MMS we just support the contentTypes above
1272- if (temporaryFiles) {
1273- attachmentFile.remove();
1274- }
1275- continue;
1276- }
1277-
1278- if (fileData.isEmpty()) {
1279- fileData = attachmentFile.readAll();
1280- }
1281-
1282- if (temporaryFiles) {
1283- attachmentFile.remove();
1284- }
1285-
1286- if (hasVideo) {
1287- regions += QString(SMIL_VIDEO_REGION);
1288- }
1289-
1290- if (hasAudio) {
1291- regions += QString(SMIL_AUDIO_REGION);
1292- }
1293-
1294- if (hasText) {
1295- regions += QString(SMIL_TEXT_REGION);
1296- }
1297- if (hasImage) {
1298- regions += QString(SMIL_IMAGE_REGION);
1299- }
1300-
1301- Tp::MessagePart part;
1302- part["content-type"] = QDBusVariant(attachment.contentType);
1303- part["identifier"] = QDBusVariant(attachment.id);
1304- part["content"] = QDBusVariant(fileData);
1305- part["size"] = QDBusVariant(fileData.size());
1306-
1307- message << part;
1308- }
1309-
1310- if (!pendingMessage.message.isEmpty()) {
1311- Tp::MessagePart part;
1312- QString tmpTextId("text_0.txt");
1313- part["content-type"] = QDBusVariant(QString("text/plain"));
1314- part["identifier"] = QDBusVariant(tmpTextId);
1315- part["content"] = QDBusVariant(pendingMessage.message);
1316- part["size"] = QDBusVariant(pendingMessage.message.size());
1317- if (isMMS) {
1318- parts += QString(SMIL_TEXT_PART).arg(tmpTextId);
1319- regions += QString(SMIL_TEXT_REGION);
1320- }
1321- message << part;
1322- }
1323-
1324- if (isMMS) {
1325- Tp::MessagePart smilPart;
1326- smil = QString(SMIL_FILE).arg(regions).arg(parts);
1327- smilPart["content-type"] = QDBusVariant(QString("application/smil"));
1328- smilPart["identifier"] = QDBusVariant(QString("smil.xml"));
1329- smilPart["content"] = QDBusVariant(smil);
1330- smilPart["size"] = QDBusVariant(smil.size());
1331-
1332- message << smilPart;
1333- }
1334-
1335- return message;
1336-}
1337-
1338-QString TextHandler::sendMessage(const QString &accountId, const QStringList &recipients, const QString &message, const AttachmentList &attachments, const QVariantMap &properties)
1339-{
1340- AccountEntry *account = TelepathyHelper::instance()->accountForId(accountId);
1341- if (!account) {
1342- // account does not exist
1343- return QString();
1344- }
1345-
1346- // check if the message should be sent via multimedia account
1347- // we just use fallback to 1-1 chats
1348- if (account->type() == AccountEntry::PhoneAccount && recipients.size() == 1) {
1349- Q_FOREACH(AccountEntry *newAccount, TelepathyHelper::instance()->accounts()) {
1350- // TODO: we have to find the multimedia account that matches the same phone number,
1351- // but for now we just pick any multimedia connected account
1352- if (newAccount->type() != AccountEntry::MultimediaAccount) {
1353- continue;
1354- }
1355- // FIXME: the fallback implementation needs to be changed to use protocol info and create a map of
1356- // accounts. Also, it needs to check connection capabilities to determine if we can send message
1357- // to offline contacts.
1358- bool shouldFallback = false;
1359- // if the account is offline, dont fallback to this account
1360- if (!newAccount->connected()) {
1361- continue;
1362- }
1363- QList<Tp::TextChannelPtr> channels = existingChannels(recipients, newAccount->accountId());
1364- // check if we have a channel for this contact already and get the contact pointer from there,
1365- // this way we avoid doing the while(op->isFinished()) all the time
1366- if (!channels.isEmpty()) {
1367- // if the contact is known, force fallback to this account
1368- Tp::Presence presence = channels.first()->targetContact()->presence();
1369- shouldFallback = (presence.type() == Tp::ConnectionPresenceTypeAvailable ||
1370- presence.type() == Tp::ConnectionPresenceTypeOffline);
1371- } else {
1372- Tp::PendingOperation *op = newAccount->account()->connection()->contactManager()->contactsForIdentifiers(recipients);
1373- while (!op->isFinished()) {
1374- qApp->processEvents();
1375- }
1376- Tp::PendingContacts *pc = qobject_cast<Tp::PendingContacts*>(op);
1377- if (pc) {
1378- Tp::Presence presence = pc->contacts().first()->presence();
1379- shouldFallback = (presence.type() == Tp::ConnectionPresenceTypeAvailable ||
1380- presence.type() == Tp::ConnectionPresenceTypeOffline);
1381- }
1382- }
1383- if (shouldFallback) {
1384- account = newAccount;
1385- break;
1386- }
1387- }
1388- }
1389-
1390- // keep recipient list always sorted to be able to compare
1391- QStringList sortedRecipients = recipients;
1392- sortedRecipients.sort();
1393- PendingMessage pendingMessage = {account->accountId(), sortedRecipients, message, attachments, properties};
1394-
1395- if (!account->connected()) {
1396- mPendingMessages.append(pendingMessage);
1397- return account->accountId();
1398- }
1399-
1400- QList<Tp::TextChannelPtr> channels = existingChannels(recipients, account->accountId());
1401- if (channels.isEmpty()) {
1402- mPendingMessages.append(pendingMessage);
1403- startChat(sortedRecipients, account->accountId());
1404- return account->accountId();
1405- }
1406-
1407- connect(channels.last()->send(buildMessage(pendingMessage)),
1408- SIGNAL(finished(Tp::PendingOperation*)),
1409- SLOT(onMessageSent(Tp::PendingOperation*)));
1410-
1411- return account->accountId();
1412+void TextHandler::startChat(const QString &accountId, const QVariantMap &properties)
1413+{
1414+ ChatStartingJob *job = new ChatStartingJob(this, accountId, properties);
1415+ QTimer::singleShot(0, job, &ChatStartingJob::startJob);
1416+ // FIXME: do we care about the result?
1417+}
1418+
1419+QString TextHandler::sendMessage(const QString &accountId, const QString &message, const AttachmentList &attachments, const QVariantMap &properties)
1420+{
1421+ PendingMessage pendingMessage = {accountId, message, attachments, properties};
1422+ MessageSendingJob *job = new MessageSendingJob(this, pendingMessage);
1423+ QTimer::singleShot(0, job, &MessageSendingJob::startJob);
1424+
1425+ // FIXME: just for a first stage, we synchronously wait for the job to finish and return the accountId as usual
1426+ while (!job->isFinished()) {
1427+ QCoreApplication::processEvents();
1428+ }
1429+
1430+ return job->accountId();
1431 }
1432
1433 void TextHandler::acknowledgeMessages(const QStringList &recipients, const QStringList &messageIds, const QString &accountId)
1434 {
1435- QList<Tp::TextChannelPtr> channels = existingChannels(recipients, accountId);
1436+ QVariantMap properties;
1437+ properties["participantIds"] = recipients;
1438+
1439+ QList<Tp::TextChannelPtr> channels = existingChannels(accountId, properties);
1440 if (channels.isEmpty()) {
1441 return;
1442 }
1443@@ -397,7 +132,9 @@
1444
1445 void TextHandler::acknowledgeAllMessages(const QStringList &recipients, const QString &accountId)
1446 {
1447- QList<Tp::TextChannelPtr> channels = existingChannels(recipients, accountId);
1448+ QVariantMap properties;
1449+ properties["participantIds"] = recipients;
1450+ QList<Tp::TextChannelPtr> channels = existingChannels(accountId, properties);
1451 if (channels.isEmpty()) {
1452 return;
1453 }
1454@@ -411,14 +148,11 @@
1455 {
1456 Tp::TextChannelPtr textChannel(qobject_cast<Tp::TextChannel*>(sender()));
1457 mChannels.removeAll(textChannel);
1458- AccountEntry *account = TelepathyHelper::instance()->accountForConnection(textChannel->connection());
1459- if (account) {
1460- mContacts.remove(account->accountId());
1461- }
1462 }
1463
1464 void TextHandler::onTextChannelAvailable(Tp::TextChannelPtr channel)
1465 {
1466+ qDebug() << "TextHandler::onTextChannelAvailable" << channel;
1467 AccountEntry *account = TelepathyHelper::instance()->accountForConnection(channel->connection());
1468 if (!account) {
1469 return;
1470@@ -438,10 +172,9 @@
1471 QList<PendingMessage>::iterator it = mPendingMessages.begin();
1472 while (it != mPendingMessages.end()) {
1473 bool found = false;
1474- Q_FOREACH(const Tp::TextChannelPtr &existingChannel, existingChannels(it->recipients, it->accountId)) {
1475+ Q_FOREACH(const Tp::TextChannelPtr &existingChannel, existingChannels(it->accountId, it->properties)) {
1476 if (existingChannel == channel) {
1477- // FIXME: we can't trust recipients for group chats in regular IM accounts
1478- sendMessage(it->accountId, it->recipients, it->message, it->attachments, it->properties);
1479+ sendMessage(it->accountId, it->message, it->attachments, it->properties);
1480 it = mPendingMessages.erase(it);
1481 found = true;
1482 break;
1483@@ -453,23 +186,15 @@
1484 }
1485 }
1486
1487-void TextHandler::onMessageSent(Tp::PendingOperation *op)
1488-{
1489- Tp::PendingSendMessage *psm = qobject_cast<Tp::PendingSendMessage*>(op);
1490- if(!psm) {
1491- qWarning() << "The pending object was not a pending operation:" << op;
1492- return;
1493- }
1494-
1495- if (psm->isError()) {
1496- qWarning() << "Error sending message:" << psm->errorName() << psm->errorMessage();
1497- return;
1498- }
1499-}
1500-
1501-QList<Tp::TextChannelPtr> TextHandler::existingChannels(const QStringList &targetIds, const QString &accountId)
1502+QList<Tp::TextChannelPtr> TextHandler::existingChannels(const QString &accountId, const QVariantMap &properties)
1503 {
1504 QList<Tp::TextChannelPtr> channels;
1505+ QStringList targetIds = properties["participantIds"].toStringList();
1506+ int chatType = properties["chatType"].toUInt();
1507+ if (chatType == 0 && targetIds.size() == 1) {
1508+ chatType = 1;
1509+ }
1510+ QString roomId = properties["threadId"].toString();
1511
1512 Q_FOREACH(const Tp::TextChannelPtr &channel, mChannels) {
1513 int count = 0;
1514@@ -479,6 +204,17 @@
1515 continue;
1516 }
1517
1518+ if (chatType != channel->targetHandleType()) {
1519+ continue;
1520+ }
1521+
1522+ if (chatType == 2) {
1523+ if (!roomId.isEmpty() && channel->targetHandleType() == chatType && roomId == channel->targetId()) {
1524+ channels.append(channel);
1525+ }
1526+ continue;
1527+ }
1528+
1529 // this is a special case. We have to check if we are looking for a channel open with our self contact.
1530 bool channelToSelfContact = channel->groupContacts(true).size() == 1 && targetIds.size() == 1 &&
1531 channel->targetHandleType() == Tp::HandleTypeContact &&
1532@@ -507,17 +243,3 @@
1533 }
1534 return channels;
1535 }
1536-
1537-void TextHandler::onContactsAvailable(Tp::PendingOperation *op)
1538-{
1539- Tp::PendingContacts *pc = qobject_cast<Tp::PendingContacts*>(op);
1540-
1541- if (!pc) {
1542- qCritical() << "The pending object is not a Tp::PendingContacts";
1543- return;
1544- }
1545- AccountEntry *account = TelepathyHelper::instance()->accountForConnection(pc->manager()->connection());
1546- startChat(account->account(), pc->contacts().toSet());
1547-}
1548-
1549-
1550
1551=== modified file 'handler/texthandler.h'
1552--- handler/texthandler.h 2015-12-07 16:26:20 +0000
1553+++ handler/texthandler.h 2016-05-24 01:13:17 +0000
1554@@ -27,46 +27,35 @@
1555 #include <TelepathyQt/TextChannel>
1556 #include <TelepathyQt/ReceivedMessage>
1557 #include "dbustypes.h"
1558-
1559-struct PendingMessage {
1560- QString accountId;
1561- QStringList recipients;
1562- QString message;
1563- AttachmentList attachments;
1564- QVariantMap properties;
1565-};
1566-Q_DECLARE_METATYPE(PendingMessage)
1567+#include "messagesendingjob.h"
1568
1569 class TextHandler : public QObject
1570 {
1571 Q_OBJECT
1572 public:
1573 static TextHandler *instance();
1574- void startChat(const QStringList &recipients, const QString &accountId);
1575- void startChatRoom(const QString &accountId, const QStringList &initialParticipants, const QVariantMap &properties);
1576- void startChat(const Tp::AccountPtr &account, const Tp::Contacts &contacts);
1577+ void startChat(const QString &accountId, const QVariantMap &properties);
1578+
1579+ friend class MessageSendingJob;
1580
1581 public Q_SLOTS:
1582- QString sendMessage(const QString &accountId, const QStringList &recipients, const QString &message, const AttachmentList &attachments, const QVariantMap &properties);
1583+ QString sendMessage(const QString &accountId, const QString &message, const AttachmentList &attachments, const QVariantMap &properties);
1584 void acknowledgeMessages(const QStringList &recipients, const QStringList &messageIds, const QString &accountId);
1585 void acknowledgeAllMessages(const QStringList &recipients, const QString &accountId);
1586
1587 protected Q_SLOTS:
1588 void onTextChannelAvailable(Tp::TextChannelPtr channel);
1589 void onTextChannelInvalidated();
1590- void onContactsAvailable(Tp::PendingOperation *op);
1591- void onMessageSent(Tp::PendingOperation *op);
1592 void onConnectedChanged();
1593
1594 protected:
1595- QList<Tp::TextChannelPtr> existingChannels(const QStringList &targetIds, const QString &accountId);
1596+ QList<Tp::TextChannelPtr> existingChannels(const QString &accountId, const QVariantMap &properties);
1597
1598 private:
1599 explicit TextHandler(QObject *parent = 0);
1600- Tp::MessagePartList buildMessage(const PendingMessage &pendingMessage);
1601+
1602
1603 QList<Tp::TextChannelPtr> mChannels;
1604- QMap<QString, QMap<QString, Tp::ContactPtr> > mContacts;
1605 QList<PendingMessage> mPendingMessages;
1606 };
1607
1608
1609=== modified file 'indicator/TelephonyServiceIndicator.client'
1610--- indicator/TelephonyServiceIndicator.client 2014-11-21 13:58:47 +0000
1611+++ indicator/TelephonyServiceIndicator.client 2016-05-24 01:13:17 +0000
1612@@ -8,11 +8,6 @@
1613
1614 [org.freedesktop.Telepathy.Client.Observer.ObserverChannelFilter 1]
1615 org.freedesktop.Telepathy.Channel.ChannelType s=org.freedesktop.Telepathy.Channel.Type.Text
1616-org.freedesktop.Telepathy.Channel.TargetHandleType u=1
1617-
1618-[org.freedesktop.Telepathy.Client.Observer.ObserverChannelFilter 2]
1619-org.freedesktop.Telepathy.Channel.ChannelType s=org.freedesktop.Telepathy.Channel.Type.Text
1620-org.freedesktop.Telepathy.Channel.TargetHandleType u=0
1621
1622 [org.freedesktop.Telepathy.Client.Observer.Capabilities]
1623 org.freedesktop.Telepathy.Channel.Type.Call1/audio=true
1624
1625=== modified file 'indicator/textchannelobserver.cpp'
1626--- indicator/textchannelobserver.cpp 2016-03-30 13:34:38 +0000
1627+++ indicator/textchannelobserver.cpp 2016-05-24 01:13:17 +0000
1628@@ -277,7 +277,9 @@
1629 return;
1630 }
1631
1632- ChatManager::instance()->sendMessage(account->accountId(), recipients, text);
1633+ QVariantMap properties;
1634+ properties["participantIds"] = recipients;
1635+ ChatManager::instance()->sendMessage(account->accountId(), text, QVariantMap(), properties);
1636 }
1637
1638 void TextChannelObserver::clearNotifications()
1639@@ -341,6 +343,9 @@
1640 void TextChannelObserver::triggerNotificationForMessage(const Tp::ReceivedMessage &message, const QString &accountId, const QStringList &participantIds)
1641 {
1642 Tp::ContactPtr contact = message.sender();
1643+ if (!contact) {
1644+ return;
1645+ }
1646
1647 QByteArray token(message.messageToken().toUtf8());
1648 if (!mUnreadMessages.contains(token)) {
1649@@ -624,7 +629,7 @@
1650 // we do not notify messages sent by ourselves on other devices, unless we
1651 // are dealing with phone accounts: #1547462
1652 if (!account->account()->connection().isNull() &&
1653- message.sender()->handle().at(0) == account->account()->connection()->selfHandle() &&
1654+ message.sender() && message.sender()->handle().at(0) == account->account()->connection()->selfHandle() &&
1655 account->type() != AccountEntry::PhoneAccount) {
1656 return;
1657 }
1658
1659=== modified file 'libtelephonyservice/accountentry.cpp'
1660--- libtelephonyservice/accountentry.cpp 2015-11-23 20:01:58 +0000
1661+++ libtelephonyservice/accountentry.cpp 2016-05-24 01:13:17 +0000
1662@@ -106,6 +106,38 @@
1663 mAccount->connection()->status() == Tp::ConnectionStatusConnected;
1664 }
1665
1666+AccountEntry::Capabilities AccountEntry::capabilities() const
1667+{
1668+ AccountEntry::Capabilities capabilities = CapabilityNone;
1669+
1670+ if (!connected()) {
1671+ return capabilities;
1672+ }
1673+
1674+ Tp::ConnectionCapabilities tpCapabilities = mAccount->capabilities();
1675+
1676+ if (tpCapabilities.textChatrooms()) {
1677+ capabilities |= (AccountEntry::Capabilities)AccountEntry::CapabilityTextChatrooms;
1678+ }
1679+ if (tpCapabilities.conferenceTextChats()) {
1680+ capabilities |= (AccountEntry::Capabilities)AccountEntry::CapabilityConferenceTextChats;
1681+ }
1682+ if (tpCapabilities.conferenceTextChatsWithInvitees()) {
1683+ capabilities |= (AccountEntry::Capabilities)AccountEntry::CapabilityConferenceTextChatsWithInvitees;
1684+ }
1685+ if (tpCapabilities.conferenceTextChatrooms()) {
1686+ capabilities |= (AccountEntry::Capabilities)AccountEntry::CapabilityConferenceTextChatrooms;
1687+ }
1688+ if (tpCapabilities.conferenceTextChatroomsWithInvitees()) {
1689+ capabilities |= (AccountEntry::Capabilities)AccountEntry::CapabilityConferenceTextChatroomsWithInvitees;
1690+ }
1691+ if (tpCapabilities.contactSearches()) {
1692+ capabilities |= (AccountEntry::Capabilities)AccountEntry::CapabilityContactSearches;
1693+ }
1694+
1695+ return capabilities;
1696+}
1697+
1698 Tp::AccountPtr AccountEntry::account() const
1699 {
1700 return mAccount;
1701@@ -219,6 +251,7 @@
1702
1703 Q_EMIT connectedChanged();
1704 Q_EMIT selfContactIdChanged();
1705+ Q_EMIT capabilitiesChanged();
1706 }
1707
1708 void AccountEntry::addAccountLabel(const QString &accountId, QString &text)
1709
1710=== modified file 'libtelephonyservice/accountentry.h'
1711--- libtelephonyservice/accountentry.h 2015-11-23 20:01:58 +0000
1712+++ libtelephonyservice/accountentry.h 2016-05-24 01:13:17 +0000
1713@@ -45,6 +45,7 @@
1714 Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged)
1715 Q_PROPERTY(QStringList addressableVCardFields READ addressableVCardFields NOTIFY addressableVCardFieldsChanged)
1716 Q_PROPERTY(Protocol* protocolInfo READ protocolInfo CONSTANT)
1717+ Q_PROPERTY(Capabilities capabilities READ capabilities NOTIFY capabilitiesChanged)
1718 Q_ENUMS(AccountType)
1719 friend class AccountEntryFactory;
1720
1721@@ -55,6 +56,17 @@
1722 GenericAccount
1723 };
1724
1725+ enum Capability {
1726+ CapabilityNone = 0,
1727+ CapabilityTextChatrooms = 1,
1728+ CapabilityConferenceTextChats = 2,
1729+ CapabilityConferenceTextChatsWithInvitees = 4,
1730+ CapabilityConferenceTextChatrooms = 8,
1731+ CapabilityConferenceTextChatroomsWithInvitees = 16,
1732+ CapabilityContactSearches = 32
1733+ };
1734+ Q_DECLARE_FLAGS(Capabilities, Capability);
1735+
1736 bool ready() const;
1737 QString accountId() const;
1738 QString displayName() const;
1739@@ -68,6 +80,7 @@
1740 virtual bool compareIds(const QString &first, const QString &second) const;
1741 virtual bool active() const;
1742 virtual bool connected() const;
1743+ Capabilities capabilities() const;
1744
1745 Protocol *protocolInfo() const;
1746
1747@@ -85,6 +98,7 @@
1748 void addressableVCardFieldsChanged();
1749 void removed();
1750 void connectionStatusChanged(Tp::ConnectionStatus status);
1751+ void capabilitiesChanged();
1752
1753 protected Q_SLOTS:
1754 virtual void initialize();
1755@@ -101,4 +115,6 @@
1756 Protocol *mProtocol;
1757 };
1758
1759+Q_DECLARE_OPERATORS_FOR_FLAGS(AccountEntry::Capabilities);
1760+
1761 #endif // ACCOUNTENTRY_H
1762
1763=== modified file 'libtelephonyservice/chatentry.cpp'
1764--- libtelephonyservice/chatentry.cpp 2015-08-04 19:50:53 +0000
1765+++ libtelephonyservice/chatentry.cpp 2016-05-24 01:13:17 +0000
1766@@ -31,7 +31,10 @@
1767
1768 ChatEntry::ChatEntry(const Tp::TextChannelPtr &channel, QObject *parent) :
1769 QObject(parent),
1770- mChannel(channel)
1771+ mChannel(channel),
1772+ roomInterface(NULL),
1773+ roomConfigInterface(NULL),
1774+ subjectInterface(NULL)
1775 {
1776 qRegisterMetaType<ContactChatStates>();
1777 mAccount = TelepathyHelper::instance()->accountForConnection(mChannel->connection());
1778@@ -40,12 +43,54 @@
1779 mChatStates[contact->id()] = state;
1780 }
1781
1782+ roomInterface = channel->optionalInterface<Tp::Client::ChannelInterfaceRoomInterface>();
1783+ roomConfigInterface = channel->optionalInterface<Tp::Client::ChannelInterfaceRoomConfigInterface>();
1784+ subjectInterface = channel->optionalInterface<Tp::Client::ChannelInterfaceSubjectInterface>();
1785+
1786+ if (roomInterface) {
1787+ roomInterface->setMonitorProperties(true);
1788+ connect(roomInterface, SIGNAL(propertiesChanged(const QVariantMap &,const QStringList &)),
1789+ SLOT(onRoomPropertiesChanged(const QVariantMap &,const QStringList &)));
1790+ }
1791+ if (roomConfigInterface) {
1792+ roomConfigInterface->setMonitorProperties(true);
1793+ connect(roomConfigInterface, SIGNAL(propertiesChanged(const QVariantMap &,const QStringList &)),
1794+ SLOT(onRoomPropertiesChanged(const QVariantMap &,const QStringList &)));
1795+ }
1796+ if (subjectInterface) {
1797+ subjectInterface->setMonitorProperties(true);
1798+ connect(subjectInterface, SIGNAL(propertiesChanged(const QVariantMap &,const QStringList &)),
1799+ SLOT(onRoomPropertiesChanged(const QVariantMap &,const QStringList &)));
1800+ }
1801+
1802 connect(channel.data(), SIGNAL(chatStateChanged(const Tp::ContactPtr &, Tp::ChannelChatState)),
1803 this, SLOT(onChatStateChanged(const Tp::ContactPtr &,Tp::ChannelChatState)));
1804 connect(channel.data(), SIGNAL(groupMembersChanged(const Tp::Contacts &, const Tp::Contacts &, const Tp::Contacts &,
1805 const Tp::Contacts &, const Tp::Channel::GroupMemberChangeDetails &)), this, SIGNAL(participantsChanged()));
1806 }
1807
1808+void ChatEntry::onRoomPropertiesChanged(const QVariantMap &changed,const QStringList &invalidated)
1809+{
1810+ if (changed.contains("RoomName")) {
1811+ mRoomName = changed["RoomName"].toString();
1812+ Q_EMIT roomNameChanged();
1813+ }
1814+ if (changed.contains("Title")) {
1815+ mTitle = changed["Title"].toString();
1816+ Q_EMIT titleChanged();
1817+ }
1818+}
1819+
1820+QString ChatEntry::roomName()
1821+{
1822+ return mRoomName;
1823+}
1824+
1825+QString ChatEntry::title()
1826+{
1827+ return mTitle;
1828+}
1829+
1830 ChatEntry::~ChatEntry()
1831 {
1832 QMap<QString, ContactChatState*> tmp = mChatStates;
1833@@ -56,6 +101,24 @@
1834 it.next();
1835 delete it.value();
1836 }
1837+
1838+ if (roomInterface) {
1839+ roomInterface->deleteLater();
1840+ }
1841+ if (roomConfigInterface) {
1842+ roomConfigInterface->deleteLater();
1843+ }
1844+ if (subjectInterface) {
1845+ subjectInterface->deleteLater();
1846+ }
1847+}
1848+
1849+QString ChatEntry::chatId()
1850+{
1851+ if (mChannel) {
1852+ return mChannel->targetId();
1853+ }
1854+ return QString();
1855 }
1856
1857 void ChatEntry::onChatStateChanged(const Tp::ContactPtr &contact, Tp::ChannelChatState state)
1858
1859=== modified file 'libtelephonyservice/chatentry.h'
1860--- libtelephonyservice/chatentry.h 2015-03-20 19:00:21 +0000
1861+++ libtelephonyservice/chatentry.h 2016-05-24 01:13:17 +0000
1862@@ -55,6 +55,9 @@
1863 Q_PROPERTY(AccountEntry* account READ account CONSTANT)
1864 Q_PROPERTY(ChatType chatType READ chatType CONSTANT)
1865 Q_PROPERTY(QStringList participants READ participants NOTIFY participantsChanged)
1866+ Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged)
1867+ Q_PROPERTY(QString chatId READ chatId CONSTANT)
1868+ Q_PROPERTY(QString title READ title NOTIFY titleChanged)
1869 Q_PROPERTY(QQmlListProperty<ContactChatState> chatStates
1870 READ chatStates
1871 NOTIFY chatStatesChanged)
1872@@ -83,20 +86,31 @@
1873 QQmlListProperty<ContactChatState> chatStates();
1874 QStringList participants();
1875 ChatType chatType();
1876+ QString chatId();
1877+ QString roomName();
1878+ QString title();
1879 static int chatStatesCount(QQmlListProperty<ContactChatState> *p);
1880 static ContactChatState *chatStatesAt(QQmlListProperty<ContactChatState> *p, int index);
1881
1882 private Q_SLOTS:
1883 void onChatStateChanged(const Tp::ContactPtr &contact, Tp::ChannelChatState state);
1884+ void onRoomPropertiesChanged(const QVariantMap &changed,const QStringList &invalidated);
1885
1886 Q_SIGNALS:
1887 void chatStatesChanged();
1888 void participantsChanged();
1889+ void roomNameChanged();
1890+ void titleChanged();
1891
1892 private:
1893 AccountEntry *mAccount;
1894 Tp::TextChannelPtr mChannel;
1895 QMap<QString, ContactChatState*> mChatStates;
1896+ QString mRoomName;
1897+ QString mTitle;
1898+ Tp::Client::ChannelInterfaceRoomInterface *roomInterface;
1899+ Tp::Client::ChannelInterfaceRoomConfigInterface *roomConfigInterface;
1900+ Tp::Client::ChannelInterfaceSubjectInterface *subjectInterface;
1901 };
1902
1903 #endif // CHATENTRY_H
1904
1905=== modified file 'libtelephonyservice/chatmanager.cpp'
1906--- libtelephonyservice/chatmanager.cpp 2016-03-07 19:27:55 +0000
1907+++ libtelephonyservice/chatmanager.cpp 2016-05-24 01:13:17 +0000
1908@@ -95,7 +95,7 @@
1909 return manager;
1910 }
1911
1912-QString ChatManager::sendMessage(const QString &accountId, const QStringList &recipients, const QString &message, const QVariant &attachments, const QVariantMap &properties)
1913+QString ChatManager::sendMessage(const QString &accountId, const QString &message, const QVariant &attachments, const QVariantMap &properties)
1914 {
1915 AccountEntry *account = TelepathyHelper::instance()->accountForId(accountId);
1916
1917@@ -103,9 +103,16 @@
1918 return QString();
1919 }
1920
1921+ QVariantMap propMap = properties;
1922+
1923 // check if files should be copied to a temporary location before passing them to handler
1924 bool tmpFiles = (properties.contains("x-canonical-tmp-files") && properties["x-canonical-tmp-files"].toBool());
1925
1926+ // participants coming from qml are variants
1927+ if (properties.contains("participantIds")) {
1928+ propMap["participantIds"] = properties["participantIds"].toStringList();
1929+ }
1930+
1931 AttachmentList newAttachments;
1932 Q_FOREACH (const QVariant &attachment, attachments.toList()) {
1933 AttachmentStruct newAttachment;
1934@@ -142,7 +149,7 @@
1935 }
1936
1937 QDBusInterface *phoneAppHandler = TelepathyHelper::instance()->handlerInterface();
1938- QDBusReply<QString> reply = phoneAppHandler->call("SendMessage", account->accountId(), recipients, message, QVariant::fromValue(newAttachments), properties);
1939+ QDBusReply<QString> reply = phoneAppHandler->call("SendMessage", account->accountId(), message, QVariant::fromValue(newAttachments), propMap);
1940 if (reply.isValid()) {
1941 return reply.value();
1942 }
1943@@ -164,7 +171,7 @@
1944 connect(channel.data(),
1945 SIGNAL(messageSent(Tp::Message,Tp::MessageSendingFlags,QString)),
1946 SLOT(onMessageSent(Tp::Message,Tp::MessageSendingFlags,QString)));
1947- connect(channel.data(),
1948+ connect(channel.data(),
1949 SIGNAL(invalidated(Tp::DBusProxy*,const QString&, const QString&)),
1950 SLOT(onChannelInvalidated()));
1951
1952@@ -206,6 +213,10 @@
1953 return;
1954 }
1955
1956+ if (!message.sender()) {
1957+ return;
1958+ }
1959+
1960 Q_EMIT messageReceived(message.sender()->id(), message.text(), message.received(), message.messageToken(), true);
1961 }
1962
1963@@ -278,9 +289,41 @@
1964 return mChatEntries;
1965 }
1966
1967-ChatEntry *ChatManager::chatEntryForParticipants(const QString &accountId, const QStringList &participants, bool create)
1968+ChatEntry *ChatManager::chatEntryForProperties(const QString &accountId, const QVariantMap &properties, bool create)
1969 {
1970- if (participants.count() == 0 || accountId.isEmpty()) {
1971+ QVariantMap propMap = properties;
1972+ int chatType = 0;
1973+
1974+ QStringList participants;
1975+ // participants coming from qml are variants
1976+ if (properties.contains("participantIds")) {
1977+ participants = properties["participantIds"].toStringList();
1978+ if (!participants.isEmpty()) {
1979+ propMap["participantIds"] = participants;
1980+ }
1981+ }
1982+
1983+ if (participants.isEmpty() && propMap.contains("participants")) {
1984+ // try to generate list of participants from "participants"
1985+ Q_FOREACH(const QVariant &participantMap, propMap["participants"].toList()) {
1986+ if (participantMap.toMap().contains("identifier")) {
1987+ participants << participantMap.toMap()["identifier"].toString();
1988+ }
1989+ }
1990+ if (!participants.isEmpty()) {
1991+ propMap["participantIds"] = participants;
1992+ }
1993+ }
1994+
1995+ if (properties.contains("chatType")) {
1996+ chatType = properties["chatType"].toInt();
1997+ } else {
1998+ if (participants.length() == 1) {
1999+ chatType = 1;
2000+ }
2001+ }
2002+
2003+ if ((participants.count() == 0 && chatType == 1) || accountId.isEmpty()) {
2004 return NULL;
2005 }
2006
2007@@ -292,6 +335,15 @@
2008
2009 Q_FOREACH (ChatEntry *chatEntry, mChatEntries) {
2010 int participantCount = 0;
2011+
2012+ if (chatType == 2) {
2013+ QString roomId = propMap["threadId"].toString();
2014+ if (!roomId.isEmpty() && chatEntry->chatType() == 2 && roomId == chatEntry->chatId()) {
2015+ return chatEntry;
2016+ }
2017+ continue;
2018+ }
2019+
2020 Tp::Contacts contacts = chatEntry->channel()->groupContacts(false);
2021 if (participants.count() != contacts.count()) {
2022 continue;
2023@@ -320,19 +372,11 @@
2024
2025 if (create) {
2026 QDBusInterface *phoneAppHandler = TelepathyHelper::instance()->handlerInterface();
2027- phoneAppHandler->call("StartChat", accountId, participants);
2028+ phoneAppHandler->call("StartChat", accountId, propMap);
2029 }
2030 return NULL;
2031 }
2032
2033-ChatEntry *ChatManager::chatEntryForChatRoom(const QString &accountId, const QVariantMap &properties, bool create)
2034-{
2035- Q_UNUSED(accountId)
2036- Q_UNUSED(properties)
2037- Q_UNUSED(create)
2038- // FIXME: implement
2039-}
2040-
2041 QQmlListProperty<ChatEntry> ChatManager::chats()
2042 {
2043 return QQmlListProperty<ChatEntry>(this, 0, chatCount, chatAt);
2044
2045=== modified file 'libtelephonyservice/chatmanager.h'
2046--- libtelephonyservice/chatmanager.h 2015-12-07 16:26:20 +0000
2047+++ libtelephonyservice/chatmanager.h 2016-05-24 01:13:17 +0000
2048@@ -39,9 +39,8 @@
2049 public:
2050 static ChatManager *instance();
2051
2052- Q_INVOKABLE QString sendMessage(const QString &accountId, const QStringList &recipients, const QString &message, const QVariant &attachments = QVariant(), const QVariantMap &properties = QVariantMap());
2053- Q_INVOKABLE ChatEntry *chatEntryForParticipants(const QString &accountId, const QStringList &participants, bool create = false);
2054- Q_INVOKABLE ChatEntry *chatEntryForChatRoom(const QString &accountId, const QVariantMap &properties, bool create);
2055+ Q_INVOKABLE QString sendMessage(const QString &accountId, const QString &message, const QVariant &attachments = QVariant(), const QVariantMap &properties = QVariantMap());
2056+ Q_INVOKABLE ChatEntry *chatEntryForProperties(const QString &accountId, const QVariantMap &properties, bool create = false);
2057
2058 QQmlListProperty<ChatEntry> chats();
2059 static int chatCount(QQmlListProperty<ChatEntry> *p);
2060
2061=== modified file 'libtelephonyservice/telepathyhelper.cpp'
2062--- libtelephonyservice/telepathyhelper.cpp 2016-03-10 21:10:11 +0000
2063+++ libtelephonyservice/telepathyhelper.cpp 2016-05-24 01:13:17 +0000
2064@@ -56,6 +56,7 @@
2065 "org.freedesktop.URfkill",
2066 QDBusConnection::systemBus())
2067 {
2068+ qRegisterMetaType<QList<AccountEntry*> >();
2069 mAccountFeatures << Tp::Account::FeatureCore
2070 << Tp::Account::FeatureProtocolInfo;
2071 mContactFeatures << Tp::Contact::FeatureAlias
2072@@ -585,3 +586,14 @@
2073 connectivityIface.asyncCall("UnlockAllModems");
2074 }
2075
2076+
2077+QList<AccountEntry*> TelepathyHelper::accountsForType(int type)
2078+{
2079+ QList<AccountEntry*> accounts;
2080+ Q_FOREACH(AccountEntry *account, mAccounts) {
2081+ if (account->type() == (AccountEntry::AccountType)type) {
2082+ accounts << account;
2083+ }
2084+ }
2085+ return accounts;
2086+}
2087
2088=== modified file 'libtelephonyservice/telepathyhelper.h'
2089--- libtelephonyservice/telepathyhelper.h 2016-03-09 20:10:48 +0000
2090+++ libtelephonyservice/telepathyhelper.h 2016-05-24 01:13:17 +0000
2091@@ -31,6 +31,7 @@
2092 #include <TelepathyQt/ConnectionManager>
2093 #include <TelepathyQt/Types>
2094 #include "channelobserver.h"
2095+#include "accountentry.h"
2096
2097 #define CANONICAL_TELEPHONY_VOICEMAIL_IFACE "com.canonical.Telephony.Voicemail"
2098 #define CANONICAL_TELEPHONY_AUDIOOUTPUTS_IFACE "com.canonical.Telephony.AudioOutputs"
2099@@ -56,12 +57,19 @@
2100 Q_PROPERTY(bool emergencyCallsAvailable READ emergencyCallsAvailable NOTIFY emergencyCallsAvailableChanged)
2101 Q_PROPERTY(QVariantMap simNames READ simNames NOTIFY simNamesChanged)
2102 Q_ENUMS(AccountType)
2103+ Q_ENUMS(ChatType)
2104 public:
2105 enum AccountType {
2106 Call,
2107 Messaging
2108 };
2109
2110+ enum ChatType {
2111+ ChatTypeNone = Tp::HandleTypeNone,
2112+ ChatTypeContact = Tp::HandleTypeContact,
2113+ ChatTypeRoom = Tp::HandleTypeRoom
2114+ };
2115+
2116 ~TelepathyHelper();
2117
2118 static TelepathyHelper *instance();
2119@@ -87,6 +95,7 @@
2120 AccountEntry *accountForConnection(const Tp::ConnectionPtr &connection) const;
2121 Q_INVOKABLE AccountEntry *accountForId(const QString &accountId) const;
2122 Q_INVOKABLE void setDefaultAccount(AccountType type, AccountEntry* account);
2123+ Q_INVOKABLE QList<AccountEntry*> accountsForType(int type);
2124 bool emergencyCallsAvailable() const;
2125 Q_INVOKABLE void unlockSimCards() const;
2126 bool multiplePhoneAccounts() const;
2127
2128=== modified file 'tests/common/mock/connection.cpp'
2129--- tests/common/mock/connection.cpp 2016-03-31 19:29:44 +0000
2130+++ tests/common/mock/connection.cpp 2016-05-24 01:13:17 +0000
2131@@ -362,7 +362,9 @@
2132
2133 QStringList recipients;
2134 bool flash;
2135- if (hints.contains(TP_QT_IFACE_CHANNEL_INTERFACE_CONFERENCE + QLatin1String(".InitialInviteeHandles"))) {
2136+ if (hints.contains(TP_QT_IFACE_CHANNEL_INTERFACE_CONFERENCE + QLatin1String(".InitialInviteeIDs"))) {
2137+ recipients = qdbus_cast<QStringList>(hints[TP_QT_IFACE_CHANNEL_INTERFACE_CONFERENCE + QLatin1String(".InitialInviteeIDs")]);
2138+ } else if (hints.contains(TP_QT_IFACE_CHANNEL_INTERFACE_CONFERENCE + QLatin1String(".InitialInviteeHandles"))) {
2139 recipients << inspectHandles(Tp::HandleTypeContact, qdbus_cast<Tp::UIntList>(hints[TP_QT_IFACE_CHANNEL_INTERFACE_CONFERENCE + QLatin1String(".InitialInviteeHandles")]), error);
2140 } else {
2141 recipients << mHandles.value(targetHandle);
2142@@ -465,11 +467,15 @@
2143 const QString channelType = request.value(TP_QT_IFACE_CHANNEL + QLatin1String(".ChannelType")).toString();
2144 uint targetHandleType = request.value(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandleType")).toUInt();
2145 uint targetHandle = request.value(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetHandle")).toUInt();
2146+ QString targetId = request.value(TP_QT_IFACE_CHANNEL + QLatin1String(".TargetID")).toString();
2147 qDebug() << "MockConnection::createChannel" << targetHandle;
2148 if (mSelfPresence.type != Tp::ConnectionPresenceTypeAvailable) {
2149 error->set(TP_QT_ERROR_NETWORK_ERROR, "No network available");
2150 return Tp::BaseChannelPtr();
2151 }
2152+ if (!targetId.isEmpty()) {
2153+ targetHandle = ensureHandle(targetId);
2154+ }
2155
2156 if (channelType == TP_QT_IFACE_CHANNEL_TYPE_TEXT) {
2157 return createTextChannel(targetHandleType, targetHandle, request, error);
2158
2159=== modified file 'tests/handler/handlercontroller.cpp'
2160--- tests/handler/handlercontroller.cpp 2015-12-07 16:26:20 +0000
2161+++ tests/handler/handlercontroller.cpp 2016-05-24 01:13:17 +0000
2162@@ -75,7 +75,11 @@
2163
2164 void HandlerController::startChat(const QString &accountId, const QStringList &recipients)
2165 {
2166- mHandlerInterface.call("StartChat", accountId, recipients);
2167+ // TODO CHANGE SIGNATURE of this method
2168+ QVariantMap properties;
2169+ properties["participantIds"] = recipients;
2170+
2171+ mHandlerInterface.call("StartChat", accountId, properties);
2172 }
2173
2174 void HandlerController::startCall(const QString &number, const QString &accountId)
2175@@ -131,7 +135,10 @@
2176
2177 QString HandlerController::sendMessage(const QString &accountId, const QStringList &recipients, const QString &message, const AttachmentList &attachments, const QVariantMap &properties)
2178 {
2179- QDBusReply<QString> reply = mHandlerInterface.call("SendMessage", accountId, recipients, message, QVariant::fromValue(attachments), properties);
2180+ // TODO CHANGE SIGNATURE of this method
2181+ QVariantMap props = properties;
2182+ props["participantIds"] = recipients;
2183+ QDBusReply<QString> reply = mHandlerInterface.call("SendMessage", accountId, message, QVariant::fromValue(attachments), props);
2184 if (reply.isValid()) {
2185 return reply.value();
2186 }
2187
2188=== modified file 'tests/libtelephonyservice/ChatEntryTest.cpp'
2189--- tests/libtelephonyservice/ChatEntryTest.cpp 2015-11-17 12:41:23 +0000
2190+++ tests/libtelephonyservice/ChatEntryTest.cpp 2016-05-24 01:13:17 +0000
2191@@ -96,11 +96,13 @@
2192 MockController *mockController = accountId.startsWith("mock/mock") ? mGenericMockController : mMultimediaMockController;
2193
2194 QSignalSpy chatEntryCreatedSpy(ChatManager::instance(), SIGNAL(chatEntryCreated(QString, QStringList,ChatEntry *)));
2195- ChatEntry *entry = ChatManager::instance()->chatEntryForParticipants(accountId, participants, true);
2196+ QVariantMap properties;
2197+ properties["participantIds"] = participants;
2198+ ChatEntry *entry = ChatManager::instance()->chatEntryForProperties(accountId, properties, true);
2199 QVERIFY(entry == NULL);
2200 QTRY_COMPARE(chatEntryCreatedSpy.count(), 1);
2201
2202- entry = ChatManager::instance()->chatEntryForParticipants(accountId, participants, false);
2203+ entry = ChatManager::instance()->chatEntryForProperties(accountId, properties, false);
2204 QVERIFY(entry != NULL);
2205 QList<QVariant> arguments = chatEntryCreatedSpy.takeFirst();
2206 QCOMPARE(accountId, arguments.at(0).toString());
2207
2208=== modified file 'tests/libtelephonyservice/ChatManagerTest.cpp'
2209--- tests/libtelephonyservice/ChatManagerTest.cpp 2016-03-10 21:10:11 +0000
2210+++ tests/libtelephonyservice/ChatManagerTest.cpp 2016-05-24 01:13:17 +0000
2211@@ -104,7 +104,9 @@
2212 QSignalSpy controllerMessageSentSpy(controller, SIGNAL(MessageSent(QString,QVariantList,QVariantMap)));
2213 QSignalSpy messageSentSpy(ChatManager::instance(), SIGNAL(messageSent(QStringList,QString)));
2214
2215- ChatManager::instance()->sendMessage(accountId, recipients, message);
2216+ QVariantMap properties;
2217+ properties["participantIds"] = recipients;
2218+ ChatManager::instance()->sendMessage(accountId, message, QVariantMap(), properties);
2219
2220 TRY_COMPARE(controllerMessageSentSpy.count(), 1);
2221 QString messageText = controllerMessageSentSpy.first()[0].toString();
2222@@ -182,11 +184,14 @@
2223 QStringList recipients;
2224 recipients << "user@domain.com" << "user2@domain.com";
2225 QSignalSpy chatEntryCreatedSpy(ChatManager::instance(), SIGNAL(chatEntryCreated(QString, QStringList,ChatEntry *)));
2226- ChatEntry *entry = ChatManager::instance()->chatEntryForParticipants("mock/mock/account0", recipients, true);
2227+ QVariantMap properties;
2228+ properties["participantIds"] = recipients;
2229+
2230+ ChatEntry *entry = ChatManager::instance()->chatEntryForProperties("mock/mock/account0", properties, true);
2231 QVERIFY(entry == NULL);
2232 QTRY_COMPARE(chatEntryCreatedSpy.count(), 1);
2233
2234- entry = ChatManager::instance()->chatEntryForParticipants("mock/mock/account0", recipients, false);
2235+ entry = ChatManager::instance()->chatEntryForProperties("mock/mock/account0", properties, false);
2236 QVERIFY(entry != NULL);
2237 QList<QVariant> arguments = chatEntryCreatedSpy.takeFirst();
2238 QCOMPARE(QString("mock/mock/account0"), arguments.at(0).toString());
2239@@ -226,7 +231,9 @@
2240 attachmentList << QVariant::fromValue(attachment);
2241 QVariant attachments = QVariant::fromValue(attachmentList);
2242
2243- ChatManager::instance()->sendMessage(accountId, recipients, message, attachments);
2244+ QVariantMap properties;
2245+ properties["participantIds"] = recipients;
2246+ ChatManager::instance()->sendMessage(accountId, message, attachments, properties);
2247
2248 TRY_COMPARE(controllerMessageSentSpy.count(), 1);
2249 QString messageText = controllerMessageSentSpy.first()[0].toString();

Subscribers

People subscribed via source and target branches

to all changes: