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