Merge lp:history-service/staging into lp:history-service
- staging
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Tiago Salem Herrmann |
Approved revision: | 252 |
Merged at revision: | 233 |
Proposed branch: | lp:history-service/staging |
Merge into: | lp:history-service |
Diff against target: |
4547 lines (+2269/-272) 62 files modified
CMakeLists.txt (+1/-0) Ubuntu/History/historyeventmodel.cpp (+17/-0) Ubuntu/History/historyeventmodel.h (+2/-0) Ubuntu/History/historymodel.cpp (+144/-24) Ubuntu/History/historymodel.h (+48/-2) Ubuntu/History/historythreadmodel.cpp (+9/-1) Ubuntu/History/historythreadmodel.h (+3/-1) daemon/CMakeLists.txt (+1/-0) daemon/HistoryService.xml (+14/-0) daemon/historydaemon.cpp (+613/-55) daemon/historydaemon.h (+28/-9) daemon/historyservicedbus.cpp (+25/-17) daemon/historyservicedbus.h (+6/-1) daemon/rolesinterface.cpp (+71/-0) daemon/rolesinterface.h (+210/-0) daemon/textchannelobserver.cpp (+3/-1) daemon/textchannelobserver.h (+2/-1) plugins/sqlite/schema/v13.sql (+44/-0) plugins/sqlite/schema/v14.sql (+82/-0) plugins/sqlite/schema/v15.sql (+1/-0) plugins/sqlite/schema/v16.sql (+2/-0) plugins/sqlite/schema/v17.sql (+2/-0) plugins/sqlite/sqlitedatabase.cpp (+55/-1) plugins/sqlite/sqlitedatabase.h (+1/-0) plugins/sqlite/sqlitehistoryplugin.cpp (+478/-44) plugins/sqlite/sqlitehistoryplugin.h (+10/-1) plugins/sqlite/sqlitehistorythreadview.cpp (+0/-5) src/channelobserver.cpp (+2/-1) src/contactmatcher.cpp (+13/-3) src/contactmatcher_p.h (+2/-2) src/manager.cpp (+18/-2) src/manager.h (+7/-1) src/managerdbus.cpp (+14/-2) src/managerdbus_p.h (+7/-1) src/participant.cpp (+48/-6) src/participant.h (+7/-2) src/participant_p.h (+4/-0) src/plugin.h (+9/-1) src/plugineventview.cpp (+0/-1) src/pluginthreadview.cpp (+0/-1) src/textevent.cpp (+13/-3) src/textevent.h (+2/-0) src/textevent_p.h (+2/-0) src/thread.cpp (+48/-14) src/thread.h (+8/-2) src/thread_p.h (+8/-2) src/types.h (+67/-1) src/utils.cpp (+28/-3) src/utils_p.h (+4/-2) tests/Ubuntu.History/HistoryEventModelTest.cpp (+1/-0) tests/Ubuntu.History/HistoryGroupedThreadsModelTest.cpp (+1/-1) tests/common/mock/CMakeLists.txt (+1/-1) tests/common/mock/callchannel.cpp (+2/-1) tests/common/mock/mockconnectiondbus.cpp (+5/-6) tests/common/mock/textchannel.cpp (+6/-4) tests/common/mock/textchannel.h (+1/-1) tests/daemon/CMakeLists.txt (+4/-4) tests/daemon/DaemonTest.cpp (+2/-2) tests/libhistoryservice/ParticipantTest.cpp (+18/-4) tests/libhistoryservice/TextEventTest.cpp (+26/-17) tests/libhistoryservice/ThreadTest.cpp (+4/-2) tests/plugins/sqlite/SqlitePluginTest.cpp (+15/-16) |
To merge this branch: | bzr merge lp:history-service/staging |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Roberto Mier Escandon (community) | Approve | ||
Tiago Salem Herrmann (community) | Approve | ||
Review via email: mp+308933@code.launchpad.net |
Commit message
Improve group chat support.
Description of the change
Improve group chat support.
- 241. By Gustavo Pichorim Boiko
-
Re-enable DaemonTests.
- 242. By Gustavo Pichorim Boiko
-
Adapt the registration of objects and services to the way QtDBus works from 5.6.x on.
- 243. By Gustavo Pichorim Boiko
-
Skip self join notification in conversation when account is a ofono one
- 244. By Gustavo Pichorim Boiko
-
Fix tests on latest tp-qt.
- 245. By Gustavo Pichorim Boiko
-
Leave the mock call channel opened for a bit longer to make sure the last state change propagates correctly.
- 246. By Gustavo Pichorim Boiko
-
Allow applications to insert different kind of information events.
- 247. By Gustavo Pichorim Boiko
-
Update existing chats to Room or None based on the MMS option in Accounts Service.
- 248. By Gustavo Pichorim Boiko
-
- Create hash for threadId of broadcast messages
- Avoid grouping chats with different chatType's - 249. By Gustavo Pichorim Boiko
-
- Fix broken tests with latest changes.
- Set ChatType correctly when using createThreadForParticipants( )
Tiago Salem Herrmann (tiagosh) wrote : | # |
just two more fixes.
Gustavo Pichorim Boiko (boiko) wrote : | # |
Debug prints removed, question answered and loops changed on a separate MR.
- 250. By Gustavo Pichorim Boiko
-
Remove debug prints.
- 251. By Gustavo Pichorim Boiko
-
Use compareIds()
- 252. By Gustavo Pichorim Boiko
-
Use a more complete time format to generate the hash.
Tiago Salem Herrmann (tiagosh) wrote : | # |
Looks good to me. thank you!
- 253. By Gustavo Pichorim Boiko
-
Simplify the filtering of participants.
Preview Diff
1 | === modified file 'CMakeLists.txt' | |||
2 | --- CMakeLists.txt 2015-11-03 14:25:26 +0000 | |||
3 | +++ CMakeLists.txt 2016-11-24 12:52:24 +0000 | |||
4 | @@ -17,6 +17,7 @@ | |||
5 | 17 | find_package(Qt5Qml) | 17 | find_package(Qt5Qml) |
6 | 18 | find_package(Qt5Quick) | 18 | find_package(Qt5Quick) |
7 | 19 | find_package(Qt5Test) | 19 | find_package(Qt5Test) |
8 | 20 | find_package(Qt5Network) | ||
9 | 20 | find_package(LibPhoneNumber REQUIRED) | 21 | find_package(LibPhoneNumber REQUIRED) |
10 | 21 | 22 | ||
11 | 22 | include(qt5) | 23 | include(qt5) |
12 | 23 | 24 | ||
13 | === modified file 'Ubuntu/History/historyeventmodel.cpp' | |||
14 | --- Ubuntu/History/historyeventmodel.cpp 2015-10-06 12:59:03 +0000 | |||
15 | +++ Ubuntu/History/historyeventmodel.cpp 2016-11-24 12:52:24 +0000 | |||
16 | @@ -45,9 +45,11 @@ | |||
17 | 45 | mRoles[TextMessageAttachmentsRole] = "textMessageAttachments"; | 45 | mRoles[TextMessageAttachmentsRole] = "textMessageAttachments"; |
18 | 46 | mRoles[TextReadTimestampRole] = "textReadTimestamp"; | 46 | mRoles[TextReadTimestampRole] = "textReadTimestamp"; |
19 | 47 | mRoles[TextReadSubjectRole] = "textSubject"; | 47 | mRoles[TextReadSubjectRole] = "textSubject"; |
20 | 48 | mRoles[TextInformationTypeRole] = "textInformationType"; | ||
21 | 48 | mRoles[CallMissedRole] = "callMissed"; | 49 | mRoles[CallMissedRole] = "callMissed"; |
22 | 49 | mRoles[CallDurationRole] = "callDuration"; | 50 | mRoles[CallDurationRole] = "callDuration"; |
23 | 50 | mRoles[RemoteParticipantRole] = "remoteParticipant"; | 51 | mRoles[RemoteParticipantRole] = "remoteParticipant"; |
24 | 52 | mRoles[SubjectAsAliasRole] = "subjectAsAlias"; | ||
25 | 51 | } | 53 | } |
26 | 52 | 54 | ||
27 | 53 | int HistoryEventModel::rowCount(const QModelIndex &parent) const | 55 | int HistoryEventModel::rowCount(const QModelIndex &parent) const |
28 | @@ -135,6 +137,11 @@ | |||
29 | 135 | result = textEvent.subject(); | 137 | result = textEvent.subject(); |
30 | 136 | } | 138 | } |
31 | 137 | break; | 139 | break; |
32 | 140 | case TextInformationTypeRole: | ||
33 | 141 | if (!textEvent.isNull()) { | ||
34 | 142 | result = (int)textEvent.informationType(); | ||
35 | 143 | } | ||
36 | 144 | break; | ||
37 | 138 | case TextMessageAttachmentsRole: | 145 | case TextMessageAttachmentsRole: |
38 | 139 | if (!textEvent.isNull()) { | 146 | if (!textEvent.isNull()) { |
39 | 140 | if (mAttachmentCache.contains(textEvent)) { | 147 | if (mAttachmentCache.contains(textEvent)) { |
40 | @@ -164,6 +171,16 @@ | |||
41 | 164 | result = voiceEvent.remoteParticipant(); | 171 | result = voiceEvent.remoteParticipant(); |
42 | 165 | } | 172 | } |
43 | 166 | break; | 173 | break; |
44 | 174 | case SubjectAsAliasRole: | ||
45 | 175 | if (!textEvent.isNull()) { | ||
46 | 176 | QVariantMap contactInfo = History::ContactMatcher::instance()->contactInfo(event.accountId(), textEvent.subject()); | ||
47 | 177 | QString returnValue = contactInfo[History::FieldAlias].toString(); | ||
48 | 178 | if (returnValue.isEmpty()) { | ||
49 | 179 | returnValue = contactInfo[History::FieldIdentifier].toString(); | ||
50 | 180 | } | ||
51 | 181 | return returnValue; | ||
52 | 182 | } | ||
53 | 183 | break; | ||
54 | 167 | } | 184 | } |
55 | 168 | 185 | ||
56 | 169 | return result; | 186 | return result; |
57 | 170 | 187 | ||
58 | === modified file 'Ubuntu/History/historyeventmodel.h' | |||
59 | --- Ubuntu/History/historyeventmodel.h 2015-10-01 18:25:36 +0000 | |||
60 | +++ Ubuntu/History/historyeventmodel.h 2016-11-24 12:52:24 +0000 | |||
61 | @@ -44,10 +44,12 @@ | |||
62 | 44 | TextMessageStatusRole, | 44 | TextMessageStatusRole, |
63 | 45 | TextReadTimestampRole, | 45 | TextReadTimestampRole, |
64 | 46 | TextReadSubjectRole, | 46 | TextReadSubjectRole, |
65 | 47 | TextInformationTypeRole, | ||
66 | 47 | TextMessageAttachmentsRole, | 48 | TextMessageAttachmentsRole, |
67 | 48 | CallMissedRole, | 49 | CallMissedRole, |
68 | 49 | CallDurationRole, | 50 | CallDurationRole, |
69 | 50 | RemoteParticipantRole, | 51 | RemoteParticipantRole, |
70 | 52 | SubjectAsAliasRole, | ||
71 | 51 | LastEventRole | 53 | LastEventRole |
72 | 52 | }; | 54 | }; |
73 | 53 | 55 | ||
74 | 54 | 56 | ||
75 | === modified file 'Ubuntu/History/historymodel.cpp' | |||
76 | --- Ubuntu/History/historymodel.cpp 2015-10-08 21:52:59 +0000 | |||
77 | +++ Ubuntu/History/historymodel.cpp 2016-11-24 12:52:24 +0000 | |||
78 | @@ -1,5 +1,5 @@ | |||
79 | 1 | /* | 1 | /* |
81 | 2 | * Copyright (C) 2013-2014 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
82 | 3 | * | 3 | * |
83 | 4 | * Authors: | 4 | * Authors: |
84 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
85 | @@ -40,7 +40,10 @@ | |||
86 | 40 | mRoles[AccountIdRole] = "accountId"; | 40 | mRoles[AccountIdRole] = "accountId"; |
87 | 41 | mRoles[ThreadIdRole] = "threadId"; | 41 | mRoles[ThreadIdRole] = "threadId"; |
88 | 42 | mRoles[ParticipantsRole] = "participants"; | 42 | mRoles[ParticipantsRole] = "participants"; |
89 | 43 | mRoles[ParticipantsRemotePendingRole] = "remotePendingParticipants"; | ||
90 | 44 | mRoles[ParticipantsLocalPendingRole] = "localPendingParticipants"; | ||
91 | 43 | mRoles[TypeRole] = "type"; | 45 | mRoles[TypeRole] = "type"; |
92 | 46 | mRoles[TimestampRole] = "timestamp"; | ||
93 | 44 | mRoles[PropertiesRole] = "properties"; | 47 | mRoles[PropertiesRole] = "properties"; |
94 | 45 | 48 | ||
95 | 46 | connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SIGNAL(countChanged())); | 49 | connect(this, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SIGNAL(countChanged())); |
96 | @@ -89,16 +92,79 @@ | |||
97 | 89 | case TypeRole: | 92 | case TypeRole: |
98 | 90 | result = properties[History::FieldType]; | 93 | result = properties[History::FieldType]; |
99 | 91 | break; | 94 | break; |
110 | 92 | case ParticipantsRole: | 95 | case ParticipantsRole: { |
111 | 93 | if (mMatchContacts) { | 96 | History::Participants participants = History::Participants::fromVariantList(properties[History::FieldParticipants].toList()) |
112 | 94 | result = History::ContactMatcher::instance()->contactInfo(properties[History::FieldAccountId].toString(), | 97 | .filterByState(History::ParticipantStateRegular); |
113 | 95 | History::Participants::fromVariantList(properties[History::FieldParticipants].toList()).identifiers()); | 98 | if (mMatchContacts) { |
114 | 96 | } else { | 99 | QVariantList finalParticipantsList; |
115 | 97 | //FIXME: handle contact changes | 100 | QVariantList participantsInfo = History::ContactMatcher::instance()->contactInfo(properties[History::FieldAccountId].toString(), |
116 | 98 | result = properties[History::FieldParticipants]; | 101 | participants.identifiers()); |
117 | 99 | } | 102 | for (int i = 0; i < participantsInfo.count(); ++i) { |
118 | 100 | break; | 103 | QVariantMap newMap = participantsInfo[i].toMap(); |
119 | 101 | } | 104 | History::Participant participant = participants[i]; |
120 | 105 | newMap[History::FieldParticipantState] = participant.state(); | ||
121 | 106 | newMap[History::FieldParticipantRoles] = participant.roles(); | ||
122 | 107 | finalParticipantsList << newMap; | ||
123 | 108 | } | ||
124 | 109 | result = finalParticipantsList; | ||
125 | 110 | } else { | ||
126 | 111 | //FIXME: handle contact changes | ||
127 | 112 | result = participants.identifiers(); | ||
128 | 113 | } | ||
129 | 114 | break; | ||
130 | 115 | } | ||
131 | 116 | case ParticipantsRemotePendingRole: { | ||
132 | 117 | History::Participants participants = History::Participants::fromVariantList(properties[History::FieldParticipants].toList()) | ||
133 | 118 | .filterByState(History::ParticipantStateRemotePending); | ||
134 | 119 | if (mMatchContacts) { | ||
135 | 120 | QVariantList finalParticipantsList; | ||
136 | 121 | QVariantList participantsInfo = History::ContactMatcher::instance()->contactInfo(properties[History::FieldAccountId].toString(), | ||
137 | 122 | participants.identifiers()); | ||
138 | 123 | int count = 0; | ||
139 | 124 | Q_FOREACH(const QVariant &participantInfo, participantsInfo) { | ||
140 | 125 | QVariantMap newMap = participantInfo.toMap(); | ||
141 | 126 | newMap[History::FieldParticipantState] = participants.at(count).state(); | ||
142 | 127 | newMap[History::FieldParticipantRoles] = participants.at(count++).roles(); | ||
143 | 128 | finalParticipantsList << newMap; | ||
144 | 129 | } | ||
145 | 130 | result = finalParticipantsList; | ||
146 | 131 | } else { | ||
147 | 132 | //FIXME: handle contact changes | ||
148 | 133 | result = participants.identifiers(); | ||
149 | 134 | } | ||
150 | 135 | |||
151 | 136 | break; | ||
152 | 137 | } | ||
153 | 138 | case ParticipantsLocalPendingRole: { | ||
154 | 139 | History::Participants participants = History::Participants::fromVariantList(properties[History::FieldParticipants].toList()) | ||
155 | 140 | .filterByState(History::ParticipantStateLocalPending); | ||
156 | 141 | if (mMatchContacts) { | ||
157 | 142 | QVariantList finalParticipantsList; | ||
158 | 143 | QVariantList participantsInfo = History::ContactMatcher::instance()->contactInfo(properties[History::FieldAccountId].toString(), | ||
159 | 144 | participants.identifiers()); | ||
160 | 145 | int count = 0; | ||
161 | 146 | Q_FOREACH(const QVariant &participantInfo, participantsInfo) { | ||
162 | 147 | QVariantMap newMap = participantInfo.toMap(); | ||
163 | 148 | newMap[History::FieldParticipantState] = participants.at(count).state(); | ||
164 | 149 | newMap[History::FieldParticipantRoles] = participants.at(count++).roles(); | ||
165 | 150 | finalParticipantsList << newMap; | ||
166 | 151 | } | ||
167 | 152 | result = finalParticipantsList; | ||
168 | 153 | } else { | ||
169 | 154 | //FIXME: handle contact changes | ||
170 | 155 | result = participants.identifiers(); | ||
171 | 156 | } | ||
172 | 157 | |||
173 | 158 | break; | ||
174 | 159 | } | ||
175 | 160 | case ParticipantIdsRole: | ||
176 | 161 | result = History::Participants::fromVariantList(properties[History::FieldParticipants].toList()).identifiers(); | ||
177 | 162 | break; | ||
178 | 163 | case TimestampRole: | ||
179 | 164 | result = QDateTime::fromString(properties[History::FieldTimestamp].toString(), Qt::ISODate); | ||
180 | 165 | break; | ||
181 | 166 | } | ||
182 | 167 | |||
183 | 102 | return result; | 168 | return result; |
184 | 103 | } | 169 | } |
185 | 104 | 170 | ||
186 | @@ -187,17 +253,66 @@ | |||
187 | 187 | } | 253 | } |
188 | 188 | } | 254 | } |
189 | 189 | 255 | ||
190 | 256 | QVariantMap HistoryModel::threadForProperties(const QString &accountId, int eventType, const QVariantMap &properties, int matchFlags, bool create) | ||
191 | 257 | { | ||
192 | 258 | QVariantMap newProperties = properties; | ||
193 | 259 | if (properties.isEmpty()) { | ||
194 | 260 | return QVariantMap(); | ||
195 | 261 | } | ||
196 | 262 | |||
197 | 263 | if (newProperties.contains(History::FieldParticipantIds)) { | ||
198 | 264 | newProperties[History::FieldParticipantIds] = newProperties[History::FieldParticipantIds].toStringList(); | ||
199 | 265 | } | ||
200 | 266 | |||
201 | 267 | History::Thread thread = History::Manager::instance()->threadForProperties(accountId, | ||
202 | 268 | (History::EventType)eventType, | ||
203 | 269 | newProperties, | ||
204 | 270 | (History::MatchFlags)matchFlags, | ||
205 | 271 | create); | ||
206 | 272 | if (!thread.isNull()) { | ||
207 | 273 | return thread.properties(); | ||
208 | 274 | } | ||
209 | 275 | |||
210 | 276 | return QVariantMap(); | ||
211 | 277 | } | ||
212 | 278 | |||
213 | 279 | QString HistoryModel::threadIdForProperties(const QString &accountId, int eventType, const QVariantMap &properties, int matchFlags, bool create) | ||
214 | 280 | { | ||
215 | 281 | QVariantMap newProperties = properties; | ||
216 | 282 | if (properties.isEmpty()) { | ||
217 | 283 | return QString::null; | ||
218 | 284 | } | ||
219 | 285 | |||
220 | 286 | if (newProperties.contains(History::FieldParticipantIds)) { | ||
221 | 287 | newProperties[History::FieldParticipantIds] = newProperties[History::FieldParticipantIds].toStringList(); | ||
222 | 288 | } | ||
223 | 289 | |||
224 | 290 | History::Thread thread = History::Manager::instance()->threadForProperties(accountId, | ||
225 | 291 | (History::EventType)eventType, | ||
226 | 292 | newProperties, | ||
227 | 293 | (History::MatchFlags)matchFlags, | ||
228 | 294 | create); | ||
229 | 295 | if (!thread.isNull()) { | ||
230 | 296 | return thread.threadId(); | ||
231 | 297 | } | ||
232 | 298 | |||
233 | 299 | return QString::null; | ||
234 | 300 | } | ||
235 | 301 | |||
236 | 190 | QVariantMap HistoryModel::threadForParticipants(const QString &accountId, int eventType, const QStringList &participants, int matchFlags, bool create) | 302 | QVariantMap HistoryModel::threadForParticipants(const QString &accountId, int eventType, const QStringList &participants, int matchFlags, bool create) |
237 | 191 | { | 303 | { |
238 | 192 | if (participants.isEmpty()) { | 304 | if (participants.isEmpty()) { |
239 | 193 | return QVariantMap(); | 305 | return QVariantMap(); |
240 | 194 | } | 306 | } |
241 | 195 | 307 | ||
247 | 196 | History::Thread thread = History::Manager::instance()->threadForParticipants(accountId, | 308 | QVariantMap properties; |
248 | 197 | (History::EventType)eventType, | 309 | properties[History::FieldParticipantIds] = participants; |
249 | 198 | participants, | 310 | |
250 | 199 | (History::MatchFlags)matchFlags, | 311 | History::Thread thread = History::Manager::instance()->threadForProperties(accountId, |
251 | 200 | create); | 312 | (History::EventType)eventType, |
252 | 313 | properties, | ||
253 | 314 | (History::MatchFlags)matchFlags, | ||
254 | 315 | create); | ||
255 | 201 | if (!thread.isNull()) { | 316 | if (!thread.isNull()) { |
256 | 202 | return thread.properties(); | 317 | return thread.properties(); |
257 | 203 | } | 318 | } |
258 | @@ -211,11 +326,14 @@ | |||
259 | 211 | return QString::null; | 326 | return QString::null; |
260 | 212 | } | 327 | } |
261 | 213 | 328 | ||
267 | 214 | History::Thread thread = History::Manager::instance()->threadForParticipants(accountId, | 329 | QVariantMap properties; |
268 | 215 | (History::EventType)eventType, | 330 | properties[History::FieldParticipantIds] = participants; |
269 | 216 | participants, | 331 | |
270 | 217 | (History::MatchFlags)matchFlags, | 332 | History::Thread thread = History::Manager::instance()->threadForProperties(accountId, |
271 | 218 | create); | 333 | (History::EventType)eventType, |
272 | 334 | properties, | ||
273 | 335 | (History::MatchFlags)matchFlags, | ||
274 | 336 | create); | ||
275 | 219 | if (!thread.isNull()) { | 337 | if (!thread.isNull()) { |
276 | 220 | return thread.threadId(); | 338 | return thread.threadId(); |
277 | 221 | } | 339 | } |
278 | @@ -223,7 +341,7 @@ | |||
279 | 223 | return QString::null; | 341 | return QString::null; |
280 | 224 | } | 342 | } |
281 | 225 | 343 | ||
283 | 226 | bool HistoryModel::writeTextInformationEvent(const QString &accountId, const QString &threadId, const QStringList &participants, const QString &message) | 344 | bool HistoryModel::writeTextInformationEvent(const QString &accountId, const QString &threadId, const QStringList &participants, const QString &message, int informationType, const QString &subject) |
284 | 227 | { | 345 | { |
285 | 228 | if (participants.isEmpty() || threadId.isEmpty() || accountId.isEmpty()) { | 346 | if (participants.isEmpty() || threadId.isEmpty() || accountId.isEmpty()) { |
286 | 229 | return false; | 347 | return false; |
287 | @@ -232,7 +350,7 @@ | |||
288 | 232 | History::TextEvent historyEvent = History::TextEvent(accountId, | 350 | History::TextEvent historyEvent = History::TextEvent(accountId, |
289 | 233 | threadId, | 351 | threadId, |
290 | 234 | QString(QCryptographicHash::hash(QByteArray( | 352 | QString(QCryptographicHash::hash(QByteArray( |
292 | 235 | QDateTime::currentDateTime().toString().toLatin1()), | 353 | QDateTime::currentDateTimeUtc().toString("yyyyMMddhhmmsszzz").toLatin1()), |
293 | 236 | QCryptographicHash::Md5).toHex()), | 354 | QCryptographicHash::Md5).toHex()), |
294 | 237 | "self", | 355 | "self", |
295 | 238 | QDateTime::currentDateTime(), | 356 | QDateTime::currentDateTime(), |
296 | @@ -240,7 +358,9 @@ | |||
297 | 240 | message, | 358 | message, |
298 | 241 | History::MessageTypeInformation, | 359 | History::MessageTypeInformation, |
299 | 242 | History::MessageStatusUnknown, | 360 | History::MessageStatusUnknown, |
301 | 243 | QDateTime::currentDateTime()); | 361 | QDateTime::currentDateTime(), |
302 | 362 | subject, | ||
303 | 363 | (History::InformationType)informationType); | ||
304 | 244 | History::Events events; | 364 | History::Events events; |
305 | 245 | events << historyEvent; | 365 | events << historyEvent; |
306 | 246 | return History::Manager::instance()->writeEvents(events); | 366 | return History::Manager::instance()->writeEvents(events); |
307 | 247 | 367 | ||
308 | === modified file 'Ubuntu/History/historymodel.h' | |||
309 | --- Ubuntu/History/historymodel.h 2015-10-08 21:47:42 +0000 | |||
310 | +++ Ubuntu/History/historymodel.h 2016-11-24 12:52:24 +0000 | |||
311 | @@ -1,5 +1,5 @@ | |||
312 | 1 | /* | 1 | /* |
314 | 2 | * Copyright (C) 2013-2014 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
315 | 3 | * | 3 | * |
316 | 4 | * Authors: | 4 | * Authors: |
317 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
318 | @@ -39,14 +39,22 @@ | |||
319 | 39 | Q_PROPERTY(EventType type READ type WRITE setType NOTIFY typeChanged) | 39 | Q_PROPERTY(EventType type READ type WRITE setType NOTIFY typeChanged) |
320 | 40 | Q_PROPERTY(bool matchContacts READ matchContacts WRITE setMatchContacts NOTIFY matchContactsChanged) | 40 | Q_PROPERTY(bool matchContacts READ matchContacts WRITE setMatchContacts NOTIFY matchContactsChanged) |
321 | 41 | Q_PROPERTY(bool canFetchMore READ canFetchMore NOTIFY canFetchMoreChanged) | 41 | Q_PROPERTY(bool canFetchMore READ canFetchMore NOTIFY canFetchMoreChanged) |
322 | 42 | Q_ENUMS(ChatType) | ||
323 | 42 | Q_ENUMS(EventType) | 43 | Q_ENUMS(EventType) |
324 | 43 | Q_ENUMS(MessageType) | 44 | Q_ENUMS(MessageType) |
325 | 44 | Q_ENUMS(MatchFlag) | 45 | Q_ENUMS(MatchFlag) |
326 | 45 | Q_ENUMS(MessageStatus) | 46 | Q_ENUMS(MessageStatus) |
327 | 46 | Q_ENUMS(AttachmentFlag) | 47 | Q_ENUMS(AttachmentFlag) |
328 | 47 | Q_ENUMS(Role) | 48 | Q_ENUMS(Role) |
329 | 49 | Q_ENUMS(InformationType) | ||
330 | 48 | 50 | ||
331 | 49 | public: | 51 | public: |
332 | 52 | enum ChatType { | ||
333 | 53 | ChatTypeNone = History::ChatTypeNone, | ||
334 | 54 | ChatTypeContact = History::ChatTypeContact, | ||
335 | 55 | ChatTypeRoom = History::ChatTypeRoom | ||
336 | 56 | }; | ||
337 | 57 | |||
338 | 50 | enum EventType { | 58 | enum EventType { |
339 | 51 | EventTypeText = History::EventTypeText, | 59 | EventTypeText = History::EventTypeText, |
340 | 52 | EventTypeVoice = History::EventTypeVoice | 60 | EventTypeVoice = History::EventTypeVoice |
341 | @@ -83,12 +91,36 @@ | |||
342 | 83 | AttachmentPending = History::AttachmentPending, | 91 | AttachmentPending = History::AttachmentPending, |
343 | 84 | AttachmentError = History::AttachmentError | 92 | AttachmentError = History::AttachmentError |
344 | 85 | }; | 93 | }; |
345 | 94 | |||
346 | 95 | enum InformationType | ||
347 | 96 | { | ||
348 | 97 | InformationTypeNone = History::InformationTypeNone, | ||
349 | 98 | InformationTypeSimChange = History::InformationTypeSimChange, | ||
350 | 99 | InformationTypeText = History::InformationTypeText, | ||
351 | 100 | InformationTypeSelfJoined = History::InformationTypeSelfJoined, | ||
352 | 101 | InformationTypeJoined = History::InformationTypeJoined, | ||
353 | 102 | InformationTypeTitleChanged = History::InformationTypeTitleChanged, | ||
354 | 103 | InformationTypeInvitationSent = History::InformationTypeInvitationSent, | ||
355 | 104 | InformationTypeLeaving = History::InformationTypeLeaving, | ||
356 | 105 | InformationTypeSelfLeaving = History::InformationTypeSelfLeaving, | ||
357 | 106 | InformationTypeAdminGranted = History::InformationTypeAdminGranted, | ||
358 | 107 | InformationTypeAdminRemoved = History::InformationTypeAdminRemoved, | ||
359 | 108 | InformationTypeSelfAdminGranted = History::InformationTypeSelfAdminGranted, | ||
360 | 109 | InformationTypeSelfAdminRemoved = History::InformationTypeSelfAdminRemoved, | ||
361 | 110 | InformationTypeSelfKicked = History::InformationTypeSelfKicked, | ||
362 | 111 | InformationTypeGroupGone = History::InformationTypeGroupGone | ||
363 | 112 | }; | ||
364 | 113 | |||
365 | 86 | 114 | ||
366 | 87 | enum Role { | 115 | enum Role { |
367 | 88 | AccountIdRole = Qt::UserRole, | 116 | AccountIdRole = Qt::UserRole, |
368 | 89 | ThreadIdRole, | 117 | ThreadIdRole, |
369 | 90 | ParticipantsRole, | 118 | ParticipantsRole, |
370 | 119 | ParticipantsLocalPendingRole, | ||
371 | 120 | ParticipantsRemotePendingRole, | ||
372 | 121 | ParticipantIdsRole, | ||
373 | 91 | TypeRole, | 122 | TypeRole, |
374 | 123 | TimestampRole, | ||
375 | 92 | PropertiesRole, | 124 | PropertiesRole, |
376 | 93 | LastRole | 125 | LastRole |
377 | 94 | }; | 126 | }; |
378 | @@ -112,6 +144,18 @@ | |||
379 | 112 | bool matchContacts() const; | 144 | bool matchContacts() const; |
380 | 113 | void setMatchContacts(bool value); | 145 | void setMatchContacts(bool value); |
381 | 114 | 146 | ||
382 | 147 | Q_INVOKABLE QVariantMap threadForProperties(const QString &accountId, | ||
383 | 148 | int eventType, | ||
384 | 149 | const QVariantMap &properties, | ||
385 | 150 | int matchFlags = (int)History::MatchCaseSensitive, | ||
386 | 151 | bool create = false); | ||
387 | 152 | |||
388 | 153 | Q_INVOKABLE QString threadIdForProperties(const QString &accountId, | ||
389 | 154 | int eventType, | ||
390 | 155 | const QVariantMap &properties, | ||
391 | 156 | int matchFlags = (int)History::MatchCaseSensitive, | ||
392 | 157 | bool create = false); | ||
393 | 158 | |||
394 | 115 | Q_INVOKABLE QVariantMap threadForParticipants(const QString &accountId, | 159 | Q_INVOKABLE QVariantMap threadForParticipants(const QString &accountId, |
395 | 116 | int eventType, | 160 | int eventType, |
396 | 117 | const QStringList &participants, | 161 | const QStringList &participants, |
397 | @@ -125,7 +169,9 @@ | |||
398 | 125 | Q_INVOKABLE bool writeTextInformationEvent(const QString &accountId, | 169 | Q_INVOKABLE bool writeTextInformationEvent(const QString &accountId, |
399 | 126 | const QString &threadId, | 170 | const QString &threadId, |
400 | 127 | const QStringList &participants, | 171 | const QStringList &participants, |
402 | 128 | const QString &message); | 172 | const QString &message, |
403 | 173 | int informationType = (int)History::InformationTypeNone, | ||
404 | 174 | const QString &subject = QString()); | ||
405 | 129 | 175 | ||
406 | 130 | Q_INVOKABLE virtual QVariant get(int row) const; | 176 | Q_INVOKABLE virtual QVariant get(int row) const; |
407 | 131 | 177 | ||
408 | 132 | 178 | ||
409 | === modified file 'Ubuntu/History/historythreadmodel.cpp' | |||
410 | --- Ubuntu/History/historythreadmodel.cpp 2015-10-08 19:35:40 +0000 | |||
411 | +++ Ubuntu/History/historythreadmodel.cpp 2016-11-24 12:52:24 +0000 | |||
412 | @@ -1,5 +1,5 @@ | |||
413 | 1 | /* | 1 | /* |
415 | 2 | * Copyright (C) 2013-2015 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
416 | 3 | * | 3 | * |
417 | 4 | * Authors: | 4 | * Authors: |
418 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
419 | @@ -38,6 +38,8 @@ | |||
420 | 38 | mRoles = HistoryModel::roleNames(); | 38 | mRoles = HistoryModel::roleNames(); |
421 | 39 | mRoles[CountRole] = "count"; | 39 | mRoles[CountRole] = "count"; |
422 | 40 | mRoles[UnreadCountRole] = "unreadCount"; | 40 | mRoles[UnreadCountRole] = "unreadCount"; |
423 | 41 | mRoles[ChatType] = "chatType"; | ||
424 | 42 | mRoles[ChatRoomInfo] = "chatRoomInfo"; | ||
425 | 41 | 43 | ||
426 | 42 | // roles related to the thread´s last event | 44 | // roles related to the thread´s last event |
427 | 43 | mRoles[LastEventIdRole] = "eventId"; | 45 | mRoles[LastEventIdRole] = "eventId"; |
428 | @@ -104,6 +106,12 @@ | |||
429 | 104 | case UnreadCountRole: | 106 | case UnreadCountRole: |
430 | 105 | result = thread.unreadCount(); | 107 | result = thread.unreadCount(); |
431 | 106 | break; | 108 | break; |
432 | 109 | case ChatType: | ||
433 | 110 | result = thread.chatType(); | ||
434 | 111 | break; | ||
435 | 112 | case ChatRoomInfo: | ||
436 | 113 | result = thread.chatRoomInfo(); | ||
437 | 114 | break; | ||
438 | 107 | case PropertiesRole: | 115 | case PropertiesRole: |
439 | 108 | result = thread.properties(); | 116 | result = thread.properties(); |
440 | 109 | break; | 117 | break; |
441 | 110 | 118 | ||
442 | === modified file 'Ubuntu/History/historythreadmodel.h' | |||
443 | --- Ubuntu/History/historythreadmodel.h 2015-09-29 14:28:17 +0000 | |||
444 | +++ Ubuntu/History/historythreadmodel.h 2016-11-24 12:52:24 +0000 | |||
445 | @@ -1,5 +1,5 @@ | |||
446 | 1 | /* | 1 | /* |
448 | 2 | * Copyright (C) 2013-2015 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
449 | 3 | * | 3 | * |
450 | 4 | * Authors: | 4 | * Authors: |
451 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
452 | @@ -40,6 +40,8 @@ | |||
453 | 40 | enum ThreadRole { | 40 | enum ThreadRole { |
454 | 41 | CountRole = HistoryModel::LastRole, | 41 | CountRole = HistoryModel::LastRole, |
455 | 42 | UnreadCountRole, | 42 | UnreadCountRole, |
456 | 43 | ChatType, | ||
457 | 44 | ChatRoomInfo, | ||
458 | 43 | LastEventIdRole, | 45 | LastEventIdRole, |
459 | 44 | LastEventSenderIdRole, | 46 | LastEventSenderIdRole, |
460 | 45 | LastEventTimestampRole, | 47 | LastEventTimestampRole, |
461 | 46 | 48 | ||
462 | === modified file 'daemon/CMakeLists.txt' | |||
463 | --- daemon/CMakeLists.txt 2015-09-30 13:17:52 +0000 | |||
464 | +++ daemon/CMakeLists.txt 2016-11-24 12:52:24 +0000 | |||
465 | @@ -4,6 +4,7 @@ | |||
466 | 4 | historydaemon.cpp | 4 | historydaemon.cpp |
467 | 5 | historyservicedbus.cpp | 5 | historyservicedbus.cpp |
468 | 6 | pluginmanager.cpp | 6 | pluginmanager.cpp |
469 | 7 | rolesinterface.cpp | ||
470 | 7 | textchannelobserver.cpp | 8 | textchannelobserver.cpp |
471 | 8 | ) | 9 | ) |
472 | 9 | 10 | ||
473 | 10 | 11 | ||
474 | === modified file 'daemon/HistoryService.xml' | |||
475 | --- daemon/HistoryService.xml 2015-09-23 15:08:07 +0000 | |||
476 | +++ daemon/HistoryService.xml 2016-11-24 12:52:24 +0000 | |||
477 | @@ -9,6 +9,20 @@ | |||
478 | 9 | <dox:d> | 9 | <dox:d> |
479 | 10 | An interface to the history service | 10 | An interface to the history service |
480 | 11 | </dox:d> | 11 | </dox:d> |
481 | 12 | <method name="ThreadForProperties"> | ||
482 | 13 | <dox:d><![CDATA[ | ||
483 | 14 | Return an existing thread for the given parameters. | ||
484 | 15 | ]]></dox:d> | ||
485 | 16 | <arg name="accountId" type="s" direction="in"/> | ||
486 | 17 | <arg name="type" type="i" direction="in"/> | ||
487 | 18 | <arg name="properties" type="a{sv}" direction="in"/> | ||
488 | 19 | <arg name="matchFlags" type="i" direction="in"/> | ||
489 | 20 | <arg name="create" type="b" direction="in"/> | ||
490 | 21 | <arg type="a{sv}" direction="out"/> | ||
491 | 22 | <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/> | ||
492 | 23 | <annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="QVariantMap"/> | ||
493 | 24 | </method> | ||
494 | 25 | |||
495 | 12 | <method name="ThreadForParticipants"> | 26 | <method name="ThreadForParticipants"> |
496 | 13 | <dox:d><![CDATA[ | 27 | <dox:d><![CDATA[ |
497 | 14 | Return an existing thread for the given parameters. | 28 | Return an existing thread for the given parameters. |
498 | 15 | 29 | ||
499 | === modified file 'daemon/historydaemon.cpp' | |||
500 | --- daemon/historydaemon.cpp 2015-11-20 12:53:49 +0000 | |||
501 | +++ daemon/historydaemon.cpp 2016-11-24 12:52:24 +0000 | |||
502 | @@ -1,5 +1,5 @@ | |||
503 | 1 | /* | 1 | /* |
505 | 2 | * Copyright (C) 2013-2015 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
506 | 3 | * | 3 | * |
507 | 4 | * Authors: | 4 | * Authors: |
508 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
509 | @@ -23,20 +23,97 @@ | |||
510 | 23 | #include "telepathyhelper_p.h" | 23 | #include "telepathyhelper_p.h" |
511 | 24 | #include "filter.h" | 24 | #include "filter.h" |
512 | 25 | #include "sort.h" | 25 | #include "sort.h" |
513 | 26 | #include "utils_p.h" | ||
514 | 26 | 27 | ||
515 | 27 | #include "pluginmanager.h" | 28 | #include "pluginmanager.h" |
516 | 28 | #include "plugin.h" | 29 | #include "plugin.h" |
517 | 29 | #include "pluginthreadview.h" | 30 | #include "pluginthreadview.h" |
518 | 30 | #include "plugineventview.h" | 31 | #include "plugineventview.h" |
519 | 32 | #include "textevent.h" | ||
520 | 31 | 33 | ||
521 | 32 | #include <QStandardPaths> | 34 | #include <QStandardPaths> |
522 | 33 | #include <QCryptographicHash> | 35 | #include <QCryptographicHash> |
523 | 34 | #include <TelepathyQt/CallChannel> | 36 | #include <TelepathyQt/CallChannel> |
524 | 37 | #include <TelepathyQt/PendingVariantMap> | ||
525 | 35 | #include <TelepathyQt/ReferencedHandles> | 38 | #include <TelepathyQt/ReferencedHandles> |
526 | 36 | 39 | ||
527 | 40 | #include <TelepathyQt/PendingVariant> | ||
528 | 41 | #include <TelepathyQt/PendingOperation> | ||
529 | 42 | |||
530 | 43 | Q_DECLARE_METATYPE(RolesMap) | ||
531 | 44 | |||
532 | 45 | const constexpr static int AdminRole = 2; | ||
533 | 46 | |||
534 | 47 | enum ChannelGroupChangeReason | ||
535 | 48 | { | ||
536 | 49 | ChannelGroupChangeReasonNone = 0, | ||
537 | 50 | ChannelGroupChangeReasonOffline = 1, | ||
538 | 51 | ChannelGroupChangeReasonKicked = 2, | ||
539 | 52 | ChannelGroupChangeReasonBusy = 3, | ||
540 | 53 | ChannelGroupChangeReasonInvited = 4, | ||
541 | 54 | ChannelGroupChangeReasonBanned = 5, | ||
542 | 55 | ChannelGroupChangeReasonError = 6, | ||
543 | 56 | ChannelGroupChangeReasonInvalidContact = 7, | ||
544 | 57 | ChannelGroupChangeReasonNoAnswer = 8, | ||
545 | 58 | ChannelGroupChangeReasonRenamed = 9, | ||
546 | 59 | ChannelGroupChangeReasonPermissionDenied = 10, | ||
547 | 60 | ChannelGroupChangeReasonSeparated = 11, | ||
548 | 61 | |||
549 | 62 | // additional enum values not included in original ChannelGroupChangeReason | ||
550 | 63 | // telepathy enumeration but needed here to provide extra info to client when group | ||
551 | 64 | // is cancelled | ||
552 | 65 | ChannelGroupChangeReasonGone = 12, | ||
553 | 66 | ChannelGroupChangeReasonRejected = 13 | ||
554 | 67 | }; | ||
555 | 68 | |||
556 | 69 | const QDBusArgument &operator>>(const QDBusArgument &argument, RolesMap &roles) | ||
557 | 70 | { | ||
558 | 71 | argument.beginMap(); | ||
559 | 72 | while ( !argument.atEnd() ) { | ||
560 | 73 | argument.beginMapEntry(); | ||
561 | 74 | uint key,value; | ||
562 | 75 | argument >> key >> value; | ||
563 | 76 | argument.endMapEntry(); | ||
564 | 77 | roles[key] = value; | ||
565 | 78 | } | ||
566 | 79 | |||
567 | 80 | argument.endMap(); | ||
568 | 81 | return argument; | ||
569 | 82 | } | ||
570 | 83 | |||
571 | 84 | bool foundAsMemberInThread(const Tp::ContactPtr& contact, QVariantMap thread) | ||
572 | 85 | { | ||
573 | 86 | Q_FOREACH (QVariant participant, thread[History::FieldParticipants].toList()) { | ||
574 | 87 | // found if same identifier and as member into thread info | ||
575 | 88 | if (History::Utils::compareIds(thread[History::FieldAccountId].toString(), | ||
576 | 89 | contact->id(), | ||
577 | 90 | participant.toMap()[History::FieldIdentifier].toString()) && | ||
578 | 91 | participant.toMap()[History::FieldParticipantState].toUInt() == History::ParticipantStateRegular) | ||
579 | 92 | { | ||
580 | 93 | return true; | ||
581 | 94 | } | ||
582 | 95 | } | ||
583 | 96 | return false; | ||
584 | 97 | } | ||
585 | 98 | |||
586 | 99 | bool foundInThread(const Tp::ContactPtr& contact, QVariantMap thread) | ||
587 | 100 | { | ||
588 | 101 | Q_FOREACH (QVariant participant, thread[History::FieldParticipants].toList()) { | ||
589 | 102 | if (History::Utils::compareIds(thread[History::FieldAccountId].toString(), | ||
590 | 103 | contact->id(), | ||
591 | 104 | participant.toMap()[History::FieldIdentifier].toString())) | ||
592 | 105 | { | ||
593 | 106 | return true; | ||
594 | 107 | } | ||
595 | 108 | } | ||
596 | 109 | return false; | ||
597 | 110 | } | ||
598 | 111 | |||
599 | 37 | HistoryDaemon::HistoryDaemon(QObject *parent) | 112 | HistoryDaemon::HistoryDaemon(QObject *parent) |
600 | 38 | : QObject(parent), mCallObserver(this), mTextObserver(this) | 113 | : QObject(parent), mCallObserver(this), mTextObserver(this) |
601 | 39 | { | 114 | { |
602 | 115 | qRegisterMetaType<HandleRolesMap>(); | ||
603 | 116 | qDBusRegisterMetaType<HandleRolesMap>(); | ||
604 | 40 | // get the first plugin | 117 | // get the first plugin |
605 | 41 | if (!History::PluginManager::instance()->plugins().isEmpty()) { | 118 | if (!History::PluginManager::instance()->plugins().isEmpty()) { |
606 | 42 | mBackend = History::PluginManager::instance()->plugins().first(); | 119 | mBackend = History::PluginManager::instance()->plugins().first(); |
607 | @@ -65,6 +142,9 @@ | |||
608 | 65 | connect(&mTextObserver, | 142 | connect(&mTextObserver, |
609 | 66 | SIGNAL(messageRead(Tp::TextChannelPtr,Tp::ReceivedMessage)), | 143 | SIGNAL(messageRead(Tp::TextChannelPtr,Tp::ReceivedMessage)), |
610 | 67 | SLOT(onMessageRead(Tp::TextChannelPtr,Tp::ReceivedMessage))); | 144 | SLOT(onMessageRead(Tp::TextChannelPtr,Tp::ReceivedMessage))); |
611 | 145 | connect(&mTextObserver, | ||
612 | 146 | SIGNAL(channelAvailable(Tp::TextChannelPtr)), | ||
613 | 147 | SLOT(onTextChannelAvailable(Tp::TextChannelPtr))); | ||
614 | 68 | 148 | ||
615 | 69 | // FIXME: we need to do this in a better way, but for now this should do | 149 | // FIXME: we need to do this in a better way, but for now this should do |
616 | 70 | mProtocolFlags["ofono"] = History::MatchPhoneNumber; | 150 | mProtocolFlags["ofono"] = History::MatchPhoneNumber; |
617 | @@ -81,37 +161,153 @@ | |||
618 | 81 | return self; | 161 | return self; |
619 | 82 | } | 162 | } |
620 | 83 | 163 | ||
624 | 84 | QStringList HistoryDaemon::participantsFromChannel(const Tp::TextChannelPtr &textChannel) | 164 | void HistoryDaemon::onRolesChanged(const HandleRolesMap &added, const HandleRolesMap &removed) |
625 | 85 | { | 165 | { |
626 | 86 | QStringList participants; | 166 | Q_UNUSED(added); |
627 | 167 | Q_UNUSED(removed); | ||
628 | 168 | |||
629 | 169 | ChannelInterfaceRolesInterface *roles_interface = qobject_cast<ChannelInterfaceRolesInterface*>(sender()); | ||
630 | 170 | RolesMap roles = roles_interface->getRoles(); | ||
631 | 171 | |||
632 | 172 | Tp::TextChannelPtr channel(qobject_cast<Tp::TextChannel*>(sender()->parent())); | ||
633 | 173 | QVariantMap properties = propertiesFromChannel(channel); | ||
634 | 174 | QVariantMap thread = threadForProperties(channel->property(History::FieldAccountId).toString(), | ||
635 | 175 | History::EventTypeText, | ||
636 | 176 | properties, | ||
637 | 177 | matchFlagsForChannel(channel), | ||
638 | 178 | false); | ||
639 | 179 | |||
640 | 180 | writeRolesInformationEvents(thread, channel, roles); | ||
641 | 181 | |||
642 | 182 | updateRoomRoles(channel, roles); | ||
643 | 183 | } | ||
644 | 184 | |||
645 | 185 | QVariantMap HistoryDaemon::propertiesFromChannel(const Tp::ChannelPtr &textChannel) | ||
646 | 186 | { | ||
647 | 187 | QVariantMap properties; | ||
648 | 188 | QVariantList participants; | ||
649 | 189 | QStringList participantIds; | ||
650 | 190 | |||
651 | 191 | ChannelInterfaceRolesInterface *roles_interface = textChannel->optionalInterface<ChannelInterfaceRolesInterface>(); | ||
652 | 192 | RolesMap roles; | ||
653 | 193 | if (roles_interface) { | ||
654 | 194 | roles = roles_interface->getRoles(); | ||
655 | 195 | } | ||
656 | 196 | |||
657 | 87 | Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupContacts(false)) { | 197 | Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupContacts(false)) { |
659 | 88 | participants << contact->id(); | 198 | QVariantMap contactProperties; |
660 | 199 | contactProperties[History::FieldAlias] = contact->alias(); | ||
661 | 200 | contactProperties[History::FieldAccountId] = textChannel->property(History::FieldAccountId).toString(); | ||
662 | 201 | contactProperties[History::FieldIdentifier] = contact->id(); | ||
663 | 202 | contactProperties[History::FieldParticipantState] = History::ParticipantStateRegular; | ||
664 | 203 | contactProperties[History::FieldParticipantRoles] = roles[contact->handle().at(0)]; | ||
665 | 204 | participantIds << contact->id(); | ||
666 | 205 | participants << contactProperties; | ||
667 | 206 | } | ||
668 | 207 | |||
669 | 208 | Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupRemotePendingContacts(false)) { | ||
670 | 209 | QVariantMap contactProperties; | ||
671 | 210 | contactProperties[History::FieldAlias] = contact->alias(); | ||
672 | 211 | contactProperties[History::FieldAccountId] = textChannel->property(History::FieldAccountId).toString(); | ||
673 | 212 | contactProperties[History::FieldIdentifier] = contact->id(); | ||
674 | 213 | contactProperties[History::FieldParticipantState] = History::ParticipantStateRemotePending; | ||
675 | 214 | contactProperties[History::FieldParticipantRoles] = roles[contact->handle().at(0)]; | ||
676 | 215 | participantIds << contact->id(); | ||
677 | 216 | participants << contactProperties; | ||
678 | 217 | } | ||
679 | 218 | |||
680 | 219 | Q_FOREACH(const Tp::ContactPtr contact, textChannel->groupLocalPendingContacts(false)) { | ||
681 | 220 | QVariantMap contactProperties; | ||
682 | 221 | contactProperties[History::FieldAlias] = contact->alias(); | ||
683 | 222 | contactProperties[History::FieldAccountId] = textChannel->property(History::FieldAccountId).toString(); | ||
684 | 223 | contactProperties[History::FieldIdentifier] = contact->id(); | ||
685 | 224 | contactProperties[History::FieldParticipantState] = History::ParticipantStateLocalPending; | ||
686 | 225 | contactProperties[History::FieldParticipantRoles] = roles[contact->handle().at(0)]; | ||
687 | 226 | participantIds << contact->id(); | ||
688 | 227 | participants << contactProperties; | ||
689 | 89 | } | 228 | } |
690 | 90 | 229 | ||
691 | 91 | if (participants.isEmpty() && textChannel->targetHandleType() == Tp::HandleTypeContact && | 230 | if (participants.isEmpty() && textChannel->targetHandleType() == Tp::HandleTypeContact && |
696 | 92 | textChannel->targetContact() == textChannel->connection()->selfContact()) { | 231 | textChannel->targetContact() == textChannel->connection()->selfContact()) { |
697 | 93 | participants << textChannel->targetContact()->id(); | 232 | QVariantMap contactProperties; |
698 | 94 | } | 233 | contactProperties[History::FieldAlias] = textChannel->targetContact()->alias(); |
699 | 95 | return participants; | 234 | contactProperties[History::FieldAccountId] = textChannel->property(History::FieldAccountId).toString(); |
700 | 235 | contactProperties[History::FieldIdentifier] = textChannel->targetContact()->id(); | ||
701 | 236 | contactProperties[History::FieldParticipantState] = History::ParticipantStateRegular; | ||
702 | 237 | participantIds << textChannel->targetContact()->id(); | ||
703 | 238 | participants << contactProperties; | ||
704 | 239 | } | ||
705 | 240 | |||
706 | 241 | // We map chatType directly from telepathy targetHandleType: None, Contact, Room | ||
707 | 242 | properties[History::FieldChatType] = textChannel->targetHandleType(); | ||
708 | 243 | properties[History::FieldParticipants] = participants; | ||
709 | 244 | properties[History::FieldParticipantIds] = participantIds; | ||
710 | 245 | |||
711 | 246 | QVariantMap roomProperties; | ||
712 | 247 | switch(textChannel->targetHandleType()) { | ||
713 | 248 | case Tp::HandleTypeRoom: | ||
714 | 249 | if (textChannel->hasInterface(TP_QT_IFACE_CHANNEL_INTERFACE_ROOM)) { | ||
715 | 250 | auto room_interface = textChannel->optionalInterface<Tp::Client::ChannelInterfaceRoomInterface>(); | ||
716 | 251 | QVariantMap map = getInterfaceProperties(room_interface); | ||
717 | 252 | for (QVariantMap::const_iterator iter = map.begin(); iter != map.end(); ++iter) { | ||
718 | 253 | if (iter.value().isValid()) { | ||
719 | 254 | roomProperties[iter.key()] = iter.value(); | ||
720 | 255 | } | ||
721 | 256 | } | ||
722 | 257 | } | ||
723 | 258 | if (textChannel->hasInterface(TP_QT_IFACE_CHANNEL_INTERFACE_ROOM_CONFIG)) { | ||
724 | 259 | auto room_config_interface = textChannel->optionalInterface<Tp::Client::ChannelInterfaceRoomConfigInterface>(); | ||
725 | 260 | QVariantMap map = getInterfaceProperties(room_config_interface); | ||
726 | 261 | for (QVariantMap::const_iterator iter = map.begin(); iter != map.end(); ++iter) { | ||
727 | 262 | if (iter.value().isValid()) { | ||
728 | 263 | roomProperties[iter.key()] = iter.value(); | ||
729 | 264 | } | ||
730 | 265 | } | ||
731 | 266 | } | ||
732 | 267 | if (textChannel->hasInterface(TP_QT_IFACE_CHANNEL_INTERFACE_SUBJECT)) { | ||
733 | 268 | auto subject_interface = textChannel->optionalInterface<Tp::Client::ChannelInterfaceSubjectInterface>(); | ||
734 | 269 | QVariantMap map = getInterfaceProperties(subject_interface); | ||
735 | 270 | for (QVariantMap::const_iterator iter = map.begin(); iter != map.end(); ++iter) { | ||
736 | 271 | if (iter.value().isValid()) { | ||
737 | 272 | roomProperties[iter.key()] = iter.value(); | ||
738 | 273 | } | ||
739 | 274 | } | ||
740 | 275 | } | ||
741 | 276 | |||
742 | 277 | properties[History::FieldChatRoomInfo] = roomProperties; | ||
743 | 278 | properties[History::FieldThreadId] = textChannel->targetId(); | ||
744 | 279 | break; | ||
745 | 280 | case Tp::HandleTypeContact: | ||
746 | 281 | case Tp::HandleTypeNone: | ||
747 | 282 | default: | ||
748 | 283 | break; | ||
749 | 284 | } | ||
750 | 285 | |||
751 | 286 | return properties; | ||
752 | 96 | } | 287 | } |
753 | 97 | 288 | ||
759 | 98 | QVariantMap HistoryDaemon::threadForParticipants(const QString &accountId, | 289 | QVariantMap HistoryDaemon::threadForProperties(const QString &accountId, |
760 | 99 | History::EventType type, | 290 | History::EventType type, |
761 | 100 | const QStringList &participants, | 291 | const QVariantMap &properties, |
762 | 101 | History::MatchFlags matchFlags, | 292 | History::MatchFlags matchFlags, |
763 | 102 | bool create) | 293 | bool create) |
764 | 103 | { | 294 | { |
765 | 104 | if (!mBackend) { | 295 | if (!mBackend) { |
766 | 105 | return QVariantMap(); | 296 | return QVariantMap(); |
767 | 106 | } | 297 | } |
768 | 107 | 298 | ||
773 | 108 | QVariantMap thread = mBackend->threadForParticipants(accountId, | 299 | QVariantMap thread = mBackend->threadForProperties(accountId, |
774 | 109 | type, | 300 | type, |
775 | 110 | participants, | 301 | properties, |
776 | 111 | matchFlags); | 302 | matchFlags); |
777 | 112 | if (thread.isEmpty() && create) { | 303 | if (thread.isEmpty() && create) { |
779 | 113 | thread = mBackend->createThreadForParticipants(accountId, type, participants); | 304 | thread = mBackend->createThreadForProperties(accountId, type, properties); |
780 | 114 | if (!thread.isEmpty()) { | 305 | if (!thread.isEmpty()) { |
781 | 306 | if (properties.contains("Requested") && properties[History::FieldChatType].toInt() == History::ChatTypeRoom) { | ||
782 | 307 | QVariantMap map = thread[History::FieldChatRoomInfo].toMap(); | ||
783 | 308 | map["Requested"] = properties["Requested"]; | ||
784 | 309 | thread[History::FieldChatRoomInfo] = map; | ||
785 | 310 | } | ||
786 | 115 | mDBus.notifyThreadsAdded(QList<QVariantMap>() << thread); | 311 | mDBus.notifyThreadsAdded(QList<QVariantMap>() << thread); |
787 | 116 | } | 312 | } |
788 | 117 | } | 313 | } |
789 | @@ -174,7 +370,7 @@ | |||
790 | 174 | return mBackend->getSingleEvent((History::EventType)type, accountId, threadId, eventId); | 370 | return mBackend->getSingleEvent((History::EventType)type, accountId, threadId, eventId); |
791 | 175 | } | 371 | } |
792 | 176 | 372 | ||
794 | 177 | bool HistoryDaemon::writeEvents(const QList<QVariantMap> &events) | 373 | bool HistoryDaemon::writeEvents(const QList<QVariantMap> &events, const QVariantMap &properties) |
795 | 178 | { | 374 | { |
796 | 179 | if (!mBackend) { | 375 | if (!mBackend) { |
797 | 180 | return false; | 376 | return false; |
798 | @@ -206,7 +402,7 @@ | |||
799 | 206 | } | 402 | } |
800 | 207 | 403 | ||
801 | 208 | // only get the thread AFTER the event is written to make sure it is up-to-date | 404 | // only get the thread AFTER the event is written to make sure it is up-to-date |
803 | 209 | QVariantMap thread = getSingleThread(type, accountId, threadId, QVariantMap()); | 405 | QVariantMap thread = getSingleThread(type, accountId, threadId, properties); |
804 | 210 | QString hash = hashThread(thread); | 406 | QString hash = hashThread(thread); |
805 | 211 | threads[hash] = thread; | 407 | threads[hash] = thread; |
806 | 212 | 408 | ||
807 | @@ -245,7 +441,6 @@ | |||
808 | 245 | 441 | ||
809 | 246 | bool HistoryDaemon::removeEvents(const QList<QVariantMap> &events) | 442 | bool HistoryDaemon::removeEvents(const QList<QVariantMap> &events) |
810 | 247 | { | 443 | { |
811 | 248 | qDebug() << __PRETTY_FUNCTION__; | ||
812 | 249 | if (!mBackend) { | 444 | if (!mBackend) { |
813 | 250 | return false; | 445 | return false; |
814 | 251 | } | 446 | } |
815 | @@ -319,7 +514,6 @@ | |||
816 | 319 | 514 | ||
817 | 320 | bool HistoryDaemon::removeThreads(const QList<QVariantMap> &threads) | 515 | bool HistoryDaemon::removeThreads(const QList<QVariantMap> &threads) |
818 | 321 | { | 516 | { |
819 | 322 | qDebug() << __PRETTY_FUNCTION__; | ||
820 | 323 | if (!mBackend) { | 517 | if (!mBackend) { |
821 | 324 | return false; | 518 | return false; |
822 | 325 | } | 519 | } |
823 | @@ -360,7 +554,6 @@ | |||
824 | 360 | 554 | ||
825 | 361 | void HistoryDaemon::onObserverCreated() | 555 | void HistoryDaemon::onObserverCreated() |
826 | 362 | { | 556 | { |
827 | 363 | qDebug() << __PRETTY_FUNCTION__; | ||
828 | 364 | History::ChannelObserver *observer = History::TelepathyHelper::instance()->channelObserver(); | 557 | History::ChannelObserver *observer = History::TelepathyHelper::instance()->channelObserver(); |
829 | 365 | 558 | ||
830 | 366 | connect(observer, SIGNAL(callChannelAvailable(Tp::CallChannelPtr)), | 559 | connect(observer, SIGNAL(callChannelAvailable(Tp::CallChannelPtr)), |
831 | @@ -371,10 +564,14 @@ | |||
832 | 371 | 564 | ||
833 | 372 | void HistoryDaemon::onCallEnded(const Tp::CallChannelPtr &channel) | 565 | void HistoryDaemon::onCallEnded(const Tp::CallChannelPtr &channel) |
834 | 373 | { | 566 | { |
837 | 374 | qDebug() << __PRETTY_FUNCTION__; | 567 | QVariantMap properties = propertiesFromChannel(channel); |
838 | 375 | QStringList participants; | 568 | QVariantList participants; |
839 | 376 | Q_FOREACH(const Tp::ContactPtr contact, channel->remoteMembers()) { | 569 | Q_FOREACH(const Tp::ContactPtr contact, channel->remoteMembers()) { |
841 | 377 | participants << contact->id(); | 570 | QVariantMap contactProperties; |
842 | 571 | contactProperties[History::FieldAlias] = contact->alias(); | ||
843 | 572 | contactProperties[History::FieldIdentifier] = contact->id(); | ||
844 | 573 | contactProperties[History::FieldAccountId] = channel->property(History::FieldAccountId).toString(); | ||
845 | 574 | participants << contactProperties; | ||
846 | 378 | } | 575 | } |
847 | 379 | 576 | ||
848 | 380 | // it shouldn't happen, but in case it does, we won't crash | 577 | // it shouldn't happen, but in case it does, we won't crash |
849 | @@ -384,11 +581,11 @@ | |||
850 | 384 | } | 581 | } |
851 | 385 | 582 | ||
852 | 386 | QString accountId = channel->property(History::FieldAccountId).toString(); | 583 | QString accountId = channel->property(History::FieldAccountId).toString(); |
858 | 387 | QVariantMap thread = threadForParticipants(accountId, | 584 | QVariantMap thread = threadForProperties(accountId, |
859 | 388 | History::EventTypeVoice, | 585 | History::EventTypeVoice, |
860 | 389 | participants, | 586 | properties, |
861 | 390 | matchFlagsForChannel(channel), | 587 | matchFlagsForChannel(channel), |
862 | 391 | true); | 588 | true); |
863 | 392 | // fill the call info | 589 | // fill the call info |
864 | 393 | QDateTime timestamp = channel->property(History::FieldTimestamp).toDateTime(); | 590 | QDateTime timestamp = channel->property(History::FieldTimestamp).toDateTime(); |
865 | 394 | 591 | ||
866 | @@ -414,18 +611,284 @@ | |||
867 | 414 | event[History::FieldMissed] = missed; | 611 | event[History::FieldMissed] = missed; |
868 | 415 | event[History::FieldDuration] = duration; | 612 | event[History::FieldDuration] = duration; |
869 | 416 | // FIXME: check what to do when there are more than just one remote participant | 613 | // FIXME: check what to do when there are more than just one remote participant |
872 | 417 | event[History::FieldRemoteParticipant] = participants[0]; | 614 | event[History::FieldRemoteParticipant] = participants[0].toMap()[History::FieldIdentifier]; |
873 | 418 | writeEvents(QList<QVariantMap>() << event); | 615 | writeEvents(QList<QVariantMap>() << event, properties); |
874 | 616 | } | ||
875 | 617 | |||
876 | 618 | void HistoryDaemon::onTextChannelAvailable(const Tp::TextChannelPtr channel) | ||
877 | 619 | { | ||
878 | 620 | // for Rooms we need to explicitly create the thread to allow users to send messages to groups even | ||
879 | 621 | // before they receive any message. | ||
880 | 622 | // for other types, we can wait until messages are received | ||
881 | 623 | if (channel->targetHandleType() == Tp::HandleTypeRoom) { | ||
882 | 624 | QString accountId = channel->property(History::FieldAccountId).toString(); | ||
883 | 625 | QVariantMap properties = propertiesFromChannel(channel); | ||
884 | 626 | |||
885 | 627 | // first try to fetch the existing thread to see if there is any. | ||
886 | 628 | QVariantMap thread = threadForProperties(accountId, | ||
887 | 629 | History::EventTypeText, | ||
888 | 630 | properties, | ||
889 | 631 | matchFlagsForChannel(channel), | ||
890 | 632 | false); | ||
891 | 633 | if (thread.isEmpty()) { | ||
892 | 634 | // if there no existing thread, create one | ||
893 | 635 | properties["Requested"] = channel->isRequested(); | ||
894 | 636 | thread = threadForProperties(accountId, | ||
895 | 637 | History::EventTypeText, | ||
896 | 638 | properties, | ||
897 | 639 | matchFlagsForChannel(channel), | ||
898 | 640 | true); | ||
899 | 641 | |||
900 | 642 | // write information event including all initial invitees | ||
901 | 643 | Q_FOREACH(const Tp::ContactPtr contact, channel->groupRemotePendingContacts(false)) { | ||
902 | 644 | writeInformationEvent(thread, History::InformationTypeInvitationSent, contact->alias()); | ||
903 | 645 | } | ||
904 | 646 | |||
905 | 647 | // update participants only if the thread is not available previously. Otherwise we'll wait for membersChanged event | ||
906 | 648 | // for reflect in conversation information events for modified participants. | ||
907 | 649 | updateRoomParticipants(channel); | ||
908 | 650 | } | ||
909 | 651 | |||
910 | 652 | // write an entry saying you joined the group if 'joined' flag in thread is false and modify that flag. | ||
911 | 653 | if (!thread[History::FieldChatRoomInfo].toMap()["Joined"].toBool()) { | ||
912 | 654 | // only write self joined notification if protocol is not a phone one. | ||
913 | 655 | // FIXME (rmescandon): as a first solution, let's take only ofono as phone protocol | ||
914 | 656 | if (History::TelepathyHelper::instance()->accountForId(accountId)->protocolName() != "ofono") { | ||
915 | 657 | writeInformationEvent(thread, History::InformationTypeSelfJoined); | ||
916 | 658 | } | ||
917 | 659 | // update backend | ||
918 | 660 | updateRoomProperties(channel, QVariantMap{{"Joined", true}}); | ||
919 | 661 | } | ||
920 | 662 | |||
921 | 663 | Tp::AbstractInterface *room_interface = channel->optionalInterface<Tp::Client::ChannelInterfaceRoomInterface>(); | ||
922 | 664 | Tp::AbstractInterface *room_config_interface = channel->optionalInterface<Tp::Client::ChannelInterfaceRoomConfigInterface>(); | ||
923 | 665 | Tp::AbstractInterface *subject_interface = channel->optionalInterface<Tp::Client::ChannelInterfaceSubjectInterface>(); | ||
924 | 666 | ChannelInterfaceRolesInterface *roles_interface = channel->optionalInterface<ChannelInterfaceRolesInterface>(); | ||
925 | 667 | |||
926 | 668 | QList<Tp::AbstractInterface*> interfaces; | ||
927 | 669 | interfaces << room_interface << room_config_interface << subject_interface << roles_interface; | ||
928 | 670 | for (auto interface : interfaces) { | ||
929 | 671 | if (interface) { | ||
930 | 672 | interface->setMonitorProperties(true); | ||
931 | 673 | interface->setProperty(History::FieldAccountId, accountId); | ||
932 | 674 | interface->setProperty(History::FieldThreadId, thread[History::FieldThreadId].toString()); | ||
933 | 675 | interface->setProperty(History::FieldType, thread[History::FieldType].toInt()); | ||
934 | 676 | connect(interface, SIGNAL(propertiesChanged(const QVariantMap &,const QStringList &)), | ||
935 | 677 | SLOT(onRoomPropertiesChanged(const QVariantMap &,const QStringList &))); | ||
936 | 678 | // update the stored info | ||
937 | 679 | Q_EMIT interface->propertiesChanged(getInterfaceProperties(interface), QStringList()); | ||
938 | 680 | } | ||
939 | 681 | } | ||
940 | 682 | |||
941 | 683 | connect(channel.data(), SIGNAL(groupMembersChanged(const Tp::Contacts &, const Tp::Contacts &, const Tp::Contacts &, const Tp::Contacts &, const Tp::Channel::GroupMemberChangeDetails &)), | ||
942 | 684 | SLOT(onGroupMembersChanged(const Tp::Contacts &, const Tp::Contacts &, const Tp::Contacts &, const Tp::Contacts &, const Tp::Channel::GroupMemberChangeDetails &))); | ||
943 | 685 | |||
944 | 686 | connect(roles_interface, SIGNAL(RolesChanged(const HandleRolesMap&, const HandleRolesMap&)), SLOT(onRolesChanged(const HandleRolesMap&, const HandleRolesMap&))); | ||
945 | 687 | } | ||
946 | 688 | } | ||
947 | 689 | |||
948 | 690 | void HistoryDaemon::onGroupMembersChanged(const Tp::Contacts &groupMembersAdded, | ||
949 | 691 | const Tp::Contacts &groupLocalPendingMembersAdded, | ||
950 | 692 | const Tp::Contacts &groupRemotePendingMembersAdded, | ||
951 | 693 | const Tp::Contacts &groupMembersRemoved, | ||
952 | 694 | const Tp::Channel::GroupMemberChangeDetails &details) | ||
953 | 695 | { | ||
954 | 696 | Tp::TextChannelPtr channel(qobject_cast<Tp::TextChannel*>(sender())); | ||
955 | 697 | |||
956 | 698 | QVariantMap properties; | ||
957 | 699 | QVariantMap thread; | ||
958 | 700 | |||
959 | 701 | // information events for members updates. | ||
960 | 702 | bool hasRemotePendingMembersAdded = groupRemotePendingMembersAdded.size() > 0; | ||
961 | 703 | bool hasMembersAdded = groupMembersAdded.size() > 0; | ||
962 | 704 | bool hasMembersRemoved = groupMembersRemoved.size() > 0; | ||
963 | 705 | |||
964 | 706 | if (hasRemotePendingMembersAdded || hasMembersAdded || hasMembersRemoved) { | ||
965 | 707 | properties = propertiesFromChannel(channel); | ||
966 | 708 | thread = threadForProperties(channel->property(History::FieldAccountId).toString(), | ||
967 | 709 | History::EventTypeText, | ||
968 | 710 | properties, | ||
969 | 711 | matchFlagsForChannel(channel), | ||
970 | 712 | false); | ||
971 | 713 | if (!thread.isEmpty()) { | ||
972 | 714 | if (hasRemotePendingMembersAdded) { | ||
973 | 715 | Q_FOREACH (const Tp::ContactPtr& contact, groupRemotePendingMembersAdded) { | ||
974 | 716 | if (!foundInThread(contact, thread)) { | ||
975 | 717 | writeInformationEvent(thread, History::InformationTypeInvitationSent, contact->alias()); | ||
976 | 718 | } | ||
977 | 719 | } | ||
978 | 720 | } | ||
979 | 721 | if (hasMembersAdded) { | ||
980 | 722 | Q_FOREACH (const Tp::ContactPtr& contact, groupMembersAdded) { | ||
981 | 723 | // if this member was not previously regular member in thread, notify about his join | ||
982 | 724 | if (!foundAsMemberInThread(contact, thread)) { | ||
983 | 725 | writeInformationEvent(thread, History::InformationTypeJoined, contact->alias()); | ||
984 | 726 | } | ||
985 | 727 | } | ||
986 | 728 | } | ||
987 | 729 | |||
988 | 730 | if (hasMembersRemoved) { | ||
989 | 731 | if (channel->groupSelfContactRemoveInfo().isValid()) { | ||
990 | 732 | // evaluate if we are leaving by our own or we are kicked | ||
991 | 733 | History::InformationType type = History::InformationTypeSelfLeaving; | ||
992 | 734 | if (channel->groupSelfContactRemoveInfo().hasReason()) { | ||
993 | 735 | switch (channel->groupSelfContactRemoveInfo().reason()) { | ||
994 | 736 | case ChannelGroupChangeReasonKicked: | ||
995 | 737 | type = History::InformationTypeSelfKicked; | ||
996 | 738 | break; | ||
997 | 739 | case ChannelGroupChangeReasonGone: | ||
998 | 740 | type = History::InformationTypeGroupGone; | ||
999 | 741 | break; | ||
1000 | 742 | } | ||
1001 | 743 | } | ||
1002 | 744 | writeInformationEvent(thread, type); | ||
1003 | 745 | // update backend | ||
1004 | 746 | updateRoomProperties(channel, QVariantMap{{"Joined", false}}); | ||
1005 | 747 | } | ||
1006 | 748 | else // don't notify any other group member removal if we are leaving the group | ||
1007 | 749 | { | ||
1008 | 750 | Q_FOREACH (const Tp::ContactPtr& contact, groupMembersRemoved) { | ||
1009 | 751 | // inform about removed members other than us | ||
1010 | 752 | if (contact->id() != channel->groupSelfContact()->id()) { | ||
1011 | 753 | writeInformationEvent(thread, History::InformationTypeLeaving, contact->alias()); | ||
1012 | 754 | } | ||
1013 | 755 | } | ||
1014 | 756 | } | ||
1015 | 757 | } | ||
1016 | 758 | } | ||
1017 | 759 | } | ||
1018 | 760 | |||
1019 | 761 | updateRoomParticipants(channel); | ||
1020 | 762 | } | ||
1021 | 763 | |||
1022 | 764 | void HistoryDaemon::updateRoomParticipants(const Tp::TextChannelPtr channel) | ||
1023 | 765 | { | ||
1024 | 766 | if (!channel) { | ||
1025 | 767 | return; | ||
1026 | 768 | } | ||
1027 | 769 | |||
1028 | 770 | QVariantList participants; | ||
1029 | 771 | QStringList contactsAdded; | ||
1030 | 772 | |||
1031 | 773 | ChannelInterfaceRolesInterface *roles_interface = channel->optionalInterface<ChannelInterfaceRolesInterface>(); | ||
1032 | 774 | RolesMap roles; | ||
1033 | 775 | if (roles_interface) { | ||
1034 | 776 | roles = roles_interface->getRoles(); | ||
1035 | 777 | } | ||
1036 | 778 | |||
1037 | 779 | Q_FOREACH(const Tp::ContactPtr contact, channel->groupRemotePendingContacts(false)) { | ||
1038 | 780 | QVariantMap participant; | ||
1039 | 781 | contactsAdded << contact->id(); | ||
1040 | 782 | participant[History::FieldIdentifier] = contact->id(); | ||
1041 | 783 | participant[History::FieldAlias] = contact->alias(); | ||
1042 | 784 | participant[History::FieldParticipantState] = History::ParticipantStateRemotePending; | ||
1043 | 785 | participant[History::FieldParticipantRoles] = roles[contact->handle().at(0)]; | ||
1044 | 786 | participants << QVariant::fromValue(participant); | ||
1045 | 787 | } | ||
1046 | 788 | Q_FOREACH(const Tp::ContactPtr contact, channel->groupLocalPendingContacts(false)) { | ||
1047 | 789 | QVariantMap participant; | ||
1048 | 790 | contactsAdded << contact->id(); | ||
1049 | 791 | participant[History::FieldIdentifier] = contact->id(); | ||
1050 | 792 | participant[History::FieldAlias] = contact->alias(); | ||
1051 | 793 | participant[History::FieldParticipantState] = History::ParticipantStateLocalPending; | ||
1052 | 794 | participant[History::FieldParticipantRoles] = roles[contact->handle().at(0)]; | ||
1053 | 795 | participants << QVariant::fromValue(participant); | ||
1054 | 796 | } | ||
1055 | 797 | |||
1056 | 798 | Q_FOREACH(const Tp::ContactPtr contact, channel->groupContacts(false)) { | ||
1057 | 799 | // do not include remote and local pending members | ||
1058 | 800 | if (contactsAdded.contains(contact->id())) { | ||
1059 | 801 | continue; | ||
1060 | 802 | } | ||
1061 | 803 | QVariantMap participant; | ||
1062 | 804 | participant[History::FieldIdentifier] = contact->id(); | ||
1063 | 805 | participant[History::FieldAlias] = contact->alias(); | ||
1064 | 806 | participant[History::FieldParticipantState] = History::ParticipantStateRegular; | ||
1065 | 807 | participant[History::FieldParticipantRoles] = roles[contact->handle().at(0)]; | ||
1066 | 808 | participants << QVariant::fromValue(participant); | ||
1067 | 809 | } | ||
1068 | 810 | |||
1069 | 811 | QString accountId = channel->property(History::FieldAccountId).toString(); | ||
1070 | 812 | QString threadId = channel->targetId(); | ||
1071 | 813 | if (mBackend->updateRoomParticipants(accountId, threadId, History::EventTypeText, participants)) { | ||
1072 | 814 | QVariantMap updatedThread = getSingleThread(History::EventTypeText, accountId, threadId, QVariantMap()); | ||
1073 | 815 | mDBus.notifyThreadsModified(QList<QVariantMap>() << updatedThread); | ||
1074 | 816 | } | ||
1075 | 817 | } | ||
1076 | 818 | |||
1077 | 819 | void HistoryDaemon::updateRoomRoles(const Tp::TextChannelPtr &channel, const RolesMap &rolesMap) | ||
1078 | 820 | { | ||
1079 | 821 | if (!channel) { | ||
1080 | 822 | return; | ||
1081 | 823 | } | ||
1082 | 824 | |||
1083 | 825 | QVariantMap participantsRoles; | ||
1084 | 826 | |||
1085 | 827 | Q_FOREACH(const Tp::ContactPtr contact, channel->groupRemotePendingContacts(false)) { | ||
1086 | 828 | participantsRoles[contact->id()] = rolesMap[contact->handle().at(0)]; | ||
1087 | 829 | } | ||
1088 | 830 | Q_FOREACH(const Tp::ContactPtr contact, channel->groupLocalPendingContacts(false)) { | ||
1089 | 831 | participantsRoles[contact->id()] = rolesMap[contact->handle().at(0)]; | ||
1090 | 832 | } | ||
1091 | 833 | |||
1092 | 834 | Q_FOREACH(const Tp::ContactPtr contact, channel->groupContacts(false)) { | ||
1093 | 835 | if (!participantsRoles.contains(contact->id())) { | ||
1094 | 836 | participantsRoles[contact->id()] = rolesMap[contact->handle().at(0)]; | ||
1095 | 837 | } | ||
1096 | 838 | } | ||
1097 | 839 | |||
1098 | 840 | // update participants roles | ||
1099 | 841 | QString accountId = channel->property(History::FieldAccountId).toString(); | ||
1100 | 842 | QString threadId = channel->targetId(); | ||
1101 | 843 | if (mBackend->updateRoomParticipantsRoles(accountId, threadId, History::EventTypeText, participantsRoles)) { | ||
1102 | 844 | QVariantMap updatedThread = getSingleThread(History::EventTypeText, accountId, threadId, QVariantMap()); | ||
1103 | 845 | mDBus.notifyThreadsModified(QList<QVariantMap>() << updatedThread); | ||
1104 | 846 | } | ||
1105 | 847 | |||
1106 | 848 | // update self roles in room properties | ||
1107 | 849 | uint selfRoles = rolesMap[channel->groupSelfContact()->handle().at(0)]; | ||
1108 | 850 | updateRoomProperties(channel, QVariantMap{{"SelfRoles", selfRoles}}); | ||
1109 | 851 | } | ||
1110 | 852 | |||
1111 | 853 | void HistoryDaemon::onRoomPropertiesChanged(const QVariantMap &properties,const QStringList &invalidated) | ||
1112 | 854 | { | ||
1113 | 855 | QString accountId = sender()->property(History::FieldAccountId).toString(); | ||
1114 | 856 | QString threadId = sender()->property(History::FieldThreadId).toString(); | ||
1115 | 857 | History::EventType type = (History::EventType)sender()->property(History::FieldType).toInt(); | ||
1116 | 858 | |||
1117 | 859 | // get thread before updating to see if there are changes to insert as information events | ||
1118 | 860 | QVariantMap thread = getSingleThread(type, accountId, threadId, QVariantMap()); | ||
1119 | 861 | if (!thread.empty()) { | ||
1120 | 862 | writeRoomChangesInformationEvents(thread, properties); | ||
1121 | 863 | } | ||
1122 | 864 | |||
1123 | 865 | updateRoomProperties(accountId, threadId, type, properties, invalidated); | ||
1124 | 866 | } | ||
1125 | 867 | |||
1126 | 868 | void HistoryDaemon::updateRoomProperties(const Tp::TextChannelPtr &channel, const QVariantMap &properties) | ||
1127 | 869 | { | ||
1128 | 870 | QString accountId = channel->property(History::FieldAccountId).toString(); | ||
1129 | 871 | QString threadId = channel->targetId(); | ||
1130 | 872 | History::EventType type = History::EventTypeText; | ||
1131 | 873 | updateRoomProperties(accountId, threadId, type, properties, QStringList()); | ||
1132 | 874 | } | ||
1133 | 875 | |||
1134 | 876 | void HistoryDaemon::updateRoomProperties(const QString &accountId, const QString &threadId, History::EventType type, const QVariantMap &properties, const QStringList &invalidated) | ||
1135 | 877 | { | ||
1136 | 878 | if (mBackend->updateRoomInfo(accountId, threadId, type, properties, invalidated)) { | ||
1137 | 879 | QVariantMap thread = getSingleThread(type, accountId, threadId, QVariantMap()); | ||
1138 | 880 | mDBus.notifyThreadsModified(QList<QVariantMap>() << thread); | ||
1139 | 881 | } | ||
1140 | 419 | } | 882 | } |
1141 | 420 | 883 | ||
1142 | 421 | void HistoryDaemon::onMessageReceived(const Tp::TextChannelPtr textChannel, const Tp::ReceivedMessage &message) | 884 | void HistoryDaemon::onMessageReceived(const Tp::TextChannelPtr textChannel, const Tp::ReceivedMessage &message) |
1143 | 422 | { | 885 | { |
1144 | 423 | qDebug() << __PRETTY_FUNCTION__; | ||
1145 | 424 | QString eventId; | 886 | QString eventId; |
1146 | 425 | Tp::MessagePart header = message.header(); | 887 | Tp::MessagePart header = message.header(); |
1147 | 426 | QString senderId; | 888 | QString senderId; |
1148 | 889 | QVariantMap properties = propertiesFromChannel(textChannel); | ||
1149 | 427 | History::MessageStatus status = History::MessageStatusUnknown; | 890 | History::MessageStatus status = History::MessageStatusUnknown; |
1151 | 428 | if (message.sender()->handle().at(0) == textChannel->connection()->selfHandle()) { | 891 | if (!message.sender() || message.sender()->handle().at(0) == textChannel->connection()->selfHandle()) { |
1152 | 429 | senderId = "self"; | 892 | senderId = "self"; |
1153 | 430 | status = History::MessageStatusDelivered; | 893 | status = History::MessageStatusDelivered; |
1154 | 431 | } else { | 894 | } else { |
1155 | @@ -452,6 +915,13 @@ | |||
1156 | 452 | return; | 915 | return; |
1157 | 453 | } | 916 | } |
1158 | 454 | 917 | ||
1159 | 918 | // FIXME: if this message is already read, don't allow reverting the status. | ||
1160 | 919 | // we need to check if this is the right place to do it. | ||
1161 | 920 | if (textEvent[History::FieldMessageStatus].toInt() == History::MessageStatusRead) { | ||
1162 | 921 | qWarning() << "Skipping delivery report as it is trying to revert the Read status of an existing message to the following status:" << message.deliveryDetails().status(); | ||
1163 | 922 | return; | ||
1164 | 923 | } | ||
1165 | 924 | |||
1166 | 455 | History::MessageStatus status; | 925 | History::MessageStatus status; |
1167 | 456 | switch (message.deliveryDetails().status()) { | 926 | switch (message.deliveryDetails().status()) { |
1168 | 457 | case Tp::DeliveryStatusAccepted: | 927 | case Tp::DeliveryStatusAccepted: |
1169 | @@ -478,20 +948,18 @@ | |||
1170 | 478 | } | 948 | } |
1171 | 479 | 949 | ||
1172 | 480 | textEvent[History::FieldMessageStatus] = (int) status; | 950 | textEvent[History::FieldMessageStatus] = (int) status; |
1174 | 481 | if (!writeEvents(QList<QVariantMap>() << textEvent)) { | 951 | if (!writeEvents(QList<QVariantMap>() << textEvent, properties)) { |
1175 | 482 | qWarning() << "Failed to save the new message status!"; | 952 | qWarning() << "Failed to save the new message status!"; |
1176 | 483 | } | 953 | } |
1177 | 484 | 954 | ||
1178 | 485 | return; | 955 | return; |
1179 | 486 | } | 956 | } |
1180 | 487 | 957 | ||
1188 | 488 | QStringList participants = participantsFromChannel(textChannel); | 958 | QVariantMap thread = threadForProperties(textChannel->property(History::FieldAccountId).toString(), |
1189 | 489 | 959 | History::EventTypeText, | |
1190 | 490 | QVariantMap thread = threadForParticipants(textChannel->property(History::FieldAccountId).toString(), | 960 | properties, |
1191 | 491 | History::EventTypeText, | 961 | matchFlagsForChannel(textChannel), |
1192 | 492 | participants, | 962 | true); |
1186 | 493 | matchFlagsForChannel(textChannel), | ||
1187 | 494 | true); | ||
1193 | 495 | int count = 1; | 963 | int count = 1; |
1194 | 496 | QList<QVariantMap> attachments; | 964 | QList<QVariantMap> attachments; |
1195 | 497 | History::MessageType type = History::MessageTypeText; | 965 | History::MessageType type = History::MessageTypeText; |
1196 | @@ -558,16 +1026,22 @@ | |||
1197 | 558 | event[History::FieldSubject] = subject; | 1026 | event[History::FieldSubject] = subject; |
1198 | 559 | event[History::FieldAttachments] = QVariant::fromValue(attachments); | 1027 | event[History::FieldAttachments] = QVariant::fromValue(attachments); |
1199 | 560 | 1028 | ||
1201 | 561 | writeEvents(QList<QVariantMap>() << event); | 1029 | writeEvents(QList<QVariantMap>() << event, properties); |
1202 | 1030 | |||
1203 | 1031 | // if this messages supersedes another one, remove the original message | ||
1204 | 1032 | if (!message.supersededToken().isEmpty()) { | ||
1205 | 1033 | event[History::FieldEventId] = message.supersededToken(); | ||
1206 | 1034 | removeEvents(QList<QVariantMap>() << event); | ||
1207 | 1035 | } | ||
1208 | 562 | } | 1036 | } |
1209 | 563 | 1037 | ||
1210 | 564 | QVariantMap HistoryDaemon::getSingleEventFromTextChannel(const Tp::TextChannelPtr textChannel, const QString &messageId) | 1038 | QVariantMap HistoryDaemon::getSingleEventFromTextChannel(const Tp::TextChannelPtr textChannel, const QString &messageId) |
1211 | 565 | { | 1039 | { |
1213 | 566 | QStringList participants = participantsFromChannel(textChannel); | 1040 | QVariantMap properties = propertiesFromChannel(textChannel); |
1214 | 567 | 1041 | ||
1216 | 568 | QVariantMap thread = threadForParticipants(textChannel->property(History::FieldAccountId).toString(), | 1042 | QVariantMap thread = threadForProperties(textChannel->property(History::FieldAccountId).toString(), |
1217 | 569 | History::EventTypeText, | 1043 | History::EventTypeText, |
1219 | 570 | participants, | 1044 | properties, |
1220 | 571 | matchFlagsForChannel(textChannel), | 1045 | matchFlagsForChannel(textChannel), |
1221 | 572 | false); | 1046 | false); |
1222 | 573 | if (thread.isEmpty()) { | 1047 | if (thread.isEmpty()) { |
1223 | @@ -587,6 +1061,7 @@ | |||
1224 | 587 | void HistoryDaemon::onMessageRead(const Tp::TextChannelPtr textChannel, const Tp::ReceivedMessage &message) | 1061 | void HistoryDaemon::onMessageRead(const Tp::TextChannelPtr textChannel, const Tp::ReceivedMessage &message) |
1225 | 588 | { | 1062 | { |
1226 | 589 | QVariantMap textEvent = getSingleEventFromTextChannel(textChannel, message.messageToken()); | 1063 | QVariantMap textEvent = getSingleEventFromTextChannel(textChannel, message.messageToken()); |
1227 | 1064 | QVariantMap properties = propertiesFromChannel(textChannel); | ||
1228 | 590 | 1065 | ||
1229 | 591 | if (textEvent.isEmpty()) { | 1066 | if (textEvent.isEmpty()) { |
1230 | 592 | qWarning() << "Cound not find the original event to update with newEvent = false."; | 1067 | qWarning() << "Cound not find the original event to update with newEvent = false."; |
1231 | @@ -594,15 +1069,14 @@ | |||
1232 | 594 | } | 1069 | } |
1233 | 595 | 1070 | ||
1234 | 596 | textEvent[History::FieldNewEvent] = false; | 1071 | textEvent[History::FieldNewEvent] = false; |
1236 | 597 | if (!writeEvents(QList<QVariantMap>() << textEvent)) { | 1072 | if (!writeEvents(QList<QVariantMap>() << textEvent, properties)) { |
1237 | 598 | qWarning() << "Failed to save the new message status!"; | 1073 | qWarning() << "Failed to save the new message status!"; |
1238 | 599 | } | 1074 | } |
1239 | 600 | } | 1075 | } |
1240 | 601 | 1076 | ||
1241 | 602 | void HistoryDaemon::onMessageSent(const Tp::TextChannelPtr textChannel, const Tp::Message &message, const QString &messageToken) | 1077 | void HistoryDaemon::onMessageSent(const Tp::TextChannelPtr textChannel, const Tp::Message &message, const QString &messageToken) |
1242 | 603 | { | 1078 | { |
1245 | 604 | qDebug() << __PRETTY_FUNCTION__; | 1079 | QVariantMap properties = propertiesFromChannel(textChannel); |
1244 | 605 | QStringList participants = participantsFromChannel(textChannel); | ||
1246 | 606 | QList<QVariantMap> attachments; | 1080 | QList<QVariantMap> attachments; |
1247 | 607 | History::MessageType type = History::MessageTypeText; | 1081 | History::MessageType type = History::MessageTypeText; |
1248 | 608 | int count = 1; | 1082 | int count = 1; |
1249 | @@ -615,9 +1089,9 @@ | |||
1250 | 615 | eventId = messageToken; | 1089 | eventId = messageToken; |
1251 | 616 | } | 1090 | } |
1252 | 617 | 1091 | ||
1254 | 618 | QVariantMap thread = threadForParticipants(textChannel->property(History::FieldAccountId).toString(), | 1092 | QVariantMap thread = threadForProperties(textChannel->property(History::FieldAccountId).toString(), |
1255 | 619 | History::EventTypeText, | 1093 | History::EventTypeText, |
1257 | 620 | participants, | 1094 | properties, |
1258 | 621 | matchFlagsForChannel(textChannel), | 1095 | matchFlagsForChannel(textChannel), |
1259 | 622 | true); | 1096 | true); |
1260 | 623 | if (message.hasNonTextContent()) { | 1097 | if (message.hasNonTextContent()) { |
1261 | @@ -666,7 +1140,6 @@ | |||
1262 | 666 | } | 1140 | } |
1263 | 667 | } | 1141 | } |
1264 | 668 | 1142 | ||
1265 | 669 | |||
1266 | 670 | QVariantMap event; | 1143 | QVariantMap event; |
1267 | 671 | event[History::FieldType] = History::EventTypeText; | 1144 | event[History::FieldType] = History::EventTypeText; |
1268 | 672 | event[History::FieldAccountId] = thread[History::FieldAccountId]; | 1145 | event[History::FieldAccountId] = thread[History::FieldAccountId]; |
1269 | @@ -686,7 +1159,7 @@ | |||
1270 | 686 | event[History::FieldSubject] = ""; | 1159 | event[History::FieldSubject] = ""; |
1271 | 687 | event[History::FieldAttachments] = QVariant::fromValue(attachments); | 1160 | event[History::FieldAttachments] = QVariant::fromValue(attachments); |
1272 | 688 | 1161 | ||
1274 | 689 | writeEvents(QList<QVariantMap>() << event); | 1162 | writeEvents(QList<QVariantMap>() << event, properties); |
1275 | 690 | } | 1163 | } |
1276 | 691 | 1164 | ||
1277 | 692 | History::MatchFlags HistoryDaemon::matchFlagsForChannel(const Tp::ChannelPtr &channel) | 1165 | History::MatchFlags HistoryDaemon::matchFlagsForChannel(const Tp::ChannelPtr &channel) |
1278 | @@ -707,3 +1180,88 @@ | |||
1279 | 707 | hash += "#-#" + thread[History::FieldThreadId].toString(); | 1180 | hash += "#-#" + thread[History::FieldThreadId].toString(); |
1280 | 708 | return hash; | 1181 | return hash; |
1281 | 709 | } | 1182 | } |
1282 | 1183 | |||
1283 | 1184 | QVariantMap HistoryDaemon::getInterfaceProperties(const Tp::AbstractInterface *interface) | ||
1284 | 1185 | { | ||
1285 | 1186 | QDBusInterface propsInterface(interface->service(), interface->path(), "org.freedesktop.DBus.Properties"); | ||
1286 | 1187 | QDBusReply<QVariantMap> reply = propsInterface.call("GetAll", interface->interface()); | ||
1287 | 1188 | if (!reply.isValid()) { | ||
1288 | 1189 | qWarning() << "Failed to fetch channel properties for interface" << interface->interface() << reply.error().message(); | ||
1289 | 1190 | } | ||
1290 | 1191 | return reply.value(); | ||
1291 | 1192 | } | ||
1292 | 1193 | |||
1293 | 1194 | void HistoryDaemon::writeInformationEvent(const QVariantMap &thread, History::InformationType type, const QString &subject, const QString &sender, const QString &text) | ||
1294 | 1195 | { | ||
1295 | 1196 | History::TextEvent historyEvent = History::TextEvent(thread[History::FieldAccountId].toString(), | ||
1296 | 1197 | thread[History::FieldThreadId].toString(), | ||
1297 | 1198 | QString(QCryptographicHash::hash(QByteArray( | ||
1298 | 1199 | (QDateTime::currentDateTime().toString("yyyy-MM-ddTHH:mm:ss.zzz") + subject + text).toLatin1()), | ||
1299 | 1200 | QCryptographicHash::Md5).toHex()), | ||
1300 | 1201 | sender, | ||
1301 | 1202 | QDateTime::currentDateTime(), | ||
1302 | 1203 | false, | ||
1303 | 1204 | text, | ||
1304 | 1205 | History::MessageTypeInformation, | ||
1305 | 1206 | History::MessageStatusUnknown, | ||
1306 | 1207 | QDateTime::currentDateTime(), | ||
1307 | 1208 | subject, | ||
1308 | 1209 | type); | ||
1309 | 1210 | writeEvents(QList<QVariantMap>() << historyEvent.properties(), thread); | ||
1310 | 1211 | } | ||
1311 | 1212 | |||
1312 | 1213 | void HistoryDaemon::writeRoomChangesInformationEvents(const QVariantMap &thread, const QVariantMap &interfaceProperties) | ||
1313 | 1214 | { | ||
1314 | 1215 | if (!thread.isEmpty()) { | ||
1315 | 1216 | // group subject | ||
1316 | 1217 | QString storedSubject = thread[History::FieldChatRoomInfo].toMap()["Subject"].toString(); | ||
1317 | 1218 | QString newSubject = interfaceProperties["Subject"].toString(); | ||
1318 | 1219 | if (!newSubject.isEmpty() && storedSubject != newSubject) { | ||
1319 | 1220 | //see if we have an actor. If actor is 'me', we have changed that subject | ||
1320 | 1221 | QString actor = thread[History::FieldChatRoomInfo].toMap()["Actor"].toString(); | ||
1321 | 1222 | if (actor == "me") { | ||
1322 | 1223 | actor = "self"; | ||
1323 | 1224 | } | ||
1324 | 1225 | writeInformationEvent(thread, History::InformationTypeTitleChanged, newSubject, actor); | ||
1325 | 1226 | } | ||
1326 | 1227 | } | ||
1327 | 1228 | } | ||
1328 | 1229 | |||
1329 | 1230 | void HistoryDaemon::writeRolesInformationEvents(const QVariantMap &thread, const Tp::ChannelPtr &channel, const RolesMap &rolesMap) | ||
1330 | 1231 | { | ||
1331 | 1232 | if (thread.isEmpty()) { | ||
1332 | 1233 | return; | ||
1333 | 1234 | } | ||
1334 | 1235 | |||
1335 | 1236 | if (!thread[History::FieldChatRoomInfo].toMap()["Joined"].toBool()) { | ||
1336 | 1237 | return; | ||
1337 | 1238 | } | ||
1338 | 1239 | |||
1339 | 1240 | // list of identifiers for current channel admins | ||
1340 | 1241 | QStringList adminIds; | ||
1341 | 1242 | |||
1342 | 1243 | Q_FOREACH(const Tp::ContactPtr contact, channel->groupContacts(false)) { | ||
1343 | 1244 | // see if admin role (ChannelAdminRole == 2) | ||
1344 | 1245 | if (rolesMap[contact->handle().at(0)] & AdminRole) { | ||
1345 | 1246 | adminIds << contact->id(); | ||
1346 | 1247 | } | ||
1347 | 1248 | } | ||
1348 | 1249 | |||
1349 | 1250 | Q_FOREACH (QVariant participant, thread[History::FieldParticipants].toList()) { | ||
1350 | 1251 | QString participantId = participant.toMap()[History::FieldIdentifier].toString(); | ||
1351 | 1252 | if (adminIds.contains(participantId)) { | ||
1352 | 1253 | // see if already was admin or not (ChannelAdminRole == 2) | ||
1353 | 1254 | if (! (participant.toMap()[History::FieldParticipantRoles].toUInt() & AdminRole)) { | ||
1354 | 1255 | writeInformationEvent(thread, History::InformationTypeAdminGranted, participantId); | ||
1355 | 1256 | } | ||
1356 | 1257 | } | ||
1357 | 1258 | } | ||
1358 | 1259 | |||
1359 | 1260 | //evaluate now self roles | ||
1360 | 1261 | if (rolesMap[channel->groupSelfContact()->handle().at(0)] & AdminRole) { | ||
1361 | 1262 | uint selfRoles = thread[History::FieldChatRoomInfo].toMap()["SelfRoles"].toUInt(); | ||
1362 | 1263 | if (! (selfRoles & AdminRole)) { | ||
1363 | 1264 | writeInformationEvent(thread, History::InformationTypeSelfAdminGranted); | ||
1364 | 1265 | } | ||
1365 | 1266 | } | ||
1366 | 1267 | } | ||
1367 | 710 | 1268 | ||
1368 | === modified file 'daemon/historydaemon.h' | |||
1369 | --- daemon/historydaemon.h 2015-11-20 11:45:07 +0000 | |||
1370 | +++ daemon/historydaemon.h 2016-11-24 12:52:24 +0000 | |||
1371 | @@ -1,5 +1,5 @@ | |||
1372 | 1 | /* | 1 | /* |
1374 | 2 | * Copyright (C) 2013 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
1375 | 3 | * | 3 | * |
1376 | 4 | * Authors: | 4 | * Authors: |
1377 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
1378 | @@ -30,6 +30,9 @@ | |||
1379 | 30 | #include "callchannelobserver.h" | 30 | #include "callchannelobserver.h" |
1380 | 31 | #include "historyservicedbus.h" | 31 | #include "historyservicedbus.h" |
1381 | 32 | #include "plugin.h" | 32 | #include "plugin.h" |
1382 | 33 | #include "rolesinterface.h" | ||
1383 | 34 | |||
1384 | 35 | typedef QMap<uint,uint> RolesMap; | ||
1385 | 33 | 36 | ||
1386 | 34 | class HistoryDaemon : public QObject | 37 | class HistoryDaemon : public QObject |
1387 | 35 | { | 38 | { |
1388 | @@ -39,19 +42,19 @@ | |||
1389 | 39 | 42 | ||
1390 | 40 | static HistoryDaemon *instance(); | 43 | static HistoryDaemon *instance(); |
1391 | 41 | 44 | ||
1398 | 42 | static QStringList participantsFromChannel(const Tp::TextChannelPtr &textChannel); | 45 | static QVariantMap propertiesFromChannel(const Tp::ChannelPtr &textChannel); |
1399 | 43 | QVariantMap threadForParticipants(const QString &accountId, | 46 | QVariantMap threadForProperties(const QString &accountId, |
1400 | 44 | History::EventType type, | 47 | History::EventType type, |
1401 | 45 | const QStringList &participants, | 48 | const QVariantMap &properties, |
1402 | 46 | History::MatchFlags matchFlags = History::MatchCaseSensitive, | 49 | History::MatchFlags matchFlags = History::MatchCaseSensitive, |
1403 | 47 | bool create = true); | 50 | bool create = true); |
1404 | 48 | QString queryThreads(int type, const QVariantMap &sort, const QVariantMap &filter, const QVariantMap &properties); | 51 | QString queryThreads(int type, const QVariantMap &sort, const QVariantMap &filter, const QVariantMap &properties); |
1405 | 49 | QString queryEvents(int type, const QVariantMap &sort, const QVariantMap &filter); | 52 | QString queryEvents(int type, const QVariantMap &sort, const QVariantMap &filter); |
1406 | 50 | QVariantMap getSingleThread(int type, const QString &accountId, const QString &threadId, const QVariantMap &properties); | 53 | QVariantMap getSingleThread(int type, const QString &accountId, const QString &threadId, const QVariantMap &properties); |
1407 | 51 | QVariantMap getSingleEvent(int type, const QString &accountId, const QString &threadId, const QString &eventId); | 54 | QVariantMap getSingleEvent(int type, const QString &accountId, const QString &threadId, const QString &eventId); |
1408 | 52 | QVariantMap getSingleEventFromTextChannel(const Tp::TextChannelPtr textChannel, const QString &messageId); | 55 | QVariantMap getSingleEventFromTextChannel(const Tp::TextChannelPtr textChannel, const QString &messageId); |
1409 | 53 | 56 | ||
1411 | 54 | bool writeEvents(const QList<QVariantMap> &events); | 57 | bool writeEvents(const QList<QVariantMap> &events, const QVariantMap &properties); |
1412 | 55 | bool removeEvents(const QList<QVariantMap> &events); | 58 | bool removeEvents(const QList<QVariantMap> &events); |
1413 | 56 | bool removeThreads(const QList<QVariantMap> &threads); | 59 | bool removeThreads(const QList<QVariantMap> &threads); |
1414 | 57 | 60 | ||
1415 | @@ -61,11 +64,27 @@ | |||
1416 | 61 | void onMessageReceived(const Tp::TextChannelPtr textChannel, const Tp::ReceivedMessage &message); | 64 | void onMessageReceived(const Tp::TextChannelPtr textChannel, const Tp::ReceivedMessage &message); |
1417 | 62 | void onMessageRead(const Tp::TextChannelPtr textChannel, const Tp::ReceivedMessage &message); | 65 | void onMessageRead(const Tp::TextChannelPtr textChannel, const Tp::ReceivedMessage &message); |
1418 | 63 | void onMessageSent(const Tp::TextChannelPtr textChannel, const Tp::Message &message, const QString &messageToken); | 66 | void onMessageSent(const Tp::TextChannelPtr textChannel, const Tp::Message &message, const QString &messageToken); |
1419 | 67 | void onTextChannelAvailable(const Tp::TextChannelPtr channel); | ||
1420 | 68 | void onRoomPropertiesChanged(const QVariantMap &properties,const QStringList &invalidated); | ||
1421 | 69 | void onGroupMembersChanged(const Tp::Contacts &groupMembersAdded, const Tp::Contacts &groupLocalPendingMembersAdded, | ||
1422 | 70 | const Tp::Contacts &groupRemotePendingMembersAdded, const Tp::Contacts &groupMembersRemoved, | ||
1423 | 71 | const Tp::Channel::GroupMemberChangeDetails &details); | ||
1424 | 72 | void onRolesChanged(const HandleRolesMap &added, const HandleRolesMap &removed); | ||
1425 | 64 | 73 | ||
1426 | 65 | protected: | 74 | protected: |
1427 | 66 | History::MatchFlags matchFlagsForChannel(const Tp::ChannelPtr &channel); | 75 | History::MatchFlags matchFlagsForChannel(const Tp::ChannelPtr &channel); |
1428 | 76 | void updateRoomParticipants(const Tp::TextChannelPtr channel); | ||
1429 | 77 | void updateRoomRoles(const Tp::TextChannelPtr &channel, const RolesMap &rolesMap); | ||
1430 | 67 | QString hashThread(const QVariantMap &thread); | 78 | QString hashThread(const QVariantMap &thread); |
1432 | 68 | 79 | static QVariantMap getInterfaceProperties(const Tp::AbstractInterface *interface); | |
1433 | 80 | void updateRoomProperties(const Tp::TextChannelPtr &channel, const QVariantMap &properties); | ||
1434 | 81 | void updateRoomProperties(const QString &accountId, const QString &threadId, History::EventType type, const QVariantMap &properties, const QStringList &invalidated); | ||
1435 | 82 | |||
1436 | 83 | void writeInformationEvent(const QVariantMap &thread, History::InformationType type, const QString &subject = QString(), const QString &sender = QString("self"), const QString &text = QString()); | ||
1437 | 84 | |||
1438 | 85 | void writeRoomChangesInformationEvents(const QVariantMap &thread, const QVariantMap &interfaceProperties); | ||
1439 | 86 | void writeRolesInformationEvents(const QVariantMap &thread, const Tp::ChannelPtr &channel, const RolesMap &rolesMap); | ||
1440 | 87 | void writeRolesChangesInformationEvents(const QVariantMap &thread, const Tp::ChannelPtr &channel, const RolesMap &rolesMap); | ||
1441 | 69 | private: | 88 | private: |
1442 | 70 | HistoryDaemon(QObject *parent = 0); | 89 | HistoryDaemon(QObject *parent = 0); |
1443 | 71 | 90 | ||
1444 | 72 | 91 | ||
1445 | === modified file 'daemon/historyservicedbus.cpp' | |||
1446 | --- daemon/historyservicedbus.cpp 2015-10-01 19:44:45 +0000 | |||
1447 | +++ daemon/historyservicedbus.cpp 2016-11-24 12:52:24 +0000 | |||
1448 | @@ -1,5 +1,5 @@ | |||
1449 | 1 | /* | 1 | /* |
1451 | 2 | * Copyright (C) 2013 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
1452 | 3 | * | 3 | * |
1453 | 4 | * Authors: | 4 | * Authors: |
1454 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
1455 | @@ -34,16 +34,15 @@ | |||
1456 | 34 | 34 | ||
1457 | 35 | bool HistoryServiceDBus::connectToBus() | 35 | bool HistoryServiceDBus::connectToBus() |
1458 | 36 | { | 36 | { |
1459 | 37 | bool ok = QDBusConnection::sessionBus().registerService(History::DBusService); | ||
1460 | 38 | if (!ok) { | ||
1461 | 39 | return false; | ||
1462 | 40 | } | ||
1463 | 41 | |||
1464 | 42 | if (!mAdaptor) { | 37 | if (!mAdaptor) { |
1465 | 43 | mAdaptor = new HistoryServiceAdaptor(this); | 38 | mAdaptor = new HistoryServiceAdaptor(this); |
1466 | 44 | } | 39 | } |
1467 | 45 | 40 | ||
1469 | 46 | return QDBusConnection::sessionBus().registerObject(History::DBusObjectPath, this); | 41 | if (!QDBusConnection::sessionBus().registerObject(History::DBusObjectPath, this)) { |
1470 | 42 | return false; | ||
1471 | 43 | } | ||
1472 | 44 | |||
1473 | 45 | return QDBusConnection::sessionBus().registerService(History::DBusService); | ||
1474 | 47 | } | 46 | } |
1475 | 48 | 47 | ||
1476 | 49 | void HistoryServiceDBus::notifyThreadsAdded(const QList<QVariantMap> &threads) | 48 | void HistoryServiceDBus::notifyThreadsAdded(const QList<QVariantMap> &threads) |
1477 | @@ -76,58 +75,67 @@ | |||
1478 | 76 | Q_EMIT EventsRemoved(events); | 75 | Q_EMIT EventsRemoved(events); |
1479 | 77 | } | 76 | } |
1480 | 78 | 77 | ||
1481 | 78 | QVariantMap HistoryServiceDBus::ThreadForProperties(const QString &accountId, | ||
1482 | 79 | int type, | ||
1483 | 80 | const QVariantMap &properties, | ||
1484 | 81 | int matchFlags, | ||
1485 | 82 | bool create) | ||
1486 | 83 | { | ||
1487 | 84 | return HistoryDaemon::instance()->threadForProperties(accountId, | ||
1488 | 85 | (History::EventType) type, | ||
1489 | 86 | properties, | ||
1490 | 87 | (History::MatchFlags) matchFlags, | ||
1491 | 88 | create); | ||
1492 | 89 | } | ||
1493 | 90 | |||
1494 | 79 | QVariantMap HistoryServiceDBus::ThreadForParticipants(const QString &accountId, | 91 | QVariantMap HistoryServiceDBus::ThreadForParticipants(const QString &accountId, |
1495 | 80 | int type, | 92 | int type, |
1496 | 81 | const QStringList &participants, | 93 | const QStringList &participants, |
1497 | 82 | int matchFlags, | 94 | int matchFlags, |
1498 | 83 | bool create) | 95 | bool create) |
1499 | 84 | { | 96 | { |
1501 | 85 | return HistoryDaemon::instance()->threadForParticipants(accountId, | 97 | QVariantMap properties; |
1502 | 98 | properties[History::FieldParticipants] = participants; | ||
1503 | 99 | |||
1504 | 100 | return HistoryDaemon::instance()->threadForProperties(accountId, | ||
1505 | 86 | (History::EventType) type, | 101 | (History::EventType) type, |
1507 | 87 | participants, | 102 | properties, |
1508 | 88 | (History::MatchFlags) matchFlags, | 103 | (History::MatchFlags) matchFlags, |
1509 | 89 | create); | 104 | create); |
1510 | 90 | } | 105 | } |
1511 | 91 | 106 | ||
1512 | 92 | bool HistoryServiceDBus::WriteEvents(const QList<QVariantMap> &events) | 107 | bool HistoryServiceDBus::WriteEvents(const QList<QVariantMap> &events) |
1513 | 93 | { | 108 | { |
1516 | 94 | qDebug() << __PRETTY_FUNCTION__; | 109 | return HistoryDaemon::instance()->writeEvents(events, QVariantMap()); |
1515 | 95 | return HistoryDaemon::instance()->writeEvents(events); | ||
1517 | 96 | } | 110 | } |
1518 | 97 | 111 | ||
1519 | 98 | bool HistoryServiceDBus::RemoveThreads(const QList<QVariantMap> &threads) | 112 | bool HistoryServiceDBus::RemoveThreads(const QList<QVariantMap> &threads) |
1520 | 99 | { | 113 | { |
1521 | 100 | qDebug() << __PRETTY_FUNCTION__; | ||
1522 | 101 | return HistoryDaemon::instance()->removeThreads(threads); | 114 | return HistoryDaemon::instance()->removeThreads(threads); |
1523 | 102 | } | 115 | } |
1524 | 103 | 116 | ||
1525 | 104 | bool HistoryServiceDBus::RemoveEvents(const QList<QVariantMap> &events) | 117 | bool HistoryServiceDBus::RemoveEvents(const QList<QVariantMap> &events) |
1526 | 105 | { | 118 | { |
1527 | 106 | qDebug() << __PRETTY_FUNCTION__; | ||
1528 | 107 | return HistoryDaemon::instance()->removeEvents(events); | 119 | return HistoryDaemon::instance()->removeEvents(events); |
1529 | 108 | } | 120 | } |
1530 | 109 | 121 | ||
1531 | 110 | QString HistoryServiceDBus::QueryThreads(int type, const QVariantMap &sort, const QVariantMap &filter, const QVariantMap &properties) | 122 | QString HistoryServiceDBus::QueryThreads(int type, const QVariantMap &sort, const QVariantMap &filter, const QVariantMap &properties) |
1532 | 111 | { | 123 | { |
1533 | 112 | qDebug() << __PRETTY_FUNCTION__; | ||
1534 | 113 | return HistoryDaemon::instance()->queryThreads(type, sort, filter, properties); | 124 | return HistoryDaemon::instance()->queryThreads(type, sort, filter, properties); |
1535 | 114 | } | 125 | } |
1536 | 115 | 126 | ||
1537 | 116 | QString HistoryServiceDBus::QueryEvents(int type, const QVariantMap &sort, const QVariantMap &filter) | 127 | QString HistoryServiceDBus::QueryEvents(int type, const QVariantMap &sort, const QVariantMap &filter) |
1538 | 117 | { | 128 | { |
1539 | 118 | qDebug() << __PRETTY_FUNCTION__; | ||
1540 | 119 | return HistoryDaemon::instance()->queryEvents(type, sort, filter); | 129 | return HistoryDaemon::instance()->queryEvents(type, sort, filter); |
1541 | 120 | } | 130 | } |
1542 | 121 | 131 | ||
1543 | 122 | QVariantMap HistoryServiceDBus::GetSingleThread(int type, const QString &accountId, const QString &threadId, const QVariantMap &properties) | 132 | QVariantMap HistoryServiceDBus::GetSingleThread(int type, const QString &accountId, const QString &threadId, const QVariantMap &properties) |
1544 | 123 | { | 133 | { |
1545 | 124 | qDebug() << __PRETTY_FUNCTION__; | ||
1546 | 125 | return HistoryDaemon::instance()->getSingleThread(type, accountId, threadId, properties); | 134 | return HistoryDaemon::instance()->getSingleThread(type, accountId, threadId, properties); |
1547 | 126 | } | 135 | } |
1548 | 127 | 136 | ||
1549 | 128 | QVariantMap HistoryServiceDBus::GetSingleEvent(int type, const QString &accountId, const QString &threadId, const QString &eventId) | 137 | QVariantMap HistoryServiceDBus::GetSingleEvent(int type, const QString &accountId, const QString &threadId, const QString &eventId) |
1550 | 129 | { | 138 | { |
1551 | 130 | qDebug() << __PRETTY_FUNCTION__; | ||
1552 | 131 | return HistoryDaemon::instance()->getSingleEvent(type, accountId, threadId, eventId); | 139 | return HistoryDaemon::instance()->getSingleEvent(type, accountId, threadId, eventId); |
1553 | 132 | } | 140 | } |
1554 | 133 | 141 | ||
1555 | 134 | 142 | ||
1556 | === modified file 'daemon/historyservicedbus.h' | |||
1557 | --- daemon/historyservicedbus.h 2015-09-23 15:08:07 +0000 | |||
1558 | +++ daemon/historyservicedbus.h 2016-11-24 12:52:24 +0000 | |||
1559 | @@ -1,5 +1,5 @@ | |||
1560 | 1 | /* | 1 | /* |
1562 | 2 | * Copyright (C) 2013 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
1563 | 3 | * | 3 | * |
1564 | 4 | * Authors: | 4 | * Authors: |
1565 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
1566 | @@ -50,6 +50,11 @@ | |||
1567 | 50 | const QStringList &participants, | 50 | const QStringList &participants, |
1568 | 51 | int matchFlags, | 51 | int matchFlags, |
1569 | 52 | bool create); | 52 | bool create); |
1570 | 53 | QVariantMap ThreadForProperties(const QString &accountId, | ||
1571 | 54 | int type, | ||
1572 | 55 | const QVariantMap &properties, | ||
1573 | 56 | int matchFlags, | ||
1574 | 57 | bool create); | ||
1575 | 53 | bool WriteEvents(const QList <QVariantMap> &events); | 58 | bool WriteEvents(const QList <QVariantMap> &events); |
1576 | 54 | bool RemoveThreads(const QList <QVariantMap> &threads); | 59 | bool RemoveThreads(const QList <QVariantMap> &threads); |
1577 | 55 | bool RemoveEvents(const QList <QVariantMap> &events); | 60 | bool RemoveEvents(const QList <QVariantMap> &events); |
1578 | 56 | 61 | ||
1579 | === added file 'daemon/rolesinterface.cpp' | |||
1580 | --- daemon/rolesinterface.cpp 1970-01-01 00:00:00 +0000 | |||
1581 | +++ daemon/rolesinterface.cpp 2016-11-24 12:52:24 +0000 | |||
1582 | @@ -0,0 +1,71 @@ | |||
1583 | 1 | /* | ||
1584 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
1585 | 3 | * | ||
1586 | 4 | * Authors: | ||
1587 | 5 | * Roberto Mier Escandon <roberto.escandon@canonical.com> | ||
1588 | 6 | * | ||
1589 | 7 | * This file is part of history-service. | ||
1590 | 8 | * | ||
1591 | 9 | * history-service is free software; you can redistribute it and/or modify | ||
1592 | 10 | * it under the terms of the GNU General Public License as published by | ||
1593 | 11 | * the Free Software Foundation; version 3. | ||
1594 | 12 | * | ||
1595 | 13 | * history-service is distributed in the hope that it will be useful, | ||
1596 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1597 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1598 | 16 | * GNU General Public License for more details. | ||
1599 | 17 | * | ||
1600 | 18 | * You should have received a copy of the GNU General Public License | ||
1601 | 19 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1602 | 20 | */ | ||
1603 | 21 | |||
1604 | 22 | #include <daemon/rolesinterface.h> | ||
1605 | 23 | |||
1606 | 24 | ChannelInterfaceRolesInterface::ChannelInterfaceRolesInterface(const QString& busName, const QString& objectPath, QObject *parent) | ||
1607 | 25 | : Tp::AbstractInterface(busName, objectPath, staticInterfaceName(), QDBusConnection::sessionBus(), parent) | ||
1608 | 26 | { | ||
1609 | 27 | } | ||
1610 | 28 | |||
1611 | 29 | ChannelInterfaceRolesInterface::ChannelInterfaceRolesInterface(const QDBusConnection& connection, const QString& busName, const QString& objectPath, QObject *parent) | ||
1612 | 30 | : Tp::AbstractInterface(busName, objectPath, staticInterfaceName(), connection, parent) | ||
1613 | 31 | { | ||
1614 | 32 | } | ||
1615 | 33 | |||
1616 | 34 | ChannelInterfaceRolesInterface::ChannelInterfaceRolesInterface(Tp::DBusProxy *proxy) | ||
1617 | 35 | : Tp::AbstractInterface(proxy, staticInterfaceName()) | ||
1618 | 36 | { | ||
1619 | 37 | } | ||
1620 | 38 | |||
1621 | 39 | ChannelInterfaceRolesInterface::ChannelInterfaceRolesInterface(const Tp::Client::ChannelInterface& mainInterface) | ||
1622 | 40 | : Tp::AbstractInterface(mainInterface.service(), mainInterface.path(), staticInterfaceName(), mainInterface.connection(), mainInterface.parent()) | ||
1623 | 41 | { | ||
1624 | 42 | } | ||
1625 | 43 | |||
1626 | 44 | ChannelInterfaceRolesInterface::ChannelInterfaceRolesInterface(const Tp::Client::ChannelInterface& mainInterface, QObject *parent) | ||
1627 | 45 | : Tp::AbstractInterface(mainInterface.service(), mainInterface.path(), staticInterfaceName(), mainInterface.connection(), parent) | ||
1628 | 46 | { | ||
1629 | 47 | } | ||
1630 | 48 | |||
1631 | 49 | void ChannelInterfaceRolesInterface::invalidate(Tp::DBusProxy *proxy, | ||
1632 | 50 | const QString &error, const QString &message) | ||
1633 | 51 | { | ||
1634 | 52 | Tp::AbstractInterface::invalidate(proxy, error, message); | ||
1635 | 53 | } | ||
1636 | 54 | |||
1637 | 55 | HandleRolesMap ChannelInterfaceRolesInterface::getRoles() const | ||
1638 | 56 | { | ||
1639 | 57 | QDBusMessage msg = QDBusMessage::createMethodCall(service(), path(), | ||
1640 | 58 | TP_QT_IFACE_PROPERTIES, QLatin1String("Get")); | ||
1641 | 59 | msg << interface() << QLatin1String("Roles"); | ||
1642 | 60 | QDBusMessage result = connection().call(msg); | ||
1643 | 61 | return qdbus_cast<HandleRolesMap>(result.arguments().at(0).value<QDBusVariant>().variant()); | ||
1644 | 62 | } | ||
1645 | 63 | |||
1646 | 64 | bool ChannelInterfaceRolesInterface::getCanUpdateRoles() const | ||
1647 | 65 | { | ||
1648 | 66 | QDBusMessage msg = QDBusMessage::createMethodCall(service(), path(), | ||
1649 | 67 | TP_QT_IFACE_PROPERTIES, QLatin1String("Get")); | ||
1650 | 68 | msg << interface() << QLatin1String("CanUpdateRoles"); | ||
1651 | 69 | QDBusMessage result = connection().call(msg); | ||
1652 | 70 | return qdbus_cast<bool>(result.arguments().at(0).value<QDBusVariant>().variant()); | ||
1653 | 71 | } | ||
1654 | 0 | 72 | ||
1655 | === added file 'daemon/rolesinterface.h' | |||
1656 | --- daemon/rolesinterface.h 1970-01-01 00:00:00 +0000 | |||
1657 | +++ daemon/rolesinterface.h 2016-11-24 12:52:24 +0000 | |||
1658 | @@ -0,0 +1,210 @@ | |||
1659 | 1 | /* | ||
1660 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
1661 | 3 | * | ||
1662 | 4 | * Authors: | ||
1663 | 5 | * Roberto Mier Escandon <roberto.escandon@canonical.com> | ||
1664 | 6 | * | ||
1665 | 7 | * This file is part of history-service. | ||
1666 | 8 | * | ||
1667 | 9 | * history-service is free software; you can redistribute it and/or modify | ||
1668 | 10 | * it under the terms of the GNU General Public License as published by | ||
1669 | 11 | * the Free Software Foundation; version 3. | ||
1670 | 12 | * | ||
1671 | 13 | * history-service is distributed in the hope that it will be useful, | ||
1672 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1673 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1674 | 16 | * GNU General Public License for more details. | ||
1675 | 17 | * | ||
1676 | 18 | * You should have received a copy of the GNU General Public License | ||
1677 | 19 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1678 | 20 | */ | ||
1679 | 21 | |||
1680 | 22 | #ifndef CHANNELINTERFACEROLESINTERFACE_H | ||
1681 | 23 | #define CHANNELINTERFACEROLESINTERFACE_H | ||
1682 | 24 | |||
1683 | 25 | #include <QMap> | ||
1684 | 26 | |||
1685 | 27 | #include <TelepathyQt/AbstractInterface> | ||
1686 | 28 | #include <TelepathyQt/ChannelInterface> | ||
1687 | 29 | |||
1688 | 30 | /** | ||
1689 | 31 | * \struct HandleRolesMap | ||
1690 | 32 | * \ingroup mapping | ||
1691 | 33 | * \headerfile TelepathyQt/types.h <TelepathyQt/Types> | ||
1692 | 34 | * | ||
1693 | 35 | * Convertible with | ||
1694 | 36 | * QMap<uint, uint>, but needed to have a discrete type in the Qt type system. | ||
1695 | 37 | * | ||
1696 | 38 | * A map from channel-specific handles to their owners. | ||
1697 | 39 | */ | ||
1698 | 40 | struct HandleRolesMap : public QMap<uint, uint> | ||
1699 | 41 | { | ||
1700 | 42 | inline HandleRolesMap() : QMap<uint, uint>() {} | ||
1701 | 43 | inline HandleRolesMap(const QMap<uint, uint>& a) : QMap<uint, uint>(a) {} | ||
1702 | 44 | |||
1703 | 45 | inline HandleRolesMap& operator=(const QMap<uint, uint>& a) | ||
1704 | 46 | { | ||
1705 | 47 | *(static_cast<QMap<uint, uint>*>(this)) = a; | ||
1706 | 48 | return *this; | ||
1707 | 49 | } | ||
1708 | 50 | }; | ||
1709 | 51 | |||
1710 | 52 | Q_DECLARE_METATYPE(HandleRolesMap) | ||
1711 | 53 | |||
1712 | 54 | class ChannelInterfaceRolesInterface : public Tp::AbstractInterface | ||
1713 | 55 | { | ||
1714 | 56 | Q_OBJECT | ||
1715 | 57 | public: | ||
1716 | 58 | |||
1717 | 59 | /** | ||
1718 | 60 | * Returns the name of the interface "org.freedesktop.Telepathy.Channel.Interface.Roles", which this class | ||
1719 | 61 | * represents. | ||
1720 | 62 | * | ||
1721 | 63 | * \return The D-Bus interface name. | ||
1722 | 64 | */ | ||
1723 | 65 | static inline QLatin1String staticInterfaceName() | ||
1724 | 66 | { | ||
1725 | 67 | return QLatin1String("org.freedesktop.Telepathy.Channel.Interface.Roles"); | ||
1726 | 68 | } | ||
1727 | 69 | |||
1728 | 70 | /** | ||
1729 | 71 | * Creates a ChannelInterfaceRolesInterface associated with the given object on the session bus. | ||
1730 | 72 | * | ||
1731 | 73 | * \param busName Name of the service the object is on. | ||
1732 | 74 | * \param objectPath Path to the object on the service. | ||
1733 | 75 | * \param parent Passed to the parent class constructor. | ||
1734 | 76 | */ | ||
1735 | 77 | ChannelInterfaceRolesInterface( | ||
1736 | 78 | const QString& busName, | ||
1737 | 79 | const QString& objectPath, | ||
1738 | 80 | QObject* parent = 0 | ||
1739 | 81 | ); | ||
1740 | 82 | |||
1741 | 83 | /** | ||
1742 | 84 | * Creates a ChannelInterfaceRolesInterface associated with the given object on the given bus. | ||
1743 | 85 | * | ||
1744 | 86 | * \param connection The bus via which the object can be reached. | ||
1745 | 87 | * \param busName Name of the service the object is on. | ||
1746 | 88 | * \param objectPath Path to the object on the service. | ||
1747 | 89 | * \param parent Passed to the parent class constructor. | ||
1748 | 90 | */ | ||
1749 | 91 | ChannelInterfaceRolesInterface( | ||
1750 | 92 | const QDBusConnection& connection, | ||
1751 | 93 | const QString& busName, | ||
1752 | 94 | const QString& objectPath, | ||
1753 | 95 | QObject* parent = 0 | ||
1754 | 96 | ); | ||
1755 | 97 | |||
1756 | 98 | /** | ||
1757 | 99 | * Creates a ChannelInterfaceRolesInterface associated with the same object as the given proxy. | ||
1758 | 100 | * | ||
1759 | 101 | * \param proxy The proxy to use. It will also be the QObject::parent() | ||
1760 | 102 | * for this object. | ||
1761 | 103 | */ | ||
1762 | 104 | ChannelInterfaceRolesInterface(Tp::DBusProxy *proxy); | ||
1763 | 105 | |||
1764 | 106 | /** | ||
1765 | 107 | * Creates a ChannelInterfaceRolesInterface associated with the same object as the given proxy. | ||
1766 | 108 | * Additionally, the created proxy will have the same parent as the given | ||
1767 | 109 | * proxy. | ||
1768 | 110 | * | ||
1769 | 111 | * \param mainInterface The proxy to use. | ||
1770 | 112 | */ | ||
1771 | 113 | explicit ChannelInterfaceRolesInterface(const Tp::Client::ChannelInterface& mainInterface); | ||
1772 | 114 | |||
1773 | 115 | /** | ||
1774 | 116 | * Creates a ChannelInterfaceRolesInterface associated with the same object as the given proxy. | ||
1775 | 117 | * However, a different parent object can be specified. | ||
1776 | 118 | * | ||
1777 | 119 | * \param mainInterface The proxy to use. | ||
1778 | 120 | * \param parent Passed to the parent class constructor. | ||
1779 | 121 | */ | ||
1780 | 122 | ChannelInterfaceRolesInterface(const Tp::Client::ChannelInterface& mainInterface, QObject* parent); | ||
1781 | 123 | |||
1782 | 124 | /** | ||
1783 | 125 | * Asynchronous getter for the remote object property \c Roles of type \c HandleRolesMap. | ||
1784 | 126 | * | ||
1785 | 127 | * \return A pending variant which will emit finished when the property has been | ||
1786 | 128 | * retrieved. | ||
1787 | 129 | */ | ||
1788 | 130 | inline Tp::PendingVariant *requestPropertyRoles() const | ||
1789 | 131 | { | ||
1790 | 132 | return internalRequestProperty(QLatin1String("Roles")); | ||
1791 | 133 | } | ||
1792 | 134 | |||
1793 | 135 | /** | ||
1794 | 136 | * Asynchronous getter for the remote object property \c CanUpdateRoles of type \c bool. | ||
1795 | 137 | * | ||
1796 | 138 | * \return A pending variant which will emit finished when the property has been | ||
1797 | 139 | * retrieved. | ||
1798 | 140 | */ | ||
1799 | 141 | inline Tp::PendingVariant *requestPropertyCanUpdateRoles() const | ||
1800 | 142 | { | ||
1801 | 143 | return internalRequestProperty(QLatin1String("CanUpdateRoles")); | ||
1802 | 144 | } | ||
1803 | 145 | |||
1804 | 146 | /** | ||
1805 | 147 | * Request all of the DBus properties on the interface. | ||
1806 | 148 | * | ||
1807 | 149 | * \return A pending variant map which will emit finished when the properties have | ||
1808 | 150 | * been retrieved. | ||
1809 | 151 | */ | ||
1810 | 152 | Tp::PendingVariantMap *requestAllProperties() const | ||
1811 | 153 | { | ||
1812 | 154 | return internalRequestAllProperties(); | ||
1813 | 155 | } | ||
1814 | 156 | |||
1815 | 157 | /** | ||
1816 | 158 | * Synchronous version to get Roles property | ||
1817 | 159 | */ | ||
1818 | 160 | HandleRolesMap getRoles() const; | ||
1819 | 161 | |||
1820 | 162 | /** | ||
1821 | 163 | * Synchronous version to get CanUpdateRoles property | ||
1822 | 164 | */ | ||
1823 | 165 | bool getCanUpdateRoles() const; | ||
1824 | 166 | |||
1825 | 167 | public Q_SLOTS: | ||
1826 | 168 | /** | ||
1827 | 169 | * Begins a call to the D-Bus method \c UpdateRoles on the remote object. | ||
1828 | 170 | * | ||
1829 | 171 | * Update the roles in the server | ||
1830 | 172 | * | ||
1831 | 173 | */ | ||
1832 | 174 | inline QDBusPendingReply<> UpdateRoles(const HandleRolesMap &contactRoles, int timeout = -1) | ||
1833 | 175 | { | ||
1834 | 176 | if (!invalidationReason().isEmpty()) { | ||
1835 | 177 | return QDBusPendingReply<>(QDBusMessage::createError( | ||
1836 | 178 | invalidationReason(), | ||
1837 | 179 | invalidationMessage() | ||
1838 | 180 | )); | ||
1839 | 181 | } | ||
1840 | 182 | |||
1841 | 183 | QDBusMessage callMessage = QDBusMessage::createMethodCall(this->service(), this->path(), | ||
1842 | 184 | this->staticInterfaceName(), QLatin1String("UpdateRoles")); | ||
1843 | 185 | callMessage << QVariant::fromValue(contactRoles); | ||
1844 | 186 | return this->connection().asyncCall(callMessage, timeout); | ||
1845 | 187 | } | ||
1846 | 188 | |||
1847 | 189 | Q_SIGNALS: | ||
1848 | 190 | /** | ||
1849 | 191 | * Represents the signal \c RolesChanged on the remote object. | ||
1850 | 192 | * | ||
1851 | 193 | * Emitted when the state the roles of the channel has changed. | ||
1852 | 194 | * | ||
1853 | 195 | * \param added | ||
1854 | 196 | * | ||
1855 | 197 | * map of handles and related roles added | ||
1856 | 198 | * | ||
1857 | 199 | * \param removed | ||
1858 | 200 | * | ||
1859 | 201 | * map of handles and related roles removed | ||
1860 | 202 | */ | ||
1861 | 203 | void RolesChanged(const HandleRolesMap &added, const HandleRolesMap& removed); | ||
1862 | 204 | |||
1863 | 205 | protected: | ||
1864 | 206 | virtual void invalidate(Tp::DBusProxy *, const QString &, const QString &); | ||
1865 | 207 | |||
1866 | 208 | }; | ||
1867 | 209 | |||
1868 | 210 | #endif // CHANNELINTERFACEROLESINTERFACE_H | ||
1869 | 0 | 211 | ||
1870 | === modified file 'daemon/textchannelobserver.cpp' | |||
1871 | --- daemon/textchannelobserver.cpp 2014-09-10 04:28:32 +0000 | |||
1872 | +++ daemon/textchannelobserver.cpp 2016-11-24 12:52:24 +0000 | |||
1873 | @@ -1,5 +1,5 @@ | |||
1874 | 1 | /* | 1 | /* |
1876 | 2 | * Copyright (C) 2012-2013 Canonical, Ltd. | 2 | * Copyright (C) 2012-2016 Canonical, Ltd. |
1877 | 3 | * | 3 | * |
1878 | 4 | * Authors: | 4 | * Authors: |
1879 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
1880 | @@ -43,6 +43,8 @@ | |||
1881 | 43 | SIGNAL(pendingMessageRemoved(const Tp::ReceivedMessage&)), | 43 | SIGNAL(pendingMessageRemoved(const Tp::ReceivedMessage&)), |
1882 | 44 | SLOT(onPendingMessageRemoved(const Tp::ReceivedMessage&))); | 44 | SLOT(onPendingMessageRemoved(const Tp::ReceivedMessage&))); |
1883 | 45 | 45 | ||
1884 | 46 | Q_EMIT channelAvailable(textChannel); | ||
1885 | 47 | |||
1886 | 46 | // process the messages that are already pending in the channel | 48 | // process the messages that are already pending in the channel |
1887 | 47 | Q_FOREACH(const Tp::ReceivedMessage &message, textChannel->messageQueue()) { | 49 | Q_FOREACH(const Tp::ReceivedMessage &message, textChannel->messageQueue()) { |
1888 | 48 | Q_EMIT messageReceived(textChannel, message); | 50 | Q_EMIT messageReceived(textChannel, message); |
1889 | 49 | 51 | ||
1890 | === modified file 'daemon/textchannelobserver.h' | |||
1891 | --- daemon/textchannelobserver.h 2013-07-12 14:30:18 +0000 | |||
1892 | +++ daemon/textchannelobserver.h 2016-11-24 12:52:24 +0000 | |||
1893 | @@ -1,5 +1,5 @@ | |||
1894 | 1 | /* | 1 | /* |
1896 | 2 | * Copyright (C) 2012-2013 Canonical, Ltd. | 2 | * Copyright (C) 2012-2016 Canonical, Ltd. |
1897 | 3 | * | 3 | * |
1898 | 4 | * Authors: | 4 | * Authors: |
1899 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
1900 | @@ -36,6 +36,7 @@ | |||
1901 | 36 | void onTextChannelAvailable(Tp::TextChannelPtr textChannel); | 36 | void onTextChannelAvailable(Tp::TextChannelPtr textChannel); |
1902 | 37 | 37 | ||
1903 | 38 | Q_SIGNALS: | 38 | Q_SIGNALS: |
1904 | 39 | void channelAvailable(const Tp::TextChannelPtr textChannel); | ||
1905 | 39 | void messageReceived(const Tp::TextChannelPtr textChannel, const Tp::ReceivedMessage &message); | 40 | void messageReceived(const Tp::TextChannelPtr textChannel, const Tp::ReceivedMessage &message); |
1906 | 40 | void messageRead(const Tp::TextChannelPtr textChannel, const Tp::ReceivedMessage &message); | 41 | void messageRead(const Tp::TextChannelPtr textChannel, const Tp::ReceivedMessage &message); |
1907 | 41 | void messageSent(const Tp::TextChannelPtr textChannel, const Tp::Message &message, const QString &messageToken); | 42 | void messageSent(const Tp::TextChannelPtr textChannel, const Tp::Message &message, const QString &messageToken); |
1908 | 42 | 43 | ||
1909 | === added file 'plugins/sqlite/schema/v13.sql' | |||
1910 | --- plugins/sqlite/schema/v13.sql 1970-01-01 00:00:00 +0000 | |||
1911 | +++ plugins/sqlite/schema/v13.sql 2016-11-24 12:52:24 +0000 | |||
1912 | @@ -0,0 +1,44 @@ | |||
1913 | 1 | ALTER TABLE threads ADD COLUMN chatType tinyint; | ||
1914 | 2 | ALTER TABLE thread_participants ADD COLUMN alias varchar(255); | ||
1915 | 3 | ALTER TABLE thread_participants ADD COLUMN state tinyint; | ||
1916 | 4 | CREATE TABLE chat_room_info ( | ||
1917 | 5 | accountId varchar(255), | ||
1918 | 6 | type tinyint, | ||
1919 | 7 | threadId varchar(255), | ||
1920 | 8 | roomName varchar(255), | ||
1921 | 9 | server varchar(255), | ||
1922 | 10 | creator varchar(255), | ||
1923 | 11 | creationTimestamp datetime, | ||
1924 | 12 | anonymous boolean, | ||
1925 | 13 | inviteOnly boolean, | ||
1926 | 14 | participantLimit integer, | ||
1927 | 15 | moderated boolean, | ||
1928 | 16 | title varchar(1024), | ||
1929 | 17 | description varchar(1024), | ||
1930 | 18 | persistent boolean, | ||
1931 | 19 | private boolean, | ||
1932 | 20 | passwordProtected boolean, | ||
1933 | 21 | password varchar(512), | ||
1934 | 22 | passwordHint varchar(512), | ||
1935 | 23 | canUpdateConfiguration boolean, | ||
1936 | 24 | subject varchar(1024), | ||
1937 | 25 | actor varchar(512), | ||
1938 | 26 | timestamp datetime | ||
1939 | 27 | ); | ||
1940 | 28 | UPDATE threads SET chatType = 0; | ||
1941 | 29 | UPDATE threads SET chatType=1 WHERE (SELECT COUNT(participantId) from thread_participants WHERE thread_participants.threadId=threads.threadId and thread_participants.accountId=threads.accountId AND thread_participants.type=threads.type)=1; | ||
1942 | 30 | UPDATE thread_participants SET state = 0; | ||
1943 | 31 | |||
1944 | 32 | DROP TRIGGER threads_delete_trigger; | ||
1945 | 33 | CREATE TRIGGER threads_delete_trigger AFTER DELETE ON threads | ||
1946 | 34 | FOR EACH ROW | ||
1947 | 35 | BEGIN | ||
1948 | 36 | DELETE FROM thread_participants WHERE | ||
1949 | 37 | accountId=old.accountId AND | ||
1950 | 38 | threadId=old.threadId AND | ||
1951 | 39 | type=old.type; | ||
1952 | 40 | DELETE FROM chat_room_info WHERE | ||
1953 | 41 | accountId=old.accountId AND | ||
1954 | 42 | threadId=old.threadId AND | ||
1955 | 43 | type=old.type; | ||
1956 | 44 | END; | ||
1957 | 0 | 45 | ||
1958 | === added file 'plugins/sqlite/schema/v14.sql' | |||
1959 | --- plugins/sqlite/schema/v14.sql 1970-01-01 00:00:00 +0000 | |||
1960 | +++ plugins/sqlite/schema/v14.sql 2016-11-24 12:52:24 +0000 | |||
1961 | @@ -0,0 +1,82 @@ | |||
1962 | 1 | DROP TRIGGER text_events_insert_trigger; | ||
1963 | 2 | CREATE TRIGGER text_events_insert_trigger AFTER INSERT ON text_events | ||
1964 | 3 | FOR EACH ROW WHEN new.messageType!=2 | ||
1965 | 4 | BEGIN | ||
1966 | 5 | UPDATE threads SET count=(SELECT count(eventId) FROM text_events WHERE | ||
1967 | 6 | accountId=new.accountId AND | ||
1968 | 7 | threadId=new.threadId AND | ||
1969 | 8 | messageType!=2) | ||
1970 | 9 | WHERE accountId=new.accountId AND threadId=new.threadId AND type=0; | ||
1971 | 10 | UPDATE threads SET unreadCount=(SELECT count(eventId) FROM text_events WHERE | ||
1972 | 11 | accountId=new.accountId AND threadId=new.threadId AND newEvent='1' AND messageType!=2) | ||
1973 | 12 | WHERE accountId=new.accountId AND threadId=new.threadId AND type=0; | ||
1974 | 13 | UPDATE threads SET lastEventId=(SELECT eventId FROM text_events WHERE | ||
1975 | 14 | accountId=new.accountId AND | ||
1976 | 15 | threadId=new.threadId AND | ||
1977 | 16 | messageType!=2 | ||
1978 | 17 | ORDER BY timestamp DESC LIMIT 1) | ||
1979 | 18 | WHERE accountId=new.accountId AND threadId=new.threadId AND type=0; | ||
1980 | 19 | UPDATE threads SET lastEventTimestamp=(SELECT timestamp FROM text_events WHERE | ||
1981 | 20 | accountId=new.accountId AND | ||
1982 | 21 | threadId=new.threadId AND | ||
1983 | 22 | messageType!=2 | ||
1984 | 23 | ORDER BY timestamp DESC LIMIT 1) | ||
1985 | 24 | WHERE accountId=new.accountId AND threadId=new.threadId AND type=0; | ||
1986 | 25 | END; | ||
1987 | 26 | |||
1988 | 27 | DROP TRIGGER text_events_update_trigger; | ||
1989 | 28 | CREATE TRIGGER text_events_update_trigger AFTER UPDATE ON text_events | ||
1990 | 29 | FOR EACH ROW WHEN new.messageType!=2 | ||
1991 | 30 | BEGIN | ||
1992 | 31 | UPDATE threads SET count=(SELECT count(eventId) FROM text_events WHERE | ||
1993 | 32 | accountId=new.accountId AND | ||
1994 | 33 | threadId=new.threadId AND | ||
1995 | 34 | messageType!=2) | ||
1996 | 35 | WHERE accountId=new.accountId AND threadId=new.threadId AND type=0; | ||
1997 | 36 | UPDATE threads SET unreadCount=(SELECT count(eventId) FROM text_events WHERE | ||
1998 | 37 | accountId=new.accountId AND threadId=new.threadId AND newEvent='1' AND messageType!=2) | ||
1999 | 38 | WHERE accountId=new.accountId AND threadId=new.threadId AND type=0; | ||
2000 | 39 | UPDATE threads SET lastEventId=(SELECT eventId FROM text_events WHERE | ||
2001 | 40 | accountId=new.accountId AND | ||
2002 | 41 | threadId=new.threadId AND | ||
2003 | 42 | messageType!=2 | ||
2004 | 43 | ORDER BY timestamp DESC LIMIT 1) | ||
2005 | 44 | WHERE accountId=new.accountId AND threadId=new.threadId AND type=0; | ||
2006 | 45 | UPDATE threads SET lastEventTimestamp=(SELECT timestamp FROM text_events WHERE | ||
2007 | 46 | accountId=new.accountId AND | ||
2008 | 47 | threadId=new.threadId AND | ||
2009 | 48 | messageType!=2 | ||
2010 | 49 | ORDER BY timestamp DESC LIMIT 1) | ||
2011 | 50 | WHERE accountId=new.accountId AND threadId=new.threadId AND type=0; | ||
2012 | 51 | END; | ||
2013 | 52 | |||
2014 | 53 | DROP TRIGGER text_events_delete_trigger; | ||
2015 | 54 | CREATE TRIGGER text_events_delete_trigger AFTER DELETE ON text_events | ||
2016 | 55 | FOR EACH ROW WHEN old.messageType!=2 | ||
2017 | 56 | BEGIN | ||
2018 | 57 | UPDATE threads SET count=(SELECT count(eventId) FROM text_events WHERE | ||
2019 | 58 | accountId=old.accountId AND | ||
2020 | 59 | threadId=old.threadId AND | ||
2021 | 60 | messageType!=2) | ||
2022 | 61 | WHERE accountId=old.accountId AND threadId=old.threadId AND type=0; | ||
2023 | 62 | UPDATE threads SET unreadCount=(SELECT count(eventId) FROM text_events WHERE | ||
2024 | 63 | accountId=old.accountId AND threadId=old.threadId AND newEvent='1' AND messageType!=2) | ||
2025 | 64 | WHERE accountId=old.accountId AND threadId=old.threadId AND type=0; | ||
2026 | 65 | UPDATE threads SET lastEventId=(SELECT eventId FROM text_events WHERE | ||
2027 | 66 | accountId=old.accountId AND | ||
2028 | 67 | threadId=old.threadId AND | ||
2029 | 68 | messageType!=2 | ||
2030 | 69 | ORDER BY timestamp DESC LIMIT 1) | ||
2031 | 70 | WHERE accountId=old.accountId AND threadId=old.threadId AND type=0; | ||
2032 | 71 | UPDATE threads SET lastEventTimestamp=(SELECT timestamp FROM text_events WHERE | ||
2033 | 72 | accountId=old.accountId AND | ||
2034 | 73 | threadId=old.threadId AND | ||
2035 | 74 | messageType!=2 | ||
2036 | 75 | ORDER BY timestamp DESC LIMIT 1) | ||
2037 | 76 | WHERE accountId=old.accountId AND threadId=old.threadId AND type=0; | ||
2038 | 77 | DELETE from text_event_attachments WHERE | ||
2039 | 78 | accountId=old.accountId AND | ||
2040 | 79 | threadId=old.threadId AND | ||
2041 | 80 | eventId=old.eventId; | ||
2042 | 81 | END; | ||
2043 | 82 | |||
2044 | 0 | 83 | ||
2045 | === added file 'plugins/sqlite/schema/v15.sql' | |||
2046 | --- plugins/sqlite/schema/v15.sql 1970-01-01 00:00:00 +0000 | |||
2047 | +++ plugins/sqlite/schema/v15.sql 2016-11-24 12:52:24 +0000 | |||
2048 | @@ -0,0 +1,1 @@ | |||
2049 | 1 | ALTER TABLE thread_participants ADD COLUMN roles tinyint; | ||
2050 | 0 | 2 | ||
2051 | === added file 'plugins/sqlite/schema/v16.sql' | |||
2052 | --- plugins/sqlite/schema/v16.sql 1970-01-01 00:00:00 +0000 | |||
2053 | +++ plugins/sqlite/schema/v16.sql 2016-11-24 12:52:24 +0000 | |||
2054 | @@ -0,0 +1,2 @@ | |||
2055 | 1 | ALTER TABLE chat_room_info ADD COLUMN joined boolean; | ||
2056 | 2 | ALTER TABLE chat_room_info ADD COLUMN selfRoles integer; | ||
2057 | 0 | 3 | ||
2058 | === added file 'plugins/sqlite/schema/v17.sql' | |||
2059 | --- plugins/sqlite/schema/v17.sql 1970-01-01 00:00:00 +0000 | |||
2060 | +++ plugins/sqlite/schema/v17.sql 2016-11-24 12:52:24 +0000 | |||
2061 | @@ -0,0 +1,2 @@ | |||
2062 | 1 | ALTER TABLE text_events ADD COLUMN informationType integer; | ||
2063 | 2 | UPDATE text_events SET informationType = 1; | ||
2064 | 0 | 3 | ||
2065 | === modified file 'plugins/sqlite/sqlitedatabase.cpp' | |||
2066 | --- plugins/sqlite/sqlitedatabase.cpp 2015-10-06 12:54:04 +0000 | |||
2067 | +++ plugins/sqlite/sqlitedatabase.cpp 2016-11-24 12:52:24 +0000 | |||
2068 | @@ -207,6 +207,7 @@ | |||
2069 | 207 | 207 | ||
2070 | 208 | QStringList statements; | 208 | QStringList statements; |
2071 | 209 | int existingVersion = 0; | 209 | int existingVersion = 0; |
2072 | 210 | int upgradeToVersion = 0; | ||
2073 | 210 | 211 | ||
2074 | 211 | if (create) { | 212 | if (create) { |
2075 | 212 | statements = parseSchemaFile(":/database/schema/schema.sql"); | 213 | statements = parseSchemaFile(":/database/schema/schema.sql"); |
2076 | @@ -219,7 +220,7 @@ | |||
2077 | 219 | } | 220 | } |
2078 | 220 | 221 | ||
2079 | 221 | existingVersion = query.value(0).toInt(); | 222 | existingVersion = query.value(0).toInt(); |
2081 | 222 | int upgradeToVersion = existingVersion + 1; | 223 | upgradeToVersion = existingVersion + 1; |
2082 | 223 | while (upgradeToVersion <= mSchemaVersion) { | 224 | while (upgradeToVersion <= mSchemaVersion) { |
2083 | 224 | statements += parseSchemaFile(QString(":/database/schema/v%1.sql").arg(QString::number(upgradeToVersion))); | 225 | statements += parseSchemaFile(QString(":/database/schema/v%1.sql").arg(QString::number(upgradeToVersion))); |
2084 | 225 | ++upgradeToVersion; | 226 | ++upgradeToVersion; |
2085 | @@ -256,6 +257,22 @@ | |||
2086 | 256 | return false; | 257 | return false; |
2087 | 257 | } | 258 | } |
2088 | 258 | } | 259 | } |
2089 | 260 | if (existingVersion < 13) { | ||
2090 | 261 | // convert all ofono groups to Room type depending if the mms option is enabled | ||
2091 | 262 | QVariant mmsGroupChatEnabled = History::Utils::getUserValue("com.ubuntu.touch.AccountsService.Phone", "MmsGroupChatEnabled"); | ||
2092 | 263 | // we must not fail if we cannot reach accounts service. | ||
2093 | 264 | if (mmsGroupChatEnabled.isValid()) { | ||
2094 | 265 | // if mms is disabled all chats will be turned into broadcast, otherwise | ||
2095 | 266 | // we turn them into Room | ||
2096 | 267 | if (mmsGroupChatEnabled.toBool()) { | ||
2097 | 268 | if (!convertOfonoGroupChatToRoom()) { | ||
2098 | 269 | qCritical() << "Failed to update existing group chats to Room type."; | ||
2099 | 270 | rollbackTransaction(); | ||
2100 | 271 | return false; | ||
2101 | 272 | } | ||
2102 | 273 | } | ||
2103 | 274 | } | ||
2104 | 275 | } | ||
2105 | 259 | } | 276 | } |
2106 | 260 | 277 | ||
2107 | 261 | finishTransaction(); | 278 | finishTransaction(); |
2108 | @@ -392,3 +409,40 @@ | |||
2109 | 392 | 409 | ||
2110 | 393 | return true; | 410 | return true; |
2111 | 394 | } | 411 | } |
2112 | 412 | |||
2113 | 413 | bool SQLiteDatabase::convertOfonoGroupChatToRoom() | ||
2114 | 414 | { | ||
2115 | 415 | QSqlQuery query(database()); | ||
2116 | 416 | QString queryText = "UPDATE threads SET chatType=2 WHERE accountId LIKE 'ofono/ofono%' AND (SELECT COUNT(participantId) from thread_participants WHERE thread_participants.threadId=threads.threadId and thread_participants.accountId=threads.accountId AND thread_participants.type=threads.type) > 1"; | ||
2117 | 417 | |||
2118 | 418 | query.prepare(queryText); | ||
2119 | 419 | if (!query.exec()) { | ||
2120 | 420 | qWarning() << "Failed to update group chats to Room 1:" << query.executedQuery() << query.lastError(); | ||
2121 | 421 | return false; | ||
2122 | 422 | } | ||
2123 | 423 | query.clear(); | ||
2124 | 424 | |||
2125 | 425 | // now insert a row in chat_room_info for each room | ||
2126 | 426 | if (!query.exec("SELECT accountId, threadId from threads WHERE accountId LIKE 'ofono/ofono%' AND chatType=2")) { | ||
2127 | 427 | qWarning() << "Failed to update group chats to Room 2:" << query.executedQuery() << query.lastError(); | ||
2128 | 428 | return false; | ||
2129 | 429 | } | ||
2130 | 430 | |||
2131 | 431 | while (query.next()) { | ||
2132 | 432 | QSqlQuery queryInsertRoom(database()); | ||
2133 | 433 | QString accountId = query.value(0).toString(); | ||
2134 | 434 | QString threadId = query.value(1).toString(); | ||
2135 | 435 | queryInsertRoom.prepare("INSERT INTO chat_room_info (accountId, threadId, type, joined) VALUES (:accountId,:threadId,:type,:joined)"); | ||
2136 | 436 | queryInsertRoom.bindValue(":accountId", accountId); | ||
2137 | 437 | queryInsertRoom.bindValue(":threadId", threadId); | ||
2138 | 438 | queryInsertRoom.bindValue(":type", History::EventTypeText); | ||
2139 | 439 | queryInsertRoom.bindValue(":joined", true); | ||
2140 | 440 | if(!queryInsertRoom.exec()) { | ||
2141 | 441 | qWarning() << "Failed to update group chats to Room 3:" << queryInsertRoom.executedQuery() << queryInsertRoom.lastError(); | ||
2142 | 442 | return false; | ||
2143 | 443 | } | ||
2144 | 444 | queryInsertRoom.clear(); | ||
2145 | 445 | } | ||
2146 | 446 | query.clear(); | ||
2147 | 447 | } | ||
2148 | 448 | |||
2149 | 395 | 449 | ||
2150 | === modified file 'plugins/sqlite/sqlitedatabase.h' | |||
2151 | --- plugins/sqlite/sqlitedatabase.h 2015-09-02 18:14:15 +0000 | |||
2152 | +++ plugins/sqlite/sqlitedatabase.h 2016-11-24 12:52:24 +0000 | |||
2153 | @@ -50,6 +50,7 @@ | |||
2154 | 50 | 50 | ||
2155 | 51 | // data upgrade functions | 51 | // data upgrade functions |
2156 | 52 | bool changeTimestampsToUtc(); | 52 | bool changeTimestampsToUtc(); |
2157 | 53 | bool convertOfonoGroupChatToRoom(); | ||
2158 | 53 | 54 | ||
2159 | 54 | private: | 55 | private: |
2160 | 55 | explicit SQLiteDatabase(QObject *parent = 0); | 56 | explicit SQLiteDatabase(QObject *parent = 0); |
2161 | 56 | 57 | ||
2162 | === modified file 'plugins/sqlite/sqlitehistoryplugin.cpp' | |||
2163 | --- plugins/sqlite/sqlitehistoryplugin.cpp 2015-11-20 11:40:36 +0000 | |||
2164 | +++ plugins/sqlite/sqlitehistoryplugin.cpp 2016-11-24 12:52:24 +0000 | |||
2165 | @@ -1,5 +1,5 @@ | |||
2166 | 1 | /* | 1 | /* |
2168 | 2 | * Copyright (C) 2013-2015 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
2169 | 3 | * | 3 | * |
2170 | 4 | * Authors: | 4 | * Authors: |
2171 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
2172 | @@ -35,17 +35,20 @@ | |||
2173 | 35 | #include <QStringList> | 35 | #include <QStringList> |
2174 | 36 | #include <QSqlError> | 36 | #include <QSqlError> |
2175 | 37 | #include <QDBusMetaType> | 37 | #include <QDBusMetaType> |
2176 | 38 | #include <QCryptographicHash> | ||
2177 | 38 | 39 | ||
2182 | 39 | QString generateThreadMapKey(const History::Thread &thread) | 40 | static const QLatin1String timestampFormat("yyyy-MM-ddTHH:mm:ss.zzz"); |
2179 | 40 | { | ||
2180 | 41 | return thread.accountId() + thread.threadId(); | ||
2181 | 42 | } | ||
2183 | 43 | 41 | ||
2184 | 44 | QString generateThreadMapKey(const QString &accountId, const QString &threadId) | 42 | QString generateThreadMapKey(const QString &accountId, const QString &threadId) |
2185 | 45 | { | 43 | { |
2186 | 46 | return accountId + threadId; | 44 | return accountId + threadId; |
2187 | 47 | } | 45 | } |
2188 | 48 | 46 | ||
2189 | 47 | QString generateThreadMapKey(const History::Thread &thread) | ||
2190 | 48 | { | ||
2191 | 49 | return generateThreadMapKey(thread.accountId(), thread.threadId()); | ||
2192 | 50 | } | ||
2193 | 51 | |||
2194 | 49 | SQLiteHistoryPlugin::SQLiteHistoryPlugin(QObject *parent) : | 52 | SQLiteHistoryPlugin::SQLiteHistoryPlugin(QObject *parent) : |
2195 | 50 | QObject(parent), mInitialised(false) | 53 | QObject(parent), mInitialised(false) |
2196 | 51 | { | 54 | { |
2197 | @@ -81,18 +84,18 @@ | |||
2198 | 81 | // so instead we just convert to UTC here on the cache and convert back to local time | 84 | // so instead we just convert to UTC here on the cache and convert back to local time |
2199 | 82 | // when returning | 85 | // when returning |
2200 | 83 | QDateTime timestamp = QDateTime::fromString(properties[History::FieldTimestamp].toString(), Qt::ISODate); | 86 | QDateTime timestamp = QDateTime::fromString(properties[History::FieldTimestamp].toString(), Qt::ISODate); |
2202 | 84 | properties[History::FieldTimestamp] = timestamp.toUTC().toString("yyyy-MM-ddTHH:mm:ss.zzz"); | 87 | properties[History::FieldTimestamp] = timestamp.toUTC().toString(timestampFormat); |
2203 | 85 | 88 | ||
2204 | 86 | // the same for readTimestamp | 89 | // the same for readTimestamp |
2205 | 87 | timestamp = QDateTime::fromString(properties[History::FieldReadTimestamp].toString(), Qt::ISODate); | 90 | timestamp = QDateTime::fromString(properties[History::FieldReadTimestamp].toString(), Qt::ISODate); |
2207 | 88 | properties[History::FieldReadTimestamp] = timestamp.toUTC().toString("yyyy-MM-ddTHH:mm:ss.zzz"); | 91 | properties[History::FieldReadTimestamp] = timestamp.toUTC().toString(timestampFormat); |
2208 | 89 | 92 | ||
2209 | 90 | History::Thread thread = History::Thread::fromProperties(properties); | 93 | History::Thread thread = History::Thread::fromProperties(properties); |
2210 | 91 | const QString &threadKey = generateThreadMapKey(thread); | 94 | const QString &threadKey = generateThreadMapKey(thread); |
2211 | 92 | 95 | ||
2212 | 93 | if (thread.type() != History::EventTypeText) { | 96 | if (thread.type() != History::EventTypeText) { |
2213 | 94 | continue; | 97 | continue; |
2215 | 95 | } else if (!History::Utils::shouldGroupAccount(thread.accountId())) { | 98 | } else if (!History::Utils::shouldGroupThread(thread)) { |
2216 | 96 | // never group non phone accounts | 99 | // never group non phone accounts |
2217 | 97 | mConversationsCache[threadKey] = History::Threads() << thread; | 100 | mConversationsCache[threadKey] = History::Threads() << thread; |
2218 | 98 | mConversationsCacheKeys[threadKey] = threadKey; | 101 | mConversationsCacheKeys[threadKey] = threadKey; |
2219 | @@ -119,6 +122,9 @@ | |||
2220 | 119 | const QString &conversationKey = it.key(); | 122 | const QString &conversationKey = it.key(); |
2221 | 120 | History::Threads groupedThreads = it.value(); | 123 | History::Threads groupedThreads = it.value(); |
2222 | 121 | Q_FOREACH(const History::Thread &groupedThread, groupedThreads) { | 124 | Q_FOREACH(const History::Thread &groupedThread, groupedThreads) { |
2223 | 125 | if (!History::Utils::shouldGroupThread(groupedThread) || thread.chatType() != groupedThread.chatType()) { | ||
2224 | 126 | continue; | ||
2225 | 127 | } | ||
2226 | 122 | found = History::Utils::compareNormalizedParticipants(thread.participants().identifiers(), groupedThread.participants().identifiers(), History::MatchPhoneNumber); | 128 | found = History::Utils::compareNormalizedParticipants(thread.participants().identifiers(), groupedThread.participants().identifiers(), History::MatchPhoneNumber); |
2227 | 123 | if (found) { | 129 | if (found) { |
2228 | 124 | Q_FOREACH(const History::Thread &groupedThread, groupedThreads) { | 130 | Q_FOREACH(const History::Thread &groupedThread, groupedThreads) { |
2229 | @@ -176,7 +182,7 @@ | |||
2230 | 176 | History::Thread thread = History::Thread::fromProperties(properties); | 182 | History::Thread thread = History::Thread::fromProperties(properties); |
2231 | 177 | QString threadKey = generateThreadMapKey(thread); | 183 | QString threadKey = generateThreadMapKey(thread); |
2232 | 178 | 184 | ||
2234 | 179 | if (thread.type() != History::EventTypeText || !History::Utils::shouldGroupAccount(thread.accountId())) { | 185 | if (thread.type() != History::EventTypeText || !History::Utils::shouldGroupThread(thread)) { |
2235 | 180 | mConversationsCache.remove(threadKey); | 186 | mConversationsCache.remove(threadKey); |
2236 | 181 | mConversationsCacheKeys.remove(threadKey); | 187 | mConversationsCacheKeys.remove(threadKey); |
2237 | 182 | return; | 188 | return; |
2238 | @@ -259,7 +265,7 @@ | |||
2239 | 259 | time.start(); | 265 | time.start(); |
2240 | 260 | qDebug() << "---- HistoryService: start generating cached content"; | 266 | qDebug() << "---- HistoryService: start generating cached content"; |
2241 | 261 | QSqlQuery query(SQLiteDatabase::instance()->database()); | 267 | QSqlQuery query(SQLiteDatabase::instance()->database()); |
2243 | 262 | if (!query.exec("SELECT DISTINCT accountId, normalizedId FROM thread_participants")) { | 268 | if (!query.exec("SELECT DISTINCT accountId, normalizedId, alias, state FROM thread_participants")) { |
2244 | 263 | qWarning() << "Failed to generate contact cache:" << query.lastError().text(); | 269 | qWarning() << "Failed to generate contact cache:" << query.lastError().text(); |
2245 | 264 | return; | 270 | return; |
2246 | 265 | } | 271 | } |
2247 | @@ -267,9 +273,14 @@ | |||
2248 | 267 | while (query.next()) { | 273 | while (query.next()) { |
2249 | 268 | QString accountId = query.value(0).toString(); | 274 | QString accountId = query.value(0).toString(); |
2250 | 269 | QString participantId = query.value(1).toString(); | 275 | QString participantId = query.value(1).toString(); |
2251 | 276 | QString alias = query.value(2).toString(); | ||
2252 | 277 | QVariantMap properties; | ||
2253 | 278 | if (!alias.isEmpty()) { | ||
2254 | 279 | properties[History::FieldAlias] = alias; | ||
2255 | 280 | } | ||
2256 | 270 | // we don't care about the results, as long as the contact data is present in the cache for | 281 | // we don't care about the results, as long as the contact data is present in the cache for |
2257 | 271 | // future usage. | 282 | // future usage. |
2259 | 272 | History::ContactMatcher::instance()->contactInfo(accountId, participantId, true); | 283 | History::ContactMatcher::instance()->contactInfo(accountId, participantId, true, properties); |
2260 | 273 | } | 284 | } |
2261 | 274 | 285 | ||
2262 | 275 | updateGroupedThreadsCache(); | 286 | updateGroupedThreadsCache(); |
2263 | @@ -295,6 +306,32 @@ | |||
2264 | 295 | return new SQLiteHistoryEventView(this, type, sort, filter); | 306 | return new SQLiteHistoryEventView(this, type, sort, filter); |
2265 | 296 | } | 307 | } |
2266 | 297 | 308 | ||
2267 | 309 | QVariantMap SQLiteHistoryPlugin::threadForProperties(const QString &accountId, | ||
2268 | 310 | History::EventType type, | ||
2269 | 311 | const QVariantMap &properties, | ||
2270 | 312 | History::MatchFlags matchFlags) | ||
2271 | 313 | { | ||
2272 | 314 | if (properties.isEmpty()) { | ||
2273 | 315 | return QVariantMap(); | ||
2274 | 316 | } | ||
2275 | 317 | |||
2276 | 318 | QSqlQuery query(SQLiteDatabase::instance()->database()); | ||
2277 | 319 | |||
2278 | 320 | History::ChatType chatType = (History::ChatType)properties[History::FieldChatType].toUInt(); | ||
2279 | 321 | |||
2280 | 322 | if (chatType == History::ChatTypeRoom) { | ||
2281 | 323 | QString threadId = properties[History::FieldThreadId].toString(); | ||
2282 | 324 | if (threadId.isEmpty()) { | ||
2283 | 325 | return QVariantMap(); | ||
2284 | 326 | } | ||
2285 | 327 | return getSingleThread(type, accountId, threadId); | ||
2286 | 328 | } | ||
2287 | 329 | |||
2288 | 330 | History::Participants participants = History::Participants::fromVariant(properties[History::FieldParticipantIds]); | ||
2289 | 331 | // if chatType != Room, then we select the thread based on the participant list. | ||
2290 | 332 | return threadForParticipants(accountId, type, participants.identifiers(), matchFlags); | ||
2291 | 333 | } | ||
2292 | 334 | |||
2293 | 298 | QVariantMap SQLiteHistoryPlugin::threadForParticipants(const QString &accountId, | 335 | QVariantMap SQLiteHistoryPlugin::threadForParticipants(const QString &accountId, |
2294 | 299 | History::EventType type, | 336 | History::EventType type, |
2295 | 300 | const QStringList &participants, | 337 | const QStringList &participants, |
2296 | @@ -310,7 +347,9 @@ | |||
2297 | 310 | // select all the threads the first participant is listed in, and from that list | 347 | // select all the threads the first participant is listed in, and from that list |
2298 | 311 | // check if any of the threads has all the other participants listed | 348 | // check if any of the threads has all the other participants listed |
2299 | 312 | // FIXME: find a better way to do this | 349 | // FIXME: find a better way to do this |
2301 | 313 | QString queryString("SELECT threadId FROM thread_participants WHERE %1 AND type=:type AND accountId=:accountId"); | 350 | QString queryString("SELECT threadId FROM thread_participants WHERE %1 AND type=:type AND accountId=:accountId " |
2302 | 351 | "AND (SELECT chatType FROM threads WHERE threads.threadId=thread_participants.threadId AND " | ||
2303 | 352 | " threads.type=thread_participants.type)!=:chatType"); | ||
2304 | 314 | 353 | ||
2305 | 315 | // FIXME: for now we just compare differently when using MatchPhoneNumber | 354 | // FIXME: for now we just compare differently when using MatchPhoneNumber |
2306 | 316 | QString firstParticipant = participants.first(); | 355 | QString firstParticipant = participants.first(); |
2307 | @@ -324,6 +363,9 @@ | |||
2308 | 324 | query.bindValue(":participantId", firstParticipant); | 363 | query.bindValue(":participantId", firstParticipant); |
2309 | 325 | query.bindValue(":type", type); | 364 | query.bindValue(":type", type); |
2310 | 326 | query.bindValue(":accountId", accountId); | 365 | query.bindValue(":accountId", accountId); |
2311 | 366 | // we don't want to accidentally return a chat room for a multi-recipient conversation | ||
2312 | 367 | query.bindValue(":chatType", (int)History::ChatTypeRoom); | ||
2313 | 368 | |||
2314 | 327 | if (!query.exec()) { | 369 | if (!query.exec()) { |
2315 | 328 | qCritical() << "Error:" << query.lastError() << query.lastQuery(); | 370 | qCritical() << "Error:" << query.lastError() << query.lastQuery(); |
2316 | 329 | return QVariantMap(); | 371 | return QVariantMap(); |
2317 | @@ -469,58 +511,345 @@ | |||
2318 | 469 | return result; | 511 | return result; |
2319 | 470 | } | 512 | } |
2320 | 471 | 513 | ||
2323 | 472 | // Writer | 514 | bool SQLiteHistoryPlugin::updateRoomParticipants(const QString &accountId, const QString &threadId, History::EventType type, const QVariantList &participants) |
2324 | 473 | QVariantMap SQLiteHistoryPlugin::createThreadForParticipants(const QString &accountId, History::EventType type, const QStringList &participants) | 515 | { |
2325 | 516 | QSqlQuery query(SQLiteDatabase::instance()->database()); | ||
2326 | 517 | if (accountId.isEmpty() || threadId.isEmpty()) { | ||
2327 | 518 | return false; | ||
2328 | 519 | } | ||
2329 | 520 | |||
2330 | 521 | SQLiteDatabase::instance()->beginTransation(); | ||
2331 | 522 | QString deleteString("DELETE FROM thread_participants WHERE threadId=:threadId AND type=:type AND accountId=:accountId"); | ||
2332 | 523 | query.prepare(deleteString); | ||
2333 | 524 | query.bindValue(":accountId", accountId); | ||
2334 | 525 | query.bindValue(":threadId", threadId); | ||
2335 | 526 | query.bindValue(":type", type); | ||
2336 | 527 | if (!query.exec()) { | ||
2337 | 528 | qCritical() << "Error removing old participants:" << query.lastError() << query.lastQuery(); | ||
2338 | 529 | SQLiteDatabase::instance()->rollbackTransaction(); | ||
2339 | 530 | return false; | ||
2340 | 531 | } | ||
2341 | 532 | |||
2342 | 533 | // and insert the participants | ||
2343 | 534 | Q_FOREACH(const QVariant &participantVariant, participants) { | ||
2344 | 535 | QVariantMap participant = participantVariant.toMap(); | ||
2345 | 536 | query.prepare("INSERT INTO thread_participants (accountId, threadId, type, participantId, normalizedId, alias, state, roles)" | ||
2346 | 537 | "VALUES (:accountId, :threadId, :type, :participantId, :normalizedId, :alias, :state, :roles)"); | ||
2347 | 538 | query.bindValue(":accountId", accountId); | ||
2348 | 539 | query.bindValue(":threadId", threadId); | ||
2349 | 540 | query.bindValue(":type", type); | ||
2350 | 541 | query.bindValue(":participantId", participant["identifier"].toString()); | ||
2351 | 542 | query.bindValue(":normalizedId", participant["identifier"].toString()); | ||
2352 | 543 | query.bindValue(":alias", participant["alias"].toString()); | ||
2353 | 544 | query.bindValue(":state", participant["state"].toUInt()); | ||
2354 | 545 | query.bindValue(":roles", participant["roles"].toUInt()); | ||
2355 | 546 | if (!query.exec()) { | ||
2356 | 547 | qCritical() << "Error:" << query.lastError() << query.lastQuery(); | ||
2357 | 548 | SQLiteDatabase::instance()->rollbackTransaction(); | ||
2358 | 549 | return false; | ||
2359 | 550 | } | ||
2360 | 551 | } | ||
2361 | 552 | |||
2362 | 553 | if (!SQLiteDatabase::instance()->finishTransaction()) { | ||
2363 | 554 | qCritical() << "Failed to commit the transaction."; | ||
2364 | 555 | return false; | ||
2365 | 556 | } | ||
2366 | 557 | |||
2367 | 558 | QVariantMap existingThread = getSingleThread(type, | ||
2368 | 559 | accountId, | ||
2369 | 560 | threadId, | ||
2370 | 561 | QVariantMap()); | ||
2371 | 562 | |||
2372 | 563 | if (!existingThread.isEmpty()) { | ||
2373 | 564 | addThreadsToCache(QList<QVariantMap>() << existingThread); | ||
2374 | 565 | } | ||
2375 | 566 | |||
2376 | 567 | return true; | ||
2377 | 568 | } | ||
2378 | 569 | |||
2379 | 570 | bool SQLiteHistoryPlugin::updateRoomParticipantsRoles(const QString &accountId, const QString &threadId, History::EventType type, const QVariantMap &participantsRoles) | ||
2380 | 571 | { | ||
2381 | 572 | QSqlQuery query(SQLiteDatabase::instance()->database()); | ||
2382 | 573 | if (accountId.isEmpty() || threadId.isEmpty()) { | ||
2383 | 574 | return false; | ||
2384 | 575 | } | ||
2385 | 576 | |||
2386 | 577 | SQLiteDatabase::instance()->beginTransation(); | ||
2387 | 578 | Q_FOREACH(const QString &participantId, participantsRoles.keys()) { | ||
2388 | 579 | query.prepare("UPDATE thread_participants SET roles=:roles WHERE accountId=:accountId AND threadId=:threadId AND type=:type AND participantId=:participantId"); | ||
2389 | 580 | query.bindValue(":roles", participantsRoles.value(participantId).toUInt()); | ||
2390 | 581 | query.bindValue(":accountId", accountId); | ||
2391 | 582 | query.bindValue(":threadId", threadId); | ||
2392 | 583 | query.bindValue(":type", type); | ||
2393 | 584 | query.bindValue(":participantId", participantId); | ||
2394 | 585 | if (!query.exec()) { | ||
2395 | 586 | qCritical() << "Error:" << query.lastError() << query.lastQuery(); | ||
2396 | 587 | SQLiteDatabase::instance()->rollbackTransaction(); | ||
2397 | 588 | return false; | ||
2398 | 589 | } | ||
2399 | 590 | } | ||
2400 | 591 | |||
2401 | 592 | if (!SQLiteDatabase::instance()->finishTransaction()) { | ||
2402 | 593 | qCritical() << "Failed to commit the transaction."; | ||
2403 | 594 | return false; | ||
2404 | 595 | } | ||
2405 | 596 | |||
2406 | 597 | QVariantMap existingThread = getSingleThread(type, | ||
2407 | 598 | accountId, | ||
2408 | 599 | threadId, | ||
2409 | 600 | QVariantMap()); | ||
2410 | 601 | |||
2411 | 602 | if (!existingThread.isEmpty()) { | ||
2412 | 603 | addThreadsToCache(QList<QVariantMap>() << existingThread); | ||
2413 | 604 | } | ||
2414 | 605 | |||
2415 | 606 | return true; | ||
2416 | 607 | } | ||
2417 | 608 | |||
2418 | 609 | bool SQLiteHistoryPlugin::updateRoomInfo(const QString &accountId, const QString &threadId, History::EventType type, const QVariantMap &properties, const QStringList &invalidated) | ||
2419 | 610 | { | ||
2420 | 611 | QSqlQuery query(SQLiteDatabase::instance()->database()); | ||
2421 | 612 | |||
2422 | 613 | if (threadId.isEmpty() || accountId.isEmpty()) { | ||
2423 | 614 | return false; | ||
2424 | 615 | } | ||
2425 | 616 | |||
2426 | 617 | SQLiteDatabase::instance()->beginTransation(); | ||
2427 | 618 | |||
2428 | 619 | QDateTime creationTimestamp = QDateTime::fromTime_t(properties["CreationTimestamp"].toUInt()); | ||
2429 | 620 | QDateTime timestamp = QDateTime::fromTime_t(properties["Timestamp"].toUInt()); | ||
2430 | 621 | |||
2431 | 622 | QVariantMap propertyMapping; | ||
2432 | 623 | propertyMapping["RoomName"] = "roomName"; | ||
2433 | 624 | propertyMapping["Server"] = "server"; | ||
2434 | 625 | propertyMapping["Creator"] = "creator"; | ||
2435 | 626 | propertyMapping["CreationTimestamp"] = "creationTimestamp"; | ||
2436 | 627 | propertyMapping["Anonymous"] = "anonymous"; | ||
2437 | 628 | propertyMapping["InviteOnly"] = "inviteOnly"; | ||
2438 | 629 | propertyMapping["Limit"] = "participantLimit"; | ||
2439 | 630 | propertyMapping["Moderated"] = "moderated"; | ||
2440 | 631 | propertyMapping["Title"] = "title"; | ||
2441 | 632 | propertyMapping["Description"] = "description"; | ||
2442 | 633 | propertyMapping["Persistent"] = "persistent"; | ||
2443 | 634 | propertyMapping["Private"] = "private"; | ||
2444 | 635 | propertyMapping["PasswordProtected"] = "passwordProtected"; | ||
2445 | 636 | propertyMapping["Password"] = "password"; | ||
2446 | 637 | propertyMapping["PasswordHint"] = "passwordHint"; | ||
2447 | 638 | propertyMapping["CanUpdateConfiguration"] = "canUpdateConfiguration"; | ||
2448 | 639 | propertyMapping["Subject"] = "subject"; | ||
2449 | 640 | propertyMapping["Actor"] = "actor"; | ||
2450 | 641 | propertyMapping["Timestamp"] = "timestamp"; | ||
2451 | 642 | propertyMapping["Joined"] = "joined"; | ||
2452 | 643 | propertyMapping["SelfRoles"] = "selfRoles"; | ||
2453 | 644 | |||
2454 | 645 | QStringList changedPropListValues; | ||
2455 | 646 | // populate sql query | ||
2456 | 647 | Q_FOREACH (const QString &key, properties.keys()) { | ||
2457 | 648 | if (propertyMapping.contains(key)) { | ||
2458 | 649 | QString prop = propertyMapping[key].toString(); | ||
2459 | 650 | changedPropListValues << QString(prop+"=:"+ prop); | ||
2460 | 651 | } | ||
2461 | 652 | } | ||
2462 | 653 | if (changedPropListValues.isEmpty()) { | ||
2463 | 654 | return false; | ||
2464 | 655 | } | ||
2465 | 656 | |||
2466 | 657 | query.prepare("UPDATE chat_room_info SET "+ changedPropListValues.join(", ")+" WHERE accountId=:accountId AND threadId=:threadId AND type=:type"); | ||
2467 | 658 | query.bindValue(":accountId", accountId); | ||
2468 | 659 | query.bindValue(":threadId", threadId); | ||
2469 | 660 | query.bindValue(":type", (int) type); | ||
2470 | 661 | query.bindValue(":roomName", properties["RoomName"].toString()); | ||
2471 | 662 | query.bindValue(":server", properties["Server"].toString()); | ||
2472 | 663 | query.bindValue(":creator", properties["Creator"].toString()); | ||
2473 | 664 | query.bindValue(":creationTimestamp", creationTimestamp.toUTC().toString(timestampFormat)); | ||
2474 | 665 | query.bindValue(":anonymous", properties["Anonymous"].toBool()); | ||
2475 | 666 | query.bindValue(":inviteOnly", properties["InviteOnly"].toBool()); | ||
2476 | 667 | query.bindValue(":participantLimit", properties["Limit"].toInt()); | ||
2477 | 668 | query.bindValue(":moderated", properties["Moderated"].toBool()); | ||
2478 | 669 | query.bindValue(":title", properties["Title"].toString()); | ||
2479 | 670 | query.bindValue(":description", properties["Description"].toString()); | ||
2480 | 671 | query.bindValue(":persistent", properties["Persistent"].toBool()); | ||
2481 | 672 | query.bindValue(":private", properties["Private"].toBool()); | ||
2482 | 673 | query.bindValue(":passwordProtected", properties["PasswordProtected"].toBool()); | ||
2483 | 674 | query.bindValue(":password", properties["Password"].toString()); | ||
2484 | 675 | query.bindValue(":passwordHint", properties["PasswordHint"].toString()); | ||
2485 | 676 | query.bindValue(":canUpdateConfiguration", properties["CanUpdateConfiguration"].toBool()); | ||
2486 | 677 | query.bindValue(":subject", properties["Subject"].toString()); | ||
2487 | 678 | query.bindValue(":actor", properties["Actor"].toString()); | ||
2488 | 679 | query.bindValue(":timestamp", timestamp.toUTC().toString(timestampFormat)); | ||
2489 | 680 | query.bindValue(":joined", properties["Joined"].toBool()); | ||
2490 | 681 | query.bindValue(":selfRoles", properties["SelfRoles"].toInt()); | ||
2491 | 682 | |||
2492 | 683 | if (!query.exec()) { | ||
2493 | 684 | qCritical() << "Error:" << query.lastError() << query.lastQuery(); | ||
2494 | 685 | SQLiteDatabase::instance()->rollbackTransaction(); | ||
2495 | 686 | return false; | ||
2496 | 687 | } | ||
2497 | 688 | |||
2498 | 689 | if (!SQLiteDatabase::instance()->finishTransaction()) { | ||
2499 | 690 | qCritical() << "Failed to commit the transaction."; | ||
2500 | 691 | return false; | ||
2501 | 692 | } | ||
2502 | 693 | |||
2503 | 694 | QVariantMap existingThread = getSingleThread(type, | ||
2504 | 695 | accountId, | ||
2505 | 696 | threadId, | ||
2506 | 697 | QVariantMap()); | ||
2507 | 698 | |||
2508 | 699 | if (!existingThread.isEmpty()) { | ||
2509 | 700 | addThreadsToCache(QList<QVariantMap>() << existingThread); | ||
2510 | 701 | } | ||
2511 | 702 | |||
2512 | 703 | return true; | ||
2513 | 704 | } | ||
2514 | 705 | |||
2515 | 706 | QVariantMap SQLiteHistoryPlugin::createThreadForProperties(const QString &accountId, History::EventType type, const QVariantMap &properties) | ||
2516 | 474 | { | 707 | { |
2517 | 475 | // WARNING: this function does NOT test to check if the thread is already created, you should check using HistoryReader::threadForParticipants() | 708 | // WARNING: this function does NOT test to check if the thread is already created, you should check using HistoryReader::threadForParticipants() |
2518 | 476 | 709 | ||
2519 | 477 | QVariantMap thread; | 710 | QVariantMap thread; |
2520 | 711 | History::Participants participants = History::Participants::fromVariant(properties[History::FieldParticipantIds]); | ||
2521 | 478 | 712 | ||
2522 | 479 | // Create a new thread | 713 | // Create a new thread |
2523 | 480 | // FIXME: define what the threadId will be | 714 | // FIXME: define what the threadId will be |
2525 | 481 | QString threadId = participants.join("%"); | 715 | QString threadId; |
2526 | 716 | History::ChatType chatType = (History::ChatType)properties[History::FieldChatType].toInt(); | ||
2527 | 717 | QVariantMap chatRoomInfo; | ||
2528 | 718 | |||
2529 | 719 | SQLiteDatabase::instance()->beginTransation(); | ||
2530 | 720 | |||
2531 | 721 | if (chatType == History::ChatTypeRoom) { | ||
2532 | 722 | threadId = properties[History::FieldThreadId].toString(); | ||
2533 | 723 | // we cannot save chat room without threadId | ||
2534 | 724 | if (accountId.isEmpty() || threadId.isEmpty()) { | ||
2535 | 725 | SQLiteDatabase::instance()->rollbackTransaction(); | ||
2536 | 726 | return thread; | ||
2537 | 727 | } | ||
2538 | 728 | chatRoomInfo = properties[History::FieldChatRoomInfo].toMap(); | ||
2539 | 729 | QSqlQuery query(SQLiteDatabase::instance()->database()); | ||
2540 | 730 | |||
2541 | 731 | QDateTime creationTimestamp = QDateTime::fromTime_t(chatRoomInfo["CreationTimestamp"].toUInt()); | ||
2542 | 732 | QDateTime timestamp = QDateTime::fromTime_t(chatRoomInfo["Timestamp"].toUInt()); | ||
2543 | 733 | |||
2544 | 734 | query.prepare("INSERT INTO chat_room_info (accountId, threadId, type, roomName, server, creator, creationTimestamp, anonymous, inviteOnly, participantLimit, moderated, title, description, persistent, private, passwordProtected, password, passwordHint, canUpdateConfiguration, subject, actor, timestamp, joined, selfRoles) " | ||
2545 | 735 | "VALUES (:accountId, :threadId, :type, :roomName, :server, :creator, :creationTimestamp, :anonymous, :inviteOnly, :participantLimit, :moderated, :title, :description, :persistent, :private, :passwordProtected, :password, :passwordHint, :canUpdateConfiguration, :subject, :actor, :timestamp, :joined, :selfRoles)"); | ||
2546 | 736 | query.bindValue(":accountId", accountId); | ||
2547 | 737 | query.bindValue(":threadId", threadId); | ||
2548 | 738 | query.bindValue(":type", (int) type); | ||
2549 | 739 | query.bindValue(":roomName", chatRoomInfo["RoomName"].toString()); | ||
2550 | 740 | query.bindValue(":server", chatRoomInfo["Server"].toString()); | ||
2551 | 741 | query.bindValue(":creator", chatRoomInfo["Creator"].toString()); | ||
2552 | 742 | query.bindValue(":creationTimestamp", creationTimestamp.toUTC().toString(timestampFormat)); | ||
2553 | 743 | query.bindValue(":anonymous", chatRoomInfo["Anonymous"].toBool()); | ||
2554 | 744 | query.bindValue(":inviteOnly", chatRoomInfo["InviteOnly"].toBool()); | ||
2555 | 745 | query.bindValue(":participantLimit", chatRoomInfo["Limit"].toInt()); | ||
2556 | 746 | query.bindValue(":moderated", chatRoomInfo["Moderated"].toBool()); | ||
2557 | 747 | query.bindValue(":title", chatRoomInfo["Title"].toString()); | ||
2558 | 748 | query.bindValue(":description", chatRoomInfo["Description"].toString()); | ||
2559 | 749 | query.bindValue(":persistent", chatRoomInfo["Persistent"].toBool()); | ||
2560 | 750 | query.bindValue(":private", chatRoomInfo["Private"].toBool()); | ||
2561 | 751 | query.bindValue(":passwordProtected", chatRoomInfo["PasswordProtected"].toBool()); | ||
2562 | 752 | query.bindValue(":password", chatRoomInfo["Password"].toString()); | ||
2563 | 753 | query.bindValue(":passwordHint", chatRoomInfo["PasswordHint"].toString()); | ||
2564 | 754 | query.bindValue(":canUpdateConfiguration", chatRoomInfo["CanUpdateConfiguration"].toBool()); | ||
2565 | 755 | query.bindValue(":subject", chatRoomInfo["Subject"].toString()); | ||
2566 | 756 | query.bindValue(":actor", chatRoomInfo["Actor"].toString()); | ||
2567 | 757 | query.bindValue(":timestamp", timestamp.toUTC().toString(timestampFormat)); | ||
2568 | 758 | query.bindValue(":joined", chatRoomInfo["Joined"].toBool()); | ||
2569 | 759 | query.bindValue(":selfRoles", chatRoomInfo["SelfRoles"].toInt()); | ||
2570 | 760 | |||
2571 | 761 | if (!query.exec()) { | ||
2572 | 762 | qCritical() << "Error:" << query.lastError() << query.lastQuery(); | ||
2573 | 763 | SQLiteDatabase::instance()->rollbackTransaction(); | ||
2574 | 764 | return QVariantMap(); | ||
2575 | 765 | } | ||
2576 | 766 | for (QVariantMap::iterator iter = chatRoomInfo.begin(); iter != chatRoomInfo.end();) { | ||
2577 | 767 | if (!iter.value().isValid()) { | ||
2578 | 768 | iter = chatRoomInfo.erase(iter); | ||
2579 | 769 | } else { | ||
2580 | 770 | iter++; | ||
2581 | 771 | } | ||
2582 | 772 | } | ||
2583 | 773 | thread[History::FieldChatRoomInfo] = chatRoomInfo; | ||
2584 | 774 | } else if (chatType == History::ChatTypeContact) { | ||
2585 | 775 | threadId = participants.identifiers().join("%"); | ||
2586 | 776 | } else { | ||
2587 | 777 | threadId = QString("broadcast:%1").arg(QString(QCryptographicHash::hash(participants.identifiers().join(";").toLocal8Bit(),QCryptographicHash::Md5).toHex()));; | ||
2588 | 778 | } | ||
2589 | 482 | 779 | ||
2590 | 483 | QSqlQuery query(SQLiteDatabase::instance()->database()); | 780 | QSqlQuery query(SQLiteDatabase::instance()->database()); |
2593 | 484 | query.prepare("INSERT INTO threads (accountId, threadId, type, count, unreadCount)" | 781 | query.prepare("INSERT INTO threads (accountId, threadId, type, count, unreadCount, chatType, lastEventTimestamp)" |
2594 | 485 | "VALUES (:accountId, :threadId, :type, :count, :unreadCount)"); | 782 | "VALUES (:accountId, :threadId, :type, :count, :unreadCount, :chatType, :lastEventTimestamp)"); |
2595 | 486 | query.bindValue(":accountId", accountId); | 783 | query.bindValue(":accountId", accountId); |
2596 | 487 | query.bindValue(":threadId", threadId); | 784 | query.bindValue(":threadId", threadId); |
2597 | 488 | query.bindValue(":type", (int) type); | 785 | query.bindValue(":type", (int) type); |
2598 | 489 | query.bindValue(":count", 0); | 786 | query.bindValue(":count", 0); |
2599 | 490 | query.bindValue(":unreadCount", 0); | 787 | query.bindValue(":unreadCount", 0); |
2600 | 788 | query.bindValue(":chatType", (int) chatType); | ||
2601 | 789 | // make sure threads are created with an up-to-date timestamp | ||
2602 | 790 | query.bindValue(":lastEventTimestamp", QDateTime::currentDateTimeUtc().toString(timestampFormat)); | ||
2603 | 491 | if (!query.exec()) { | 791 | if (!query.exec()) { |
2604 | 492 | qCritical() << "Error:" << query.lastError() << query.lastQuery(); | 792 | qCritical() << "Error:" << query.lastError() << query.lastQuery(); |
2605 | 793 | SQLiteDatabase::instance()->rollbackTransaction(); | ||
2606 | 493 | return QVariantMap(); | 794 | return QVariantMap(); |
2607 | 494 | } | 795 | } |
2608 | 495 | 796 | ||
2609 | 496 | // and insert the participants | 797 | // and insert the participants |
2613 | 497 | Q_FOREACH(const QString &participant, participants) { | 798 | Q_FOREACH(const History::Participant &participant, participants) { |
2614 | 498 | query.prepare("INSERT INTO thread_participants (accountId, threadId, type, participantId, normalizedId)" | 799 | query.prepare("INSERT INTO thread_participants (accountId, threadId, type, participantId, normalizedId, alias, state, roles)" |
2615 | 499 | "VALUES (:accountId, :threadId, :type, :participantId, :normalizedId)"); | 800 | "VALUES (:accountId, :threadId, :type, :participantId, :normalizedId, :alias, :state, :roles)"); |
2616 | 500 | query.bindValue(":accountId", accountId); | 801 | query.bindValue(":accountId", accountId); |
2617 | 501 | query.bindValue(":threadId", threadId); | 802 | query.bindValue(":threadId", threadId); |
2618 | 502 | query.bindValue(":type", type); | 803 | query.bindValue(":type", type); |
2621 | 503 | query.bindValue(":participantId", participant); | 804 | query.bindValue(":participantId", participant.identifier()); |
2622 | 504 | query.bindValue(":normalizedId", History::Utils::normalizeId(accountId, participant)); | 805 | query.bindValue(":normalizedId", History::Utils::normalizeId(accountId, participant.identifier())); |
2623 | 806 | query.bindValue(":alias", participant.alias()); | ||
2624 | 807 | query.bindValue(":state", participant.state()); | ||
2625 | 808 | query.bindValue(":roles", participant.roles()); | ||
2626 | 505 | if (!query.exec()) { | 809 | if (!query.exec()) { |
2627 | 506 | qCritical() << "Error:" << query.lastError() << query.lastQuery(); | 810 | qCritical() << "Error:" << query.lastError() << query.lastQuery(); |
2628 | 811 | SQLiteDatabase::instance()->rollbackTransaction(); | ||
2629 | 507 | return QVariantMap(); | 812 | return QVariantMap(); |
2630 | 508 | } | 813 | } |
2631 | 509 | } | 814 | } |
2632 | 510 | 815 | ||
2633 | 816 | if (!SQLiteDatabase::instance()->finishTransaction()) { | ||
2634 | 817 | qCritical() << "Failed to commit the transaction."; | ||
2635 | 818 | return QVariantMap(); | ||
2636 | 819 | } | ||
2637 | 820 | |||
2638 | 511 | // and finally create the thread | 821 | // and finally create the thread |
2639 | 512 | thread[History::FieldAccountId] = accountId; | 822 | thread[History::FieldAccountId] = accountId; |
2640 | 513 | thread[History::FieldThreadId] = threadId; | 823 | thread[History::FieldThreadId] = threadId; |
2641 | 514 | thread[History::FieldType] = (int) type; | 824 | thread[History::FieldType] = (int) type; |
2643 | 515 | thread[History::FieldParticipants] = History::ContactMatcher::instance()->contactInfo(accountId, participants, true); | 825 | QVariantList contactList; |
2644 | 826 | QVariantList contactInfo = History::ContactMatcher::instance()->contactInfo(accountId, participants.identifiers(), true); | ||
2645 | 827 | for (int i = 0; i < participants.count(); ++i) { | ||
2646 | 828 | QVariantMap map = contactInfo[i].toMap(); | ||
2647 | 829 | History::Participant participant = participants[i]; | ||
2648 | 830 | map["state"] = participant.state(); | ||
2649 | 831 | map["roles"] = participant.roles(); | ||
2650 | 832 | contactList << map; | ||
2651 | 833 | } | ||
2652 | 834 | thread[History::FieldParticipants] = contactList; | ||
2653 | 516 | thread[History::FieldCount] = 0; | 835 | thread[History::FieldCount] = 0; |
2654 | 517 | thread[History::FieldUnreadCount] = 0; | 836 | thread[History::FieldUnreadCount] = 0; |
2655 | 837 | thread[History::FieldChatType] = (int)chatType; | ||
2656 | 518 | 838 | ||
2657 | 519 | addThreadsToCache(QList<QVariantMap>() << thread); | 839 | addThreadsToCache(QList<QVariantMap>() << thread); |
2658 | 520 | 840 | ||
2659 | 521 | return thread; | 841 | return thread; |
2660 | 522 | } | 842 | } |
2661 | 523 | 843 | ||
2662 | 844 | // Writer | ||
2663 | 845 | QVariantMap SQLiteHistoryPlugin::createThreadForParticipants(const QString &accountId, History::EventType type, const QStringList &participants) | ||
2664 | 846 | { | ||
2665 | 847 | QVariantMap properties; | ||
2666 | 848 | properties[History::FieldParticipantIds] = participants; | ||
2667 | 849 | properties[History::FieldChatType] = participants.size() != 1 ? History::ChatTypeNone : History::ChatTypeContact; | ||
2668 | 850 | return createThreadForProperties(accountId, type, properties); | ||
2669 | 851 | } | ||
2670 | 852 | |||
2671 | 524 | bool SQLiteHistoryPlugin::removeThread(const QVariantMap &thread) | 853 | bool SQLiteHistoryPlugin::removeThread(const QVariantMap &thread) |
2672 | 525 | { | 854 | { |
2673 | 526 | QSqlQuery query(SQLiteDatabase::instance()->database()); | 855 | QSqlQuery query(SQLiteDatabase::instance()->database()); |
2674 | @@ -550,16 +879,18 @@ | |||
2675 | 550 | event[History::FieldThreadId].toString(), | 879 | event[History::FieldThreadId].toString(), |
2676 | 551 | event[History::FieldEventId].toString()); | 880 | event[History::FieldEventId].toString()); |
2677 | 552 | 881 | ||
2678 | 882 | SQLiteDatabase::instance()->beginTransation(); | ||
2679 | 883 | |||
2680 | 553 | History::EventWriteResult result; | 884 | History::EventWriteResult result; |
2681 | 554 | if (existingEvent.isEmpty()) { | 885 | if (existingEvent.isEmpty()) { |
2682 | 555 | // create new | 886 | // create new |
2685 | 556 | query.prepare("INSERT INTO text_events (accountId, threadId, eventId, senderId, timestamp, newEvent, message, messageType, messageStatus, readTimestamp, subject) " | 887 | query.prepare("INSERT INTO text_events (accountId, threadId, eventId, senderId, timestamp, newEvent, message, messageType, messageStatus, readTimestamp, subject, informationType)" |
2686 | 557 | "VALUES (:accountId, :threadId, :eventId, :senderId, :timestamp, :newEvent, :message, :messageType, :messageStatus, :readTimestamp, :subject)"); | 888 | "VALUES (:accountId, :threadId, :eventId, :senderId, :timestamp, :newEvent, :message, :messageType, :messageStatus, :readTimestamp, :subject, :informationType)"); |
2687 | 558 | result = History::EventWriteCreated; | 889 | result = History::EventWriteCreated; |
2688 | 559 | } else { | 890 | } else { |
2689 | 560 | // update existing event | 891 | // update existing event |
2692 | 561 | query.prepare("UPDATE text_events SET senderId=:senderId, timestamp=:timestamp, newEvent=:newEvent, message=:message, messageType=:messageType," | 892 | query.prepare("UPDATE text_events SET senderId=:senderId, timestamp=:timestamp, newEvent=:newEvent, message=:message, messageType=:messageType, informationType=:informationType, " |
2693 | 562 | "messageStatus=:messageStatus, readTimestamp=:readTimestamp, subject=:subject WHERE accountId=:accountId AND threadId=:threadId AND eventId=:eventId"); | 893 | "messageStatus=:messageStatus, readTimestamp=:readTimestamp, subject=:subject, informationType=:informationType WHERE accountId=:accountId AND threadId=:threadId AND eventId=:eventId"); |
2694 | 563 | result = History::EventWriteModified; | 894 | result = History::EventWriteModified; |
2695 | 564 | } | 895 | } |
2696 | 565 | 896 | ||
2697 | @@ -574,9 +905,11 @@ | |||
2698 | 574 | query.bindValue(":messageStatus", event[History::FieldMessageStatus]); | 905 | query.bindValue(":messageStatus", event[History::FieldMessageStatus]); |
2699 | 575 | query.bindValue(":readTimestamp", event[History::FieldReadTimestamp].toDateTime().toUTC()); | 906 | query.bindValue(":readTimestamp", event[History::FieldReadTimestamp].toDateTime().toUTC()); |
2700 | 576 | query.bindValue(":subject", event[History::FieldSubject].toString()); | 907 | query.bindValue(":subject", event[History::FieldSubject].toString()); |
2701 | 908 | query.bindValue(":informationType", event[History::FieldInformationType].toInt()); | ||
2702 | 577 | 909 | ||
2703 | 578 | if (!query.exec()) { | 910 | if (!query.exec()) { |
2704 | 579 | qCritical() << "Failed to save the text event: Error:" << query.lastError() << query.lastQuery(); | 911 | qCritical() << "Failed to save the text event: Error:" << query.lastError() << query.lastQuery(); |
2705 | 912 | SQLiteDatabase::instance()->rollbackTransaction(); | ||
2706 | 580 | return History::EventWriteError; | 913 | return History::EventWriteError; |
2707 | 581 | } | 914 | } |
2708 | 582 | 915 | ||
2709 | @@ -592,6 +925,7 @@ | |||
2710 | 592 | query.bindValue(":eventId", event[History::FieldEventId]); | 925 | query.bindValue(":eventId", event[History::FieldEventId]); |
2711 | 593 | if (!query.exec()) { | 926 | if (!query.exec()) { |
2712 | 594 | qCritical() << "Could not erase previous attachments. Error:" << query.lastError() << query.lastQuery(); | 927 | qCritical() << "Could not erase previous attachments. Error:" << query.lastError() << query.lastQuery(); |
2713 | 928 | SQLiteDatabase::instance()->rollbackTransaction(); | ||
2714 | 595 | return History::EventWriteError; | 929 | return History::EventWriteError; |
2715 | 596 | } | 930 | } |
2716 | 597 | } | 931 | } |
2717 | @@ -608,11 +942,17 @@ | |||
2718 | 608 | query.bindValue(":status", attachment[History::FieldStatus]); | 942 | query.bindValue(":status", attachment[History::FieldStatus]); |
2719 | 609 | if (!query.exec()) { | 943 | if (!query.exec()) { |
2720 | 610 | qCritical() << "Failed to save attachment to database" << query.lastError() << attachment; | 944 | qCritical() << "Failed to save attachment to database" << query.lastError() << attachment; |
2721 | 945 | SQLiteDatabase::instance()->rollbackTransaction(); | ||
2722 | 611 | return History::EventWriteError; | 946 | return History::EventWriteError; |
2723 | 612 | } | 947 | } |
2724 | 613 | } | 948 | } |
2725 | 614 | } | 949 | } |
2726 | 615 | 950 | ||
2727 | 951 | if (!SQLiteDatabase::instance()->finishTransaction()) { | ||
2728 | 952 | qCritical() << "Failed to commit transaction."; | ||
2729 | 953 | return History::EventWriteError; | ||
2730 | 954 | } | ||
2731 | 955 | |||
2732 | 616 | if (result == History::EventWriteModified || result == History::EventWriteCreated) { | 956 | if (result == History::EventWriteModified || result == History::EventWriteCreated) { |
2733 | 617 | QVariantMap existingThread = getSingleThread((History::EventType) event[History::FieldType].toInt(), | 957 | QVariantMap existingThread = getSingleThread((History::EventType) event[History::FieldType].toInt(), |
2734 | 618 | event[History::FieldAccountId].toString(), | 958 | event[History::FieldAccountId].toString(), |
2735 | @@ -750,7 +1090,8 @@ | |||
2736 | 750 | << "threads.threadId" | 1090 | << "threads.threadId" |
2737 | 751 | << "threads.lastEventId" | 1091 | << "threads.lastEventId" |
2738 | 752 | << "threads.count" | 1092 | << "threads.count" |
2740 | 753 | << "threads.unreadCount"; | 1093 | << "threads.unreadCount" |
2741 | 1094 | << "threads.lastEventTimestamp"; | ||
2742 | 754 | 1095 | ||
2743 | 755 | // get the participants in the query already | 1096 | // get the participants in the query already |
2744 | 756 | fields << "(SELECT group_concat(thread_participants.participantId, \"|,|\") " | 1097 | fields << "(SELECT group_concat(thread_participants.participantId, \"|,|\") " |
2745 | @@ -758,13 +1099,23 @@ | |||
2746 | 758 | "AND thread_participants.threadId=threads.threadId " | 1099 | "AND thread_participants.threadId=threads.threadId " |
2747 | 759 | "AND thread_participants.type=threads.type GROUP BY accountId,threadId,type) as participants"; | 1100 | "AND thread_participants.type=threads.type GROUP BY accountId,threadId,type) as participants"; |
2748 | 760 | 1101 | ||
2749 | 1102 | fields << "(SELECT group_concat(thread_participants.state, \"|,|\") " | ||
2750 | 1103 | "FROM thread_participants WHERE thread_participants.accountId=threads.accountId " | ||
2751 | 1104 | "AND thread_participants.threadId=threads.threadId " | ||
2752 | 1105 | "AND thread_participants.type=threads.type GROUP BY accountId,threadId,type) as state"; | ||
2753 | 1106 | |||
2754 | 1107 | fields << "(SELECT group_concat(thread_participants.roles, \"|,|\") " | ||
2755 | 1108 | "FROM thread_participants WHERE thread_participants.accountId=threads.accountId " | ||
2756 | 1109 | "AND thread_participants.threadId=threads.threadId " | ||
2757 | 1110 | "AND thread_participants.type=threads.type GROUP BY accountId,threadId,type) as roles"; | ||
2758 | 1111 | |||
2759 | 761 | QStringList extraFields; | 1112 | QStringList extraFields; |
2760 | 762 | QString table; | 1113 | QString table; |
2761 | 763 | 1114 | ||
2762 | 764 | switch (type) { | 1115 | switch (type) { |
2763 | 765 | case History::EventTypeText: | 1116 | case History::EventTypeText: |
2764 | 766 | table = "text_events"; | 1117 | table = "text_events"; |
2766 | 767 | extraFields << "text_events.message" << "text_events.messageType" << "text_events.messageStatus" << "text_events.readTimestamp"; | 1118 | extraFields << "text_events.message" << "text_events.messageType" << "text_events.messageStatus" << "text_events.readTimestamp" << "chatType" << "text_events.subject" << "text_events.informationType"; |
2767 | 768 | break; | 1119 | break; |
2768 | 769 | case History::EventTypeVoice: | 1120 | case History::EventTypeVoice: |
2769 | 770 | table = "voice_events"; | 1121 | table = "voice_events"; |
2770 | @@ -773,7 +1124,6 @@ | |||
2771 | 773 | } | 1124 | } |
2772 | 774 | 1125 | ||
2773 | 775 | fields << QString("%1.senderId").arg(table) | 1126 | fields << QString("%1.senderId").arg(table) |
2774 | 776 | << QString("%1.timestamp").arg(table) | ||
2775 | 777 | << QString("%1.newEvent").arg(table); | 1127 | << QString("%1.newEvent").arg(table); |
2776 | 778 | fields << extraFields; | 1128 | fields << extraFields; |
2777 | 779 | 1129 | ||
2778 | @@ -820,13 +1170,31 @@ | |||
2779 | 820 | thread[History::FieldEventId] = query.value(2); | 1170 | thread[History::FieldEventId] = query.value(2); |
2780 | 821 | thread[History::FieldCount] = query.value(3); | 1171 | thread[History::FieldCount] = query.value(3); |
2781 | 822 | thread[History::FieldUnreadCount] = query.value(4); | 1172 | thread[History::FieldUnreadCount] = query.value(4); |
2784 | 823 | QStringList participants = query.value(5).toString().split("|,|"); | 1173 | QStringList participants = query.value(6).toString().split("|,|", QString::SkipEmptyParts); |
2785 | 824 | thread[History::FieldParticipants] = History::ContactMatcher::instance()->contactInfo(accountId, participants, true); | 1174 | QList<int> participantStatus; |
2786 | 1175 | QStringList participantStatusString = query.value(7).toString().split("|,|", QString::SkipEmptyParts); | ||
2787 | 1176 | Q_FOREACH(const QString &statusString, participantStatusString) { | ||
2788 | 1177 | participantStatus << statusString.toUInt(); | ||
2789 | 1178 | } | ||
2790 | 1179 | QStringList participantRolesString = query.value(8).toString().split("|,|", QString::SkipEmptyParts); | ||
2791 | 1180 | QList<int> participantRoles; | ||
2792 | 1181 | Q_FOREACH(const QString &rolesString, participantRolesString) { | ||
2793 | 1182 | participantRoles << rolesString.toUInt(); | ||
2794 | 1183 | } | ||
2795 | 1184 | QVariantList contactList; | ||
2796 | 1185 | QVariantList contactInfo = History::ContactMatcher::instance()->contactInfo(accountId, participants, true); | ||
2797 | 1186 | for (int i = 0; i < contactInfo.count(); ++i) { | ||
2798 | 1187 | QVariantMap map = contactInfo[i].toMap(); | ||
2799 | 1188 | map["state"] = participantStatus[i]; | ||
2800 | 1189 | map["roles"] = participantRoles[i]; | ||
2801 | 1190 | contactList << map; | ||
2802 | 1191 | } | ||
2803 | 1192 | thread[History::FieldParticipants] = contactList; | ||
2804 | 825 | 1193 | ||
2805 | 826 | // the generic event fields | 1194 | // the generic event fields |
2809 | 827 | thread[History::FieldSenderId] = query.value(6); | 1195 | thread[History::FieldSenderId] = query.value(9); |
2810 | 828 | thread[History::FieldTimestamp] = toLocalTimeString(query.value(7).toDateTime()); | 1196 | thread[History::FieldTimestamp] = toLocalTimeString(query.value(5).toDateTime()); |
2811 | 829 | thread[History::FieldNewEvent] = query.value(8).toBool(); | 1197 | thread[History::FieldNewEvent] = query.value(10).toBool(); |
2812 | 830 | 1198 | ||
2813 | 831 | // the next step is to get the last event | 1199 | // the next step is to get the last event |
2814 | 832 | switch (type) { | 1200 | switch (type) { |
2815 | @@ -857,15 +1225,77 @@ | |||
2816 | 857 | thread[History::FieldAttachments] = QVariant::fromValue(attachments); | 1225 | thread[History::FieldAttachments] = QVariant::fromValue(attachments); |
2817 | 858 | attachments.clear(); | 1226 | attachments.clear(); |
2818 | 859 | } | 1227 | } |
2823 | 860 | thread[History::FieldMessage] = query.value(9); | 1228 | thread[History::FieldMessage] = query.value(11); |
2824 | 861 | thread[History::FieldMessageType] = query.value(10); | 1229 | thread[History::FieldMessageType] = query.value(12); |
2825 | 862 | thread[History::FieldMessageStatus] = query.value(11); | 1230 | thread[History::FieldMessageStatus] = query.value(13); |
2826 | 863 | thread[History::FieldReadTimestamp] = toLocalTimeString(query.value(12).toDateTime()); | 1231 | thread[History::FieldReadTimestamp] = toLocalTimeString(query.value(14).toDateTime()); |
2827 | 1232 | thread[History::FieldChatType] = query.value(15).toUInt(); | ||
2828 | 1233 | |||
2829 | 1234 | if (thread[History::FieldChatType].toInt() == 2) { | ||
2830 | 1235 | QVariantMap chatRoomInfo; | ||
2831 | 1236 | QSqlQuery query1(SQLiteDatabase::instance()->database()); | ||
2832 | 1237 | |||
2833 | 1238 | query1.prepare("SELECT roomName, server, creator, creationTimestamp, anonymous, inviteOnly, participantLimit, moderated, title, description, persistent, private, passwordProtected, password, passwordHint, canUpdateConfiguration, subject, actor, timestamp, joined, selfRoles FROM chat_room_info WHERE accountId=:accountId AND threadId=:threadId AND type=:type LIMIT 1"); | ||
2834 | 1239 | query1.bindValue(":accountId", thread[History::FieldAccountId]); | ||
2835 | 1240 | query1.bindValue(":threadId", thread[History::FieldThreadId]); | ||
2836 | 1241 | query1.bindValue(":type", thread[History::FieldType].toInt()); | ||
2837 | 1242 | |||
2838 | 1243 | if (!query1.exec()) { | ||
2839 | 1244 | qCritical() << "Failed to get chat room info for thread: Error:" << query1.lastError() << query1.lastQuery(); | ||
2840 | 1245 | break; | ||
2841 | 1246 | } | ||
2842 | 1247 | query1.next(); | ||
2843 | 1248 | |||
2844 | 1249 | if (query1.value(0).isValid()) | ||
2845 | 1250 | chatRoomInfo["RoomName"] = query1.value(0); | ||
2846 | 1251 | if (query1.value(1).isValid()) | ||
2847 | 1252 | chatRoomInfo["Server"] = query1.value(1); | ||
2848 | 1253 | if (query1.value(2).isValid()) | ||
2849 | 1254 | chatRoomInfo["Creator"] = query1.value(2); | ||
2850 | 1255 | if (query1.value(3).isValid()) | ||
2851 | 1256 | chatRoomInfo["CreationTimestamp"] = toLocalTimeString(query1.value(3).toDateTime()); | ||
2852 | 1257 | if (query1.value(4).isValid()) | ||
2853 | 1258 | chatRoomInfo["Anonymous"] = query1.value(4).toBool(); | ||
2854 | 1259 | if (query1.value(5).isValid()) | ||
2855 | 1260 | chatRoomInfo["InviteOnly"] = query1.value(5).toBool(); | ||
2856 | 1261 | if (query1.value(6).isValid()) | ||
2857 | 1262 | chatRoomInfo["Limit"] = query1.value(6).toInt(); | ||
2858 | 1263 | if (query1.value(7).isValid()) | ||
2859 | 1264 | chatRoomInfo["Moderated"] = query1.value(7).toBool(); | ||
2860 | 1265 | if (query1.value(8).isValid()) | ||
2861 | 1266 | chatRoomInfo["Title"] = query1.value(8); | ||
2862 | 1267 | if (query1.value(9).isValid()) | ||
2863 | 1268 | chatRoomInfo["Description"] = query1.value(9); | ||
2864 | 1269 | if (query1.value(10).isValid()) | ||
2865 | 1270 | chatRoomInfo["Persistent"] = query1.value(10).toBool(); | ||
2866 | 1271 | if (query1.value(11).isValid()) | ||
2867 | 1272 | chatRoomInfo["Private"] = query1.value(11).toBool(); | ||
2868 | 1273 | if (query1.value(12).isValid()) | ||
2869 | 1274 | chatRoomInfo["PasswordProtected"] = query1.value(12).toBool(); | ||
2870 | 1275 | if (query1.value(13).isValid()) | ||
2871 | 1276 | chatRoomInfo["Password"] = query1.value(13); | ||
2872 | 1277 | if (query1.value(14).isValid()) | ||
2873 | 1278 | chatRoomInfo["PasswordHint"] = query1.value(14); | ||
2874 | 1279 | if (query1.value(15).isValid()) | ||
2875 | 1280 | chatRoomInfo["CanUpdateConfiguration"] = query1.value(15).toBool(); | ||
2876 | 1281 | if (query1.value(16).isValid()) | ||
2877 | 1282 | chatRoomInfo["Subject"] = query1.value(16); | ||
2878 | 1283 | if (query1.value(17).isValid()) | ||
2879 | 1284 | chatRoomInfo["Actor"] = query1.value(17); | ||
2880 | 1285 | if (query1.value(18).isValid()) | ||
2881 | 1286 | chatRoomInfo["Timestamp"] = toLocalTimeString(query1.value(18).toDateTime()); | ||
2882 | 1287 | if (query1.value(19).isValid()) | ||
2883 | 1288 | chatRoomInfo["Joined"] = query1.value(19).toBool(); | ||
2884 | 1289 | if (query1.value(20).isValid()) | ||
2885 | 1290 | chatRoomInfo["SelfRoles"] = query1.value(20).toInt(); | ||
2886 | 1291 | |||
2887 | 1292 | thread[History::FieldChatRoomInfo] = chatRoomInfo; | ||
2888 | 1293 | } | ||
2889 | 864 | break; | 1294 | break; |
2890 | 865 | case History::EventTypeVoice: | 1295 | case History::EventTypeVoice: |
2894 | 866 | thread[History::FieldMissed] = query.value(10); | 1296 | thread[History::FieldMissed] = query.value(12); |
2895 | 867 | thread[History::FieldDuration] = query.value(9); | 1297 | thread[History::FieldDuration] = query.value(11); |
2896 | 868 | thread[History::FieldRemoteParticipant] = History::ContactMatcher::instance()->contactInfo(accountId, query.value(11).toString(), true); | 1298 | thread[History::FieldRemoteParticipant] = History::ContactMatcher::instance()->contactInfo(accountId, query.value(13).toString(), true); |
2897 | 869 | break; | 1299 | break; |
2898 | 870 | } | 1300 | } |
2899 | 871 | threads << thread; | 1301 | threads << thread; |
2900 | @@ -889,7 +1319,7 @@ | |||
2901 | 889 | case History::EventTypeText: | 1319 | case History::EventTypeText: |
2902 | 890 | participantsField = participantsField.arg("text_events", QString::number(type)); | 1320 | participantsField = participantsField.arg("text_events", QString::number(type)); |
2903 | 891 | queryText = QString("SELECT accountId, threadId, eventId, senderId, timestamp, newEvent, %1, " | 1321 | queryText = QString("SELECT accountId, threadId, eventId, senderId, timestamp, newEvent, %1, " |
2905 | 892 | "message, messageType, messageStatus, readTimestamp, subject FROM text_events %2 %3").arg(participantsField, modifiedCondition, order); | 1322 | "message, messageType, messageStatus, readTimestamp, subject, informationType FROM text_events %2 %3").arg(participantsField, modifiedCondition, order); |
2906 | 893 | break; | 1323 | break; |
2907 | 894 | case History::EventTypeVoice: | 1324 | case History::EventTypeVoice: |
2908 | 895 | participantsField = participantsField.arg("voice_events", QString::number(type)); | 1325 | participantsField = participantsField.arg("voice_events", QString::number(type)); |
2909 | @@ -960,6 +1390,10 @@ | |||
2910 | 960 | event[History::FieldMessageType] = query.value(8); | 1390 | event[History::FieldMessageType] = query.value(8); |
2911 | 961 | event[History::FieldMessageStatus] = query.value(9); | 1391 | event[History::FieldMessageStatus] = query.value(9); |
2912 | 962 | event[History::FieldReadTimestamp] = toLocalTimeString(query.value(10).toDateTime()); | 1392 | event[History::FieldReadTimestamp] = toLocalTimeString(query.value(10).toDateTime()); |
2913 | 1393 | if (!query.value(11).toString().isEmpty()) { | ||
2914 | 1394 | event[History::FieldSubject] = query.value(11).toString(); | ||
2915 | 1395 | } | ||
2916 | 1396 | event[History::FieldInformationType] = query.value(12).toInt(); | ||
2917 | 963 | break; | 1397 | break; |
2918 | 964 | case History::EventTypeVoice: | 1398 | case History::EventTypeVoice: |
2919 | 965 | event[History::FieldDuration] = query.value(7).toInt(); | 1399 | event[History::FieldDuration] = query.value(7).toInt(); |
2920 | @@ -975,7 +1409,7 @@ | |||
2921 | 975 | 1409 | ||
2922 | 976 | QString SQLiteHistoryPlugin::toLocalTimeString(const QDateTime ×tamp) | 1410 | QString SQLiteHistoryPlugin::toLocalTimeString(const QDateTime ×tamp) |
2923 | 977 | { | 1411 | { |
2925 | 978 | return QDateTime(timestamp.date(), timestamp.time(), Qt::UTC).toLocalTime().toString("yyyy-MM-ddTHH:mm:ss.zzz"); | 1412 | return QDateTime(timestamp.date(), timestamp.time(), Qt::UTC).toLocalTime().toString(timestampFormat); |
2926 | 979 | } | 1413 | } |
2927 | 980 | 1414 | ||
2928 | 981 | QString SQLiteHistoryPlugin::filterToString(const History::Filter &filter, QVariantMap &bindValues, const QString &propertyPrefix) const | 1415 | QString SQLiteHistoryPlugin::filterToString(const History::Filter &filter, QVariantMap &bindValues, const QString &propertyPrefix) const |
2929 | 982 | 1416 | ||
2930 | === modified file 'plugins/sqlite/sqlitehistoryplugin.h' | |||
2931 | --- plugins/sqlite/sqlitehistoryplugin.h 2015-10-20 19:20:00 +0000 | |||
2932 | +++ plugins/sqlite/sqlitehistoryplugin.h 2016-11-24 12:52:24 +0000 | |||
2933 | @@ -1,5 +1,5 @@ | |||
2934 | 1 | /* | 1 | /* |
2936 | 2 | * Copyright (C) 2013-2015 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
2937 | 3 | * | 3 | * |
2938 | 4 | * Authors: | 4 | * Authors: |
2939 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
2940 | @@ -55,6 +55,10 @@ | |||
2941 | 55 | History::EventType type, | 55 | History::EventType type, |
2942 | 56 | const QStringList &participants, | 56 | const QStringList &participants, |
2943 | 57 | History::MatchFlags matchFlags = History::MatchCaseSensitive); | 57 | History::MatchFlags matchFlags = History::MatchCaseSensitive); |
2944 | 58 | QVariantMap threadForProperties(const QString &accountId, | ||
2945 | 59 | History::EventType type, | ||
2946 | 60 | const QVariantMap &properties, | ||
2947 | 61 | History::MatchFlags matchFlags = History::MatchCaseSensitive); | ||
2948 | 58 | 62 | ||
2949 | 59 | QList<QVariantMap> eventsForThread(const QVariantMap &thread); | 63 | QList<QVariantMap> eventsForThread(const QVariantMap &thread); |
2950 | 60 | 64 | ||
2951 | @@ -62,7 +66,12 @@ | |||
2952 | 62 | QVariantMap getSingleEvent(History::EventType type, const QString &accountId, const QString &threadId, const QString &eventId); | 66 | QVariantMap getSingleEvent(History::EventType type, const QString &accountId, const QString &threadId, const QString &eventId); |
2953 | 63 | 67 | ||
2954 | 64 | // Writer part of the plugin | 68 | // Writer part of the plugin |
2955 | 69 | QVariantMap createThreadForProperties(const QString &accountId, History::EventType type, const QVariantMap &properties); | ||
2956 | 65 | QVariantMap createThreadForParticipants(const QString &accountId, History::EventType type, const QStringList &participants); | 70 | QVariantMap createThreadForParticipants(const QString &accountId, History::EventType type, const QStringList &participants); |
2957 | 71 | |||
2958 | 72 | bool updateRoomParticipants(const QString &accountId, const QString &threadId, History::EventType type, const QVariantList &participants); | ||
2959 | 73 | bool updateRoomParticipantsRoles(const QString &accountId, const QString &threadId, History::EventType type, const QVariantMap &participantsRoles); | ||
2960 | 74 | bool updateRoomInfo(const QString &accountId, const QString &threadId, History::EventType type, const QVariantMap &properties, const QStringList &invalidated = QStringList()); | ||
2961 | 66 | bool removeThread(const QVariantMap &thread); | 75 | bool removeThread(const QVariantMap &thread); |
2962 | 67 | 76 | ||
2963 | 68 | History::EventWriteResult writeTextEvent(const QVariantMap &event); | 77 | History::EventWriteResult writeTextEvent(const QVariantMap &event); |
2964 | 69 | 78 | ||
2965 | === modified file 'plugins/sqlite/sqlitehistorythreadview.cpp' | |||
2966 | --- plugins/sqlite/sqlitehistorythreadview.cpp 2015-09-21 20:05:06 +0000 | |||
2967 | +++ plugins/sqlite/sqlitehistorythreadview.cpp 2016-11-24 12:52:24 +0000 | |||
2968 | @@ -35,7 +35,6 @@ | |||
2969 | 35 | : History::PluginThreadView(), mPlugin(plugin), mType(type), mSort(sort), | 35 | : History::PluginThreadView(), mPlugin(plugin), mType(type), mSort(sort), |
2970 | 36 | mFilter(filter), mPageSize(15), mQuery(SQLiteDatabase::instance()->database()), mOffset(0), mValid(true), mQueryProperties(properties) | 36 | mFilter(filter), mPageSize(15), mQuery(SQLiteDatabase::instance()->database()), mOffset(0), mValid(true), mQueryProperties(properties) |
2971 | 37 | { | 37 | { |
2972 | 38 | qDebug() << __PRETTY_FUNCTION__; | ||
2973 | 39 | mTemporaryTable = QString("threadview%1%2").arg(QString::number((qulonglong)this), QDateTime::currentDateTimeUtc().toString("yyyyMMddhhmmsszzz")); | 38 | mTemporaryTable = QString("threadview%1%2").arg(QString::number((qulonglong)this), QDateTime::currentDateTimeUtc().toString("yyyyMMddhhmmsszzz")); |
2974 | 40 | mQuery.setForwardOnly(true); | 39 | mQuery.setForwardOnly(true); |
2975 | 41 | 40 | ||
2976 | @@ -69,9 +68,6 @@ | |||
2977 | 69 | Q_EMIT Invalidated(); | 68 | Q_EMIT Invalidated(); |
2978 | 70 | return; | 69 | return; |
2979 | 71 | } | 70 | } |
2980 | 72 | |||
2981 | 73 | mQuery.exec(QString("SELECT count(*) FROM %1").arg(mTemporaryTable)); | ||
2982 | 74 | mQuery.next(); | ||
2983 | 75 | } | 71 | } |
2984 | 76 | 72 | ||
2985 | 77 | SQLiteHistoryThreadView::~SQLiteHistoryThreadView() | 73 | SQLiteHistoryThreadView::~SQLiteHistoryThreadView() |
2986 | @@ -84,7 +80,6 @@ | |||
2987 | 84 | 80 | ||
2988 | 85 | QList<QVariantMap> SQLiteHistoryThreadView::NextPage() | 81 | QList<QVariantMap> SQLiteHistoryThreadView::NextPage() |
2989 | 86 | { | 82 | { |
2990 | 87 | qDebug() << __PRETTY_FUNCTION__; | ||
2991 | 88 | QList<QVariantMap> threads; | 83 | QList<QVariantMap> threads; |
2992 | 89 | 84 | ||
2993 | 90 | // now prepare for selecting from it | 85 | // now prepare for selecting from it |
2994 | 91 | 86 | ||
2995 | === modified file 'src/channelobserver.cpp' | |||
2996 | --- src/channelobserver.cpp 2015-10-06 17:03:38 +0000 | |||
2997 | +++ src/channelobserver.cpp 2016-11-24 12:52:24 +0000 | |||
2998 | @@ -40,6 +40,8 @@ | |||
2999 | 40 | Tp::ChannelClassSpecList specList; | 40 | Tp::ChannelClassSpecList specList; |
3000 | 41 | specList << Tp::ChannelClassSpec::audioCall(); | 41 | specList << Tp::ChannelClassSpec::audioCall(); |
3001 | 42 | specList << Tp::ChannelClassSpec::textChat(); | 42 | specList << Tp::ChannelClassSpec::textChat(); |
3002 | 43 | specList << Tp::ChannelClassSpec::textChatroom(); | ||
3003 | 44 | specList << Tp::ChannelClassSpec::unnamedTextChat(); | ||
3004 | 43 | 45 | ||
3005 | 44 | return specList; | 46 | return specList; |
3006 | 45 | } | 47 | } |
3007 | @@ -58,7 +60,6 @@ | |||
3008 | 58 | Q_UNUSED(requestsSatisfied) | 60 | Q_UNUSED(requestsSatisfied) |
3009 | 59 | Q_UNUSED(observerInfo) | 61 | Q_UNUSED(observerInfo) |
3010 | 60 | 62 | ||
3011 | 61 | qDebug() << __PRETTY_FUNCTION__; | ||
3012 | 62 | Q_FOREACH (Tp::ChannelPtr channel, channels) { | 63 | Q_FOREACH (Tp::ChannelPtr channel, channels) { |
3013 | 63 | // tp-qt has not support for the SMS interface | 64 | // tp-qt has not support for the SMS interface |
3014 | 64 | if (channel->immutableProperties().contains(TP_QT_IFACE_CHANNEL_INTERFACE_SMS + QLatin1String(".Flash"))) { | 65 | if (channel->immutableProperties().contains(TP_QT_IFACE_CHANNEL_INTERFACE_SMS + QLatin1String(".Flash"))) { |
3015 | 65 | 66 | ||
3016 | === modified file 'src/contactmatcher.cpp' | |||
3017 | --- src/contactmatcher.cpp 2015-10-07 20:21:54 +0000 | |||
3018 | +++ src/contactmatcher.cpp 2016-11-24 12:52:24 +0000 | |||
3019 | @@ -1,5 +1,5 @@ | |||
3020 | 1 | /* | 1 | /* |
3022 | 2 | * Copyright (C) 2014-2015 Canonical, Ltd. | 2 | * Copyright (C) 2014-2016 Canonical, Ltd. |
3023 | 3 | * | 3 | * |
3024 | 4 | * Authors: | 4 | * Authors: |
3025 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
3026 | @@ -95,7 +95,7 @@ | |||
3027 | 95 | * | 95 | * |
3028 | 96 | * Note that synchronous requests should only be placed after \ref TelepathyHelper is ready. | 96 | * Note that synchronous requests should only be placed after \ref TelepathyHelper is ready. |
3029 | 97 | */ | 97 | */ |
3031 | 98 | QVariantMap ContactMatcher::contactInfo(const QString &accountId, const QString &identifier, bool synchronous) | 98 | QVariantMap ContactMatcher::contactInfo(const QString &accountId, const QString &identifier, bool synchronous, const QVariantMap &properties) |
3032 | 99 | { | 99 | { |
3033 | 100 | InternalContactMap &internalMap = mContactMap[accountId]; | 100 | InternalContactMap &internalMap = mContactMap[accountId]; |
3034 | 101 | 101 | ||
3035 | @@ -103,8 +103,9 @@ | |||
3036 | 103 | if (internalMap.contains(identifier)) { | 103 | if (internalMap.contains(identifier)) { |
3037 | 104 | return internalMap[identifier]; | 104 | return internalMap[identifier]; |
3038 | 105 | } | 105 | } |
3040 | 106 | 106 | ||
3041 | 107 | QVariantMap map; | 107 | QVariantMap map; |
3042 | 108 | |||
3043 | 108 | // and if there was no match, asynchronously request the info, and return an empty map for now | 109 | // and if there was no match, asynchronously request the info, and return an empty map for now |
3044 | 109 | if (History::TelepathyHelper::instance()->ready()) { | 110 | if (History::TelepathyHelper::instance()->ready()) { |
3045 | 110 | map = requestContactInfo(accountId, identifier, synchronous); | 111 | map = requestContactInfo(accountId, identifier, synchronous); |
3046 | @@ -114,6 +115,15 @@ | |||
3047 | 114 | } | 115 | } |
3048 | 115 | map[History::FieldIdentifier] = identifier; | 116 | map[History::FieldIdentifier] = identifier; |
3049 | 116 | map[History::FieldAccountId] = accountId; | 117 | map[History::FieldAccountId] = accountId; |
3050 | 118 | |||
3051 | 119 | QMapIterator<QString, QVariant> i(properties); | ||
3052 | 120 | while (i.hasNext()) { | ||
3053 | 121 | i.next(); | ||
3054 | 122 | if (!map.contains(i.key())) { | ||
3055 | 123 | map[i.key()] = i.value(); | ||
3056 | 124 | } | ||
3057 | 125 | } | ||
3058 | 126 | |||
3059 | 117 | mContactMap[accountId][identifier] = map; | 127 | mContactMap[accountId][identifier] = map; |
3060 | 118 | return map; | 128 | return map; |
3061 | 119 | } | 129 | } |
3062 | 120 | 130 | ||
3063 | === modified file 'src/contactmatcher_p.h' | |||
3064 | --- src/contactmatcher_p.h 2015-10-06 12:59:03 +0000 | |||
3065 | +++ src/contactmatcher_p.h 2016-11-24 12:52:24 +0000 | |||
3066 | @@ -1,5 +1,5 @@ | |||
3067 | 1 | /* | 1 | /* |
3069 | 2 | * Copyright (C) 2014-2015 Canonical, Ltd. | 2 | * Copyright (C) 2014-2016 Canonical, Ltd. |
3070 | 3 | * | 3 | * |
3071 | 4 | * Authors: | 4 | * Authors: |
3072 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
3073 | @@ -45,7 +45,7 @@ | |||
3074 | 45 | Q_OBJECT | 45 | Q_OBJECT |
3075 | 46 | public: | 46 | public: |
3076 | 47 | static ContactMatcher *instance(QContactManager *manager = 0); | 47 | static ContactMatcher *instance(QContactManager *manager = 0); |
3078 | 48 | QVariantMap contactInfo(const QString &accountId, const QString &identifier, bool synchronous = false); | 48 | QVariantMap contactInfo(const QString &accountId, const QString &identifier, bool synchronous = false, const QVariantMap &properties = QVariantMap()); |
3079 | 49 | QVariantList contactInfo(const QString &accountId, const QStringList &identifiers, bool synchronous = false); | 49 | QVariantList contactInfo(const QString &accountId, const QStringList &identifiers, bool synchronous = false); |
3080 | 50 | 50 | ||
3081 | 51 | // this will only watch for contact changes affecting the identifier, but won't fetch contact info | 51 | // this will only watch for contact changes affecting the identifier, but won't fetch contact info |
3082 | 52 | 52 | ||
3083 | === modified file 'src/manager.cpp' | |||
3084 | --- src/manager.cpp 2015-10-01 19:44:45 +0000 | |||
3085 | +++ src/manager.cpp 2016-11-24 12:52:24 +0000 | |||
3086 | @@ -1,5 +1,5 @@ | |||
3087 | 1 | /* | 1 | /* |
3089 | 2 | * Copyright (C) 2013 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
3090 | 3 | * | 3 | * |
3091 | 4 | * Authors: | 4 | * Authors: |
3092 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
3093 | @@ -135,7 +135,23 @@ | |||
3094 | 135 | { | 135 | { |
3095 | 136 | Q_D(Manager); | 136 | Q_D(Manager); |
3096 | 137 | 137 | ||
3098 | 138 | return d->dbus->threadForParticipants(accountId, type, participants, matchFlags, create); | 138 | QVariantMap properties; |
3099 | 139 | properties[History::FieldParticipantIds] = participants; | ||
3100 | 140 | if (participants.size() == 1) { | ||
3101 | 141 | properties[History::FieldChatType] = History::ChatTypeContact; | ||
3102 | 142 | } | ||
3103 | 143 | return d->dbus->threadForProperties(accountId, type, properties, matchFlags, create); | ||
3104 | 144 | } | ||
3105 | 145 | |||
3106 | 146 | Thread Manager::threadForProperties(const QString &accountId, | ||
3107 | 147 | EventType type, | ||
3108 | 148 | const QVariantMap &properties, | ||
3109 | 149 | MatchFlags matchFlags, | ||
3110 | 150 | bool create) | ||
3111 | 151 | { | ||
3112 | 152 | Q_D(Manager); | ||
3113 | 153 | |||
3114 | 154 | return d->dbus->threadForProperties(accountId, type, properties, matchFlags, create); | ||
3115 | 139 | } | 155 | } |
3116 | 140 | 156 | ||
3117 | 141 | Thread Manager::getSingleThread(EventType type, const QString &accountId, const QString &threadId, const QVariantMap &properties) | 157 | Thread Manager::getSingleThread(EventType type, const QString &accountId, const QString &threadId, const QVariantMap &properties) |
3118 | 142 | 158 | ||
3119 | === modified file 'src/manager.h' | |||
3120 | --- src/manager.h 2015-10-01 19:44:45 +0000 | |||
3121 | +++ src/manager.h 2016-11-24 12:52:24 +0000 | |||
3122 | @@ -1,5 +1,5 @@ | |||
3123 | 1 | /* | 1 | /* |
3125 | 2 | * Copyright (C) 2013 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
3126 | 3 | * | 3 | * |
3127 | 4 | * Authors: | 4 | * Authors: |
3128 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
3129 | @@ -61,6 +61,12 @@ | |||
3130 | 61 | const QStringList &participants, | 61 | const QStringList &participants, |
3131 | 62 | History::MatchFlags matchFlags = History::MatchCaseSensitive, | 62 | History::MatchFlags matchFlags = History::MatchCaseSensitive, |
3132 | 63 | bool create = false); | 63 | bool create = false); |
3133 | 64 | Thread threadForProperties(const QString &accountId, | ||
3134 | 65 | EventType type, | ||
3135 | 66 | const QVariantMap &properties, | ||
3136 | 67 | History::MatchFlags matchFlags = History::MatchCaseSensitive, | ||
3137 | 68 | bool create = false); | ||
3138 | 69 | |||
3139 | 64 | Thread getSingleThread(EventType type, const QString &accountId, const QString &threadId, const QVariantMap &properties = QVariantMap()); | 70 | Thread getSingleThread(EventType type, const QString &accountId, const QString &threadId, const QVariantMap &properties = QVariantMap()); |
3140 | 65 | 71 | ||
3141 | 66 | bool writeEvents(const History::Events &events); | 72 | bool writeEvents(const History::Events &events); |
3142 | 67 | 73 | ||
3143 | === modified file 'src/managerdbus.cpp' | |||
3144 | --- src/managerdbus.cpp 2015-09-23 15:08:07 +0000 | |||
3145 | +++ src/managerdbus.cpp 2016-11-24 12:52:24 +0000 | |||
3146 | @@ -1,5 +1,5 @@ | |||
3147 | 1 | /* | 1 | /* |
3149 | 2 | * Copyright (C) 2013 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
3150 | 3 | * | 3 | * |
3151 | 4 | * Authors: | 4 | * Authors: |
3152 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
3153 | @@ -64,9 +64,21 @@ | |||
3154 | 64 | MatchFlags matchFlags, | 64 | MatchFlags matchFlags, |
3155 | 65 | bool create) | 65 | bool create) |
3156 | 66 | { | 66 | { |
3157 | 67 | QVariantMap properties; | ||
3158 | 68 | properties[History::FieldParticipantIds] = participants; | ||
3159 | 69 | |||
3160 | 70 | return threadForProperties(accountId, type, properties, matchFlags, create); | ||
3161 | 71 | } | ||
3162 | 72 | |||
3163 | 73 | Thread ManagerDBus::threadForProperties(const QString &accountId, | ||
3164 | 74 | EventType type, | ||
3165 | 75 | const QVariantMap &properties, | ||
3166 | 76 | MatchFlags matchFlags, | ||
3167 | 77 | bool create) | ||
3168 | 78 | { | ||
3169 | 67 | Thread thread; | 79 | Thread thread; |
3170 | 68 | // FIXME: move to async call if possible | 80 | // FIXME: move to async call if possible |
3172 | 69 | QDBusReply<QVariantMap> reply = mInterface.call("ThreadForParticipants", accountId, (int) type, participants, (int)matchFlags, create); | 81 | QDBusReply<QVariantMap> reply = mInterface.call("ThreadForProperties", accountId, (int) type, properties, (int)matchFlags, create); |
3173 | 70 | if (reply.isValid()) { | 82 | if (reply.isValid()) { |
3174 | 71 | QVariantMap properties = reply.value(); | 83 | QVariantMap properties = reply.value(); |
3175 | 72 | thread = Thread::fromProperties(properties); | 84 | thread = Thread::fromProperties(properties); |
3176 | 73 | 85 | ||
3177 | === modified file 'src/managerdbus_p.h' | |||
3178 | --- src/managerdbus_p.h 2015-09-23 15:08:07 +0000 | |||
3179 | +++ src/managerdbus_p.h 2016-11-24 12:52:24 +0000 | |||
3180 | @@ -1,5 +1,5 @@ | |||
3181 | 1 | /* | 1 | /* |
3183 | 2 | * Copyright (C) 2013 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
3184 | 3 | * | 3 | * |
3185 | 4 | * Authors: | 4 | * Authors: |
3186 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
3187 | @@ -45,6 +45,12 @@ | |||
3188 | 45 | History::MatchFlags matchFlags, | 45 | History::MatchFlags matchFlags, |
3189 | 46 | bool create); | 46 | bool create); |
3190 | 47 | 47 | ||
3191 | 48 | Thread threadForProperties(const QString &accountId, | ||
3192 | 49 | EventType type, | ||
3193 | 50 | const QVariantMap &properties, | ||
3194 | 51 | History::MatchFlags matchFlags, | ||
3195 | 52 | bool create); | ||
3196 | 53 | |||
3197 | 48 | bool writeEvents(const History::Events &events); | 54 | bool writeEvents(const History::Events &events); |
3198 | 49 | bool removeThreads(const Threads &threads); | 55 | bool removeThreads(const Threads &threads); |
3199 | 50 | bool removeEvents(const Events &events); | 56 | bool removeEvents(const Events &events); |
3200 | 51 | 57 | ||
3201 | === modified file 'src/participant.cpp' | |||
3202 | --- src/participant.cpp 2016-01-04 18:28:34 +0000 | |||
3203 | +++ src/participant.cpp 2016-11-24 12:52:24 +0000 | |||
3204 | @@ -1,5 +1,5 @@ | |||
3205 | 1 | /* | 1 | /* |
3207 | 2 | * Copyright (C) 2015 Canonical, Ltd. | 2 | * Copyright (C) 2015-2016 Canonical, Ltd. |
3208 | 3 | * | 3 | * |
3209 | 4 | * Authors: | 4 | * Authors: |
3210 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
3211 | @@ -36,9 +36,11 @@ | |||
3212 | 36 | const QString &theContactId, | 36 | const QString &theContactId, |
3213 | 37 | const QString &theAlias, | 37 | const QString &theAlias, |
3214 | 38 | const QString &theAvatar, | 38 | const QString &theAvatar, |
3215 | 39 | const uint theState, | ||
3216 | 40 | const uint theRoles, | ||
3217 | 39 | const QVariantMap &theDetailProperties) : | 41 | const QVariantMap &theDetailProperties) : |
3218 | 40 | accountId(theAccountId), identifier(theIdentifier), contactId(theContactId), | 42 | accountId(theAccountId), identifier(theIdentifier), contactId(theContactId), |
3220 | 41 | alias(theAlias), avatar(theAvatar), detailProperties(theDetailProperties) | 43 | alias(theAlias), avatar(theAvatar), state(theState), roles(theRoles), detailProperties(theDetailProperties) |
3221 | 42 | { | 44 | { |
3222 | 43 | } | 45 | } |
3223 | 44 | 46 | ||
3224 | @@ -51,8 +53,8 @@ | |||
3225 | 51 | { | 53 | { |
3226 | 52 | } | 54 | } |
3227 | 53 | 55 | ||
3230 | 54 | Participant::Participant(const QString &accountId, const QString &identifier, const QString &contactId, const QString &alias, const QString &avatar, const QVariantMap &detailProperties) | 56 | Participant::Participant(const QString &accountId, const QString &identifier, const QString &contactId, const QString &alias, const QString &avatar, uint state, uint roles, const QVariantMap &detailProperties) |
3231 | 55 | : d_ptr(new ParticipantPrivate(accountId, identifier, contactId, alias, avatar, detailProperties)) | 57 | : d_ptr(new ParticipantPrivate(accountId, identifier, contactId, alias, avatar, state, roles, detailProperties)) |
3232 | 56 | { | 58 | { |
3233 | 57 | } | 59 | } |
3234 | 58 | 60 | ||
3235 | @@ -104,6 +106,18 @@ | |||
3236 | 104 | return d->avatar; | 106 | return d->avatar; |
3237 | 105 | } | 107 | } |
3238 | 106 | 108 | ||
3239 | 109 | uint Participant::state() const | ||
3240 | 110 | { | ||
3241 | 111 | Q_D(const Participant); | ||
3242 | 112 | return d->state; | ||
3243 | 113 | } | ||
3244 | 114 | |||
3245 | 115 | uint Participant::roles() const | ||
3246 | 116 | { | ||
3247 | 117 | Q_D(const Participant); | ||
3248 | 118 | return d->roles; | ||
3249 | 119 | } | ||
3250 | 120 | |||
3251 | 107 | QVariantMap Participant::detailProperties() const | 121 | QVariantMap Participant::detailProperties() const |
3252 | 108 | { | 122 | { |
3253 | 109 | Q_D(const Participant); | 123 | Q_D(const Participant); |
3254 | @@ -140,6 +154,8 @@ | |||
3255 | 140 | map[FieldContactId] = d->contactId; | 154 | map[FieldContactId] = d->contactId; |
3256 | 141 | map[FieldAlias] = d->alias; | 155 | map[FieldAlias] = d->alias; |
3257 | 142 | map[FieldAvatar] = d->avatar; | 156 | map[FieldAvatar] = d->avatar; |
3258 | 157 | map[FieldParticipantState] = d->state; | ||
3259 | 158 | map[FieldParticipantRoles] = d->roles; | ||
3260 | 143 | map[FieldDetailProperties] = d->detailProperties; | 159 | map[FieldDetailProperties] = d->detailProperties; |
3261 | 144 | 160 | ||
3262 | 145 | return map; | 161 | return map; |
3263 | @@ -157,6 +173,8 @@ | |||
3264 | 157 | QString contactId = properties[FieldContactId].toString(); | 173 | QString contactId = properties[FieldContactId].toString(); |
3265 | 158 | QString alias = properties[FieldAlias].toString(); | 174 | QString alias = properties[FieldAlias].toString(); |
3266 | 159 | QString avatar = properties[FieldAvatar].toString(); | 175 | QString avatar = properties[FieldAvatar].toString(); |
3267 | 176 | uint state = properties[FieldParticipantState].toUInt(); | ||
3268 | 177 | uint roles = properties[FieldParticipantRoles].toUInt(); | ||
3269 | 160 | QVariantMap detailProperties; | 178 | QVariantMap detailProperties; |
3270 | 161 | QVariant detailPropertiesVariant = properties[FieldDetailProperties]; | 179 | QVariant detailPropertiesVariant = properties[FieldDetailProperties]; |
3271 | 162 | if (detailPropertiesVariant.canConvert<QVariantMap>()) { | 180 | if (detailPropertiesVariant.canConvert<QVariantMap>()) { |
3272 | @@ -169,7 +187,7 @@ | |||
3273 | 169 | } | 187 | } |
3274 | 170 | } | 188 | } |
3275 | 171 | 189 | ||
3277 | 172 | return Participant(accountId, identifier, contactId, alias, avatar, detailProperties); | 190 | return Participant(accountId, identifier, contactId, alias, avatar, state, roles, detailProperties); |
3278 | 173 | } | 191 | } |
3279 | 174 | 192 | ||
3280 | 175 | QStringList Participants::identifiers() const | 193 | QStringList Participants::identifiers() const |
3281 | @@ -184,7 +202,9 @@ | |||
3282 | 184 | Participants Participants::fromVariant(const QVariant &variant) | 202 | Participants Participants::fromVariant(const QVariant &variant) |
3283 | 185 | { | 203 | { |
3284 | 186 | Participants participants; | 204 | Participants participants; |
3286 | 187 | if (variant.canConvert<QVariantList>()) { | 205 | if (variant.type() == QVariant::StringList) { |
3287 | 206 | participants = Participants::fromStringList(variant.toStringList()); | ||
3288 | 207 | } else if (variant.canConvert<QVariantList>()) { | ||
3289 | 188 | participants = Participants::fromVariantList(variant.toList()); | 208 | participants = Participants::fromVariantList(variant.toList()); |
3290 | 189 | } else if (variant.canConvert<QDBusArgument>()) { | 209 | } else if (variant.canConvert<QDBusArgument>()) { |
3291 | 190 | QDBusArgument argument = variant.value<QDBusArgument>(); | 210 | QDBusArgument argument = variant.value<QDBusArgument>(); |
3292 | @@ -193,6 +213,17 @@ | |||
3293 | 193 | return participants; | 213 | return participants; |
3294 | 194 | } | 214 | } |
3295 | 195 | 215 | ||
3296 | 216 | Participants Participants::fromStringList(const QStringList &list) | ||
3297 | 217 | { | ||
3298 | 218 | Participants participants; | ||
3299 | 219 | Q_FOREACH(const QString& participantId, list) { | ||
3300 | 220 | QVariantMap properties; | ||
3301 | 221 | properties[FieldIdentifier] = participantId; | ||
3302 | 222 | participants << Participant::fromProperties(properties); | ||
3303 | 223 | } | ||
3304 | 224 | return participants; | ||
3305 | 225 | } | ||
3306 | 226 | |||
3307 | 196 | Participants Participants::fromVariantList(const QVariantList &list) | 227 | Participants Participants::fromVariantList(const QVariantList &list) |
3308 | 197 | { | 228 | { |
3309 | 198 | Participants participants; | 229 | Participants participants; |
3310 | @@ -211,6 +242,17 @@ | |||
3311 | 211 | return list; | 242 | return list; |
3312 | 212 | } | 243 | } |
3313 | 213 | 244 | ||
3314 | 245 | Participants Participants::filterByState(uint state) const | ||
3315 | 246 | { | ||
3316 | 247 | Participants filtered; | ||
3317 | 248 | Q_FOREACH(const Participant &participant, *this) { | ||
3318 | 249 | if (participant.state() == state) { | ||
3319 | 250 | filtered << participant; | ||
3320 | 251 | } | ||
3321 | 252 | } | ||
3322 | 253 | return filtered; | ||
3323 | 254 | } | ||
3324 | 255 | |||
3325 | 214 | const QDBusArgument &operator>>(const QDBusArgument &argument, Participants &participants) | 256 | const QDBusArgument &operator>>(const QDBusArgument &argument, Participants &participants) |
3326 | 215 | { | 257 | { |
3327 | 216 | argument.beginArray(); | 258 | argument.beginArray(); |
3328 | 217 | 259 | ||
3329 | === modified file 'src/participant.h' | |||
3330 | --- src/participant.h 2015-09-28 23:13:21 +0000 | |||
3331 | +++ src/participant.h 2016-11-24 12:52:24 +0000 | |||
3332 | @@ -1,5 +1,5 @@ | |||
3333 | 1 | /* | 1 | /* |
3335 | 2 | * Copyright (C) 2015 Canonical, Ltd. | 2 | * Copyright (C) 2015-2016 Canonical, Ltd. |
3336 | 3 | * | 3 | * |
3337 | 4 | * Authors: | 4 | * Authors: |
3338 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
3339 | @@ -44,6 +44,8 @@ | |||
3340 | 44 | const QString &contactId = QString::null, | 44 | const QString &contactId = QString::null, |
3341 | 45 | const QString &alias = QString::null, | 45 | const QString &alias = QString::null, |
3342 | 46 | const QString &avatar = QString::null, | 46 | const QString &avatar = QString::null, |
3343 | 47 | uint state = 0, | ||
3344 | 48 | uint roles = 0, | ||
3345 | 47 | const QVariantMap &detailProperties = QVariantMap()); | 49 | const QVariantMap &detailProperties = QVariantMap()); |
3346 | 48 | Participant(const Participant &other); | 50 | Participant(const Participant &other); |
3347 | 49 | Participant& operator=(const Participant &other); | 51 | Participant& operator=(const Participant &other); |
3348 | @@ -54,6 +56,8 @@ | |||
3349 | 54 | QString contactId() const; | 56 | QString contactId() const; |
3350 | 55 | QString alias() const; | 57 | QString alias() const; |
3351 | 56 | QString avatar() const; | 58 | QString avatar() const; |
3352 | 59 | uint state() const; | ||
3353 | 60 | uint roles() const; | ||
3354 | 57 | QVariantMap detailProperties() const; | 61 | QVariantMap detailProperties() const; |
3355 | 58 | 62 | ||
3356 | 59 | bool isNull() const; | 63 | bool isNull() const; |
3357 | @@ -75,8 +79,9 @@ | |||
3358 | 75 | QStringList identifiers() const; | 79 | QStringList identifiers() const; |
3359 | 76 | static Participants fromVariant(const QVariant &variant); | 80 | static Participants fromVariant(const QVariant &variant); |
3360 | 77 | static Participants fromVariantList(const QVariantList &list); | 81 | static Participants fromVariantList(const QVariantList &list); |
3361 | 82 | static Participants fromStringList(const QStringList &list); | ||
3362 | 78 | QVariantList toVariantList() const; | 83 | QVariantList toVariantList() const; |
3364 | 79 | 84 | History::Participants filterByState(uint state) const; | |
3365 | 80 | }; | 85 | }; |
3366 | 81 | 86 | ||
3367 | 82 | const QDBusArgument &operator>>(const QDBusArgument &argument, Participants &participants); | 87 | const QDBusArgument &operator>>(const QDBusArgument &argument, Participants &participants); |
3368 | 83 | 88 | ||
3369 | === modified file 'src/participant_p.h' | |||
3370 | --- src/participant_p.h 2015-09-28 18:53:49 +0000 | |||
3371 | +++ src/participant_p.h 2016-11-24 12:52:24 +0000 | |||
3372 | @@ -39,6 +39,8 @@ | |||
3373 | 39 | const QString &theContactId = QString::null, | 39 | const QString &theContactId = QString::null, |
3374 | 40 | const QString &theAlias = QString::null, | 40 | const QString &theAlias = QString::null, |
3375 | 41 | const QString &theAvatar = QString::null, | 41 | const QString &theAvatar = QString::null, |
3376 | 42 | uint theState = 0, | ||
3377 | 43 | uint theRoles = 0, | ||
3378 | 42 | const QVariantMap &theDetailProperties = QVariantMap()); | 44 | const QVariantMap &theDetailProperties = QVariantMap()); |
3379 | 43 | virtual ~ParticipantPrivate(); | 45 | virtual ~ParticipantPrivate(); |
3380 | 44 | 46 | ||
3381 | @@ -47,6 +49,8 @@ | |||
3382 | 47 | QString contactId; | 49 | QString contactId; |
3383 | 48 | QString alias; | 50 | QString alias; |
3384 | 49 | QString avatar; | 51 | QString avatar; |
3385 | 52 | uint state; | ||
3386 | 53 | uint roles; | ||
3387 | 50 | QVariantMap detailProperties; | 54 | QVariantMap detailProperties; |
3388 | 51 | }; | 55 | }; |
3389 | 52 | 56 | ||
3390 | 53 | 57 | ||
3391 | === modified file 'src/plugin.h' | |||
3392 | --- src/plugin.h 2015-09-28 22:23:09 +0000 | |||
3393 | +++ src/plugin.h 2016-11-24 12:52:24 +0000 | |||
3394 | @@ -1,5 +1,5 @@ | |||
3395 | 1 | /* | 1 | /* |
3397 | 2 | * Copyright (C) 2013 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
3398 | 3 | * | 3 | * |
3399 | 4 | * Authors: | 4 | * Authors: |
3400 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
3401 | @@ -61,11 +61,19 @@ | |||
3402 | 61 | EventType type, | 61 | EventType type, |
3403 | 62 | const QStringList &participants, | 62 | const QStringList &participants, |
3404 | 63 | History::MatchFlags matchFlags = History::MatchCaseSensitive) = 0; | 63 | History::MatchFlags matchFlags = History::MatchCaseSensitive) = 0; |
3405 | 64 | virtual QVariantMap threadForProperties(const QString &accountId, | ||
3406 | 65 | EventType type, | ||
3407 | 66 | const QVariantMap &properties, | ||
3408 | 67 | History::MatchFlags matchFlags = History::MatchCaseSensitive) = 0; | ||
3409 | 64 | 68 | ||
3410 | 65 | virtual QList<QVariantMap> eventsForThread(const QVariantMap &thread) = 0; | 69 | virtual QList<QVariantMap> eventsForThread(const QVariantMap &thread) = 0; |
3411 | 66 | 70 | ||
3412 | 67 | // Writer part of the plugin | 71 | // Writer part of the plugin |
3413 | 68 | virtual QVariantMap createThreadForParticipants(const QString &accountId, EventType type, const QStringList &participants) { return QVariantMap(); } | 72 | virtual QVariantMap createThreadForParticipants(const QString &accountId, EventType type, const QStringList &participants) { return QVariantMap(); } |
3414 | 73 | virtual QVariantMap createThreadForProperties(const QString &accountId, EventType type, const QVariantMap &properties) { return QVariantMap(); } | ||
3415 | 74 | virtual bool updateRoomParticipants(const QString &accountId, const QString &threadId, History::EventType type, const QVariantList &participants) { return false; }; | ||
3416 | 75 | virtual bool updateRoomParticipantsRoles(const QString &accountId, const QString &threadId, History::EventType type, const QVariantMap &participantsRoles) { return false; }; | ||
3417 | 76 | virtual bool updateRoomInfo(const QString &accountId, const QString &threadId, EventType type, const QVariantMap &properties, const QStringList &invalidated = QStringList()) { return false; }; | ||
3418 | 69 | virtual bool removeThread(const QVariantMap &thread) { return false; } | 77 | virtual bool removeThread(const QVariantMap &thread) { return false; } |
3419 | 70 | 78 | ||
3420 | 71 | virtual EventWriteResult writeTextEvent(const QVariantMap &event) { return EventWriteError; } | 79 | virtual EventWriteResult writeTextEvent(const QVariantMap &event) { return EventWriteError; } |
3421 | 72 | 80 | ||
3422 | === modified file 'src/plugineventview.cpp' | |||
3423 | --- src/plugineventview.cpp 2013-11-19 17:52:53 +0000 | |||
3424 | +++ src/plugineventview.cpp 2016-11-24 12:52:24 +0000 | |||
3425 | @@ -56,7 +56,6 @@ | |||
3426 | 56 | 56 | ||
3427 | 57 | void PluginEventView::Destroy() | 57 | void PluginEventView::Destroy() |
3428 | 58 | { | 58 | { |
3429 | 59 | qDebug() << __PRETTY_FUNCTION__; | ||
3430 | 60 | Q_D(PluginEventView); | 59 | Q_D(PluginEventView); |
3431 | 61 | deleteLater(); | 60 | deleteLater(); |
3432 | 62 | } | 61 | } |
3433 | 63 | 62 | ||
3434 | === modified file 'src/pluginthreadview.cpp' | |||
3435 | --- src/pluginthreadview.cpp 2013-11-19 17:52:53 +0000 | |||
3436 | +++ src/pluginthreadview.cpp 2016-11-24 12:52:24 +0000 | |||
3437 | @@ -56,7 +56,6 @@ | |||
3438 | 56 | 56 | ||
3439 | 57 | void PluginThreadView::Destroy() | 57 | void PluginThreadView::Destroy() |
3440 | 58 | { | 58 | { |
3441 | 59 | qDebug() << __PRETTY_FUNCTION__; | ||
3442 | 60 | Q_D(PluginThreadView); | 59 | Q_D(PluginThreadView); |
3443 | 61 | deleteLater(); | 60 | deleteLater(); |
3444 | 62 | } | 61 | } |
3445 | 63 | 62 | ||
3446 | === modified file 'src/textevent.cpp' | |||
3447 | --- src/textevent.cpp 2015-09-28 23:13:21 +0000 | |||
3448 | +++ src/textevent.cpp 2016-11-24 12:52:24 +0000 | |||
3449 | @@ -47,10 +47,11 @@ | |||
3450 | 47 | MessageStatus theMessageStatus, | 47 | MessageStatus theMessageStatus, |
3451 | 48 | const QDateTime &theReadTimestamp, | 48 | const QDateTime &theReadTimestamp, |
3452 | 49 | const QString &theSubject, | 49 | const QString &theSubject, |
3453 | 50 | InformationType theInformationType, | ||
3454 | 50 | const TextEventAttachments &theAttachments, const Participants &theParticipants) : | 51 | const TextEventAttachments &theAttachments, const Participants &theParticipants) : |
3455 | 51 | EventPrivate(theAccountId, theThreadId, theEventId, theSender, theTimestamp, theNewEvent, theParticipants), | 52 | EventPrivate(theAccountId, theThreadId, theEventId, theSender, theTimestamp, theNewEvent, theParticipants), |
3456 | 52 | message(theMessage), messageType(theMessageType), messageStatus(theMessageStatus), | 53 | message(theMessage), messageType(theMessageType), messageStatus(theMessageStatus), |
3458 | 53 | readTimestamp(theReadTimestamp), subject(theSubject), attachments(theAttachments) | 54 | readTimestamp(theReadTimestamp), subject(theSubject), informationType(theInformationType), attachments(theAttachments) |
3459 | 54 | { | 55 | { |
3460 | 55 | } | 56 | } |
3461 | 56 | 57 | ||
3462 | @@ -72,6 +73,7 @@ | |||
3463 | 72 | map[FieldMessageStatus] = (int)messageStatus; | 73 | map[FieldMessageStatus] = (int)messageStatus; |
3464 | 73 | map[FieldReadTimestamp] = readTimestamp.toString("yyyy-MM-ddTHH:mm:ss.zzz"); | 74 | map[FieldReadTimestamp] = readTimestamp.toString("yyyy-MM-ddTHH:mm:ss.zzz"); |
3465 | 74 | map[FieldSubject] = subject; | 75 | map[FieldSubject] = subject; |
3466 | 76 | map[FieldInformationType] = informationType; | ||
3467 | 75 | 77 | ||
3468 | 76 | QList<QVariantMap> attachmentsMap; | 78 | QList<QVariantMap> attachmentsMap; |
3469 | 77 | Q_FOREACH(const TextEventAttachment &attachment, attachments) { | 79 | Q_FOREACH(const TextEventAttachment &attachment, attachments) { |
3470 | @@ -102,10 +104,11 @@ | |||
3471 | 102 | MessageStatus messageStatus, | 104 | MessageStatus messageStatus, |
3472 | 103 | const QDateTime &readTimestamp, | 105 | const QDateTime &readTimestamp, |
3473 | 104 | const QString &subject, | 106 | const QString &subject, |
3474 | 107 | InformationType informationType, | ||
3475 | 105 | const TextEventAttachments &attachments, | 108 | const TextEventAttachments &attachments, |
3476 | 106 | const Participants &participants) | 109 | const Participants &participants) |
3477 | 107 | : Event(*new TextEventPrivate(accountId, threadId, eventId, sender, timestamp, newEvent, | 110 | : Event(*new TextEventPrivate(accountId, threadId, eventId, sender, timestamp, newEvent, |
3479 | 108 | message, messageType, messageStatus, readTimestamp, subject, | 111 | message, messageType, messageStatus, readTimestamp, subject, informationType, |
3480 | 109 | attachments, participants)) | 112 | attachments, participants)) |
3481 | 110 | { | 113 | { |
3482 | 111 | qDBusRegisterMetaType<QList<QVariantMap> >(); | 114 | qDBusRegisterMetaType<QList<QVariantMap> >(); |
3483 | @@ -158,6 +161,12 @@ | |||
3484 | 158 | return d->subject; | 161 | return d->subject; |
3485 | 159 | } | 162 | } |
3486 | 160 | 163 | ||
3487 | 164 | InformationType TextEvent::informationType() const | ||
3488 | 165 | { | ||
3489 | 166 | Q_D(const TextEvent); | ||
3490 | 167 | return d->informationType; | ||
3491 | 168 | } | ||
3492 | 169 | |||
3493 | 161 | TextEventAttachments TextEvent::attachments() const | 170 | TextEventAttachments TextEvent::attachments() const |
3494 | 162 | { | 171 | { |
3495 | 163 | Q_D(const TextEvent); | 172 | Q_D(const TextEvent); |
3496 | @@ -180,6 +189,7 @@ | |||
3497 | 180 | Participants participants = Participants::fromVariant(properties[FieldParticipants]); | 189 | Participants participants = Participants::fromVariant(properties[FieldParticipants]); |
3498 | 181 | QString message = properties[FieldMessage].toString(); | 190 | QString message = properties[FieldMessage].toString(); |
3499 | 182 | QString subject = properties[FieldSubject].toString(); | 191 | QString subject = properties[FieldSubject].toString(); |
3500 | 192 | InformationType informationType = (InformationType) properties[FieldInformationType].toInt(); | ||
3501 | 183 | MessageType messageType = (MessageType) properties[FieldMessageType].toInt(); | 193 | MessageType messageType = (MessageType) properties[FieldMessageType].toInt(); |
3502 | 184 | MessageStatus messageStatus = (MessageStatus) properties[FieldMessageStatus].toInt(); | 194 | MessageStatus messageStatus = (MessageStatus) properties[FieldMessageStatus].toInt(); |
3503 | 185 | QDateTime readTimestamp = QDateTime::fromString(properties[FieldReadTimestamp].toString(), Qt::ISODate); | 195 | QDateTime readTimestamp = QDateTime::fromString(properties[FieldReadTimestamp].toString(), Qt::ISODate); |
3504 | @@ -203,7 +213,7 @@ | |||
3505 | 203 | 213 | ||
3506 | 204 | // and finally create the event | 214 | // and finally create the event |
3507 | 205 | event = TextEvent(accountId, threadId, eventId, senderId, timestamp, newEvent, | 215 | event = TextEvent(accountId, threadId, eventId, senderId, timestamp, newEvent, |
3509 | 206 | message, messageType, messageStatus, readTimestamp, subject, attachments, participants); | 216 | message, messageType, messageStatus, readTimestamp, subject, informationType, attachments, participants); |
3510 | 207 | return event; | 217 | return event; |
3511 | 208 | } | 218 | } |
3512 | 209 | 219 | ||
3513 | 210 | 220 | ||
3514 | === modified file 'src/textevent.h' | |||
3515 | --- src/textevent.h 2015-09-28 23:13:21 +0000 | |||
3516 | +++ src/textevent.h 2016-11-24 12:52:24 +0000 | |||
3517 | @@ -49,6 +49,7 @@ | |||
3518 | 49 | MessageStatus messageStatus = MessageStatusUnknown, | 49 | MessageStatus messageStatus = MessageStatusUnknown, |
3519 | 50 | const QDateTime &readTimestamp = QDateTime(), | 50 | const QDateTime &readTimestamp = QDateTime(), |
3520 | 51 | const QString &subject = QString(), | 51 | const QString &subject = QString(), |
3521 | 52 | InformationType informationType = InformationTypeNone, | ||
3522 | 52 | const TextEventAttachments &attachments = TextEventAttachments(), | 53 | const TextEventAttachments &attachments = TextEventAttachments(), |
3523 | 53 | const Participants &participants = Participants()); | 54 | const Participants &participants = Participants()); |
3524 | 54 | 55 | ||
3525 | @@ -65,6 +66,7 @@ | |||
3526 | 65 | QDateTime readTimestamp() const; | 66 | QDateTime readTimestamp() const; |
3527 | 66 | void setReadTimestamp(const QDateTime &value); | 67 | void setReadTimestamp(const QDateTime &value); |
3528 | 67 | QString subject() const; | 68 | QString subject() const; |
3529 | 69 | InformationType informationType() const; | ||
3530 | 68 | TextEventAttachments attachments() const; | 70 | TextEventAttachments attachments() const; |
3531 | 69 | 71 | ||
3532 | 70 | static Event fromProperties(const QVariantMap &properties); | 72 | static Event fromProperties(const QVariantMap &properties); |
3533 | 71 | 73 | ||
3534 | === modified file 'src/textevent_p.h' | |||
3535 | --- src/textevent_p.h 2015-09-28 23:13:21 +0000 | |||
3536 | +++ src/textevent_p.h 2016-11-24 12:52:24 +0000 | |||
3537 | @@ -45,6 +45,7 @@ | |||
3538 | 45 | MessageStatus theMessageStatus, | 45 | MessageStatus theMessageStatus, |
3539 | 46 | const QDateTime &theReadTimestamp, | 46 | const QDateTime &theReadTimestamp, |
3540 | 47 | const QString &theSubject, | 47 | const QString &theSubject, |
3541 | 48 | InformationType theInformationType, | ||
3542 | 48 | const TextEventAttachments &theAttachments, | 49 | const TextEventAttachments &theAttachments, |
3543 | 49 | const Participants &theParticipants); | 50 | const Participants &theParticipants); |
3544 | 50 | ~TextEventPrivate(); | 51 | ~TextEventPrivate(); |
3545 | @@ -53,6 +54,7 @@ | |||
3546 | 53 | MessageStatus messageStatus; | 54 | MessageStatus messageStatus; |
3547 | 54 | QDateTime readTimestamp; | 55 | QDateTime readTimestamp; |
3548 | 55 | QString subject; | 56 | QString subject; |
3549 | 57 | InformationType informationType; | ||
3550 | 56 | TextEventAttachments attachments; | 58 | TextEventAttachments attachments; |
3551 | 57 | 59 | ||
3552 | 58 | EventType type() const; | 60 | EventType type() const; |
3553 | 59 | 61 | ||
3554 | === modified file 'src/thread.cpp' | |||
3555 | --- src/thread.cpp 2015-10-08 19:35:40 +0000 | |||
3556 | +++ src/thread.cpp 2016-11-24 12:52:24 +0000 | |||
3557 | @@ -1,5 +1,5 @@ | |||
3558 | 1 | /* | 1 | /* |
3560 | 2 | * Copyright (C) 2013-2015 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
3561 | 3 | * | 3 | * |
3562 | 4 | * Authors: | 4 | * Authors: |
3563 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
3564 | @@ -38,14 +38,18 @@ | |||
3565 | 38 | } | 38 | } |
3566 | 39 | 39 | ||
3567 | 40 | ThreadPrivate::ThreadPrivate(const QString &theAccountId, | 40 | ThreadPrivate::ThreadPrivate(const QString &theAccountId, |
3576 | 41 | const QString &theThreadId, EventType theType, | 41 | const QString &theThreadId, EventType theType, |
3577 | 42 | const Participants &theParticipants, | 42 | const Participants &theParticipants, |
3578 | 43 | const Event &theLastEvent, | 43 | const QDateTime &theTimestamp, |
3579 | 44 | int theCount, | 44 | const Event &theLastEvent, |
3580 | 45 | int theUnreadCount, | 45 | int theCount, |
3581 | 46 | const Threads &theGroupedThreads) : | 46 | int theUnreadCount, |
3582 | 47 | accountId(theAccountId), threadId(theThreadId), type(theType), participants(theParticipants), | 47 | const Threads &theGroupedThreads, |
3583 | 48 | lastEvent(theLastEvent), count(theCount), unreadCount(theUnreadCount), groupedThreads(theGroupedThreads) | 48 | ChatType theChatType, |
3584 | 49 | const QVariantMap &theChatRoomInfo) : | ||
3585 | 50 | accountId(theAccountId), threadId(theThreadId), type(theType), participants(theParticipants), timestamp(theTimestamp), | ||
3586 | 51 | lastEvent(theLastEvent), count(theCount), unreadCount(theUnreadCount), groupedThreads(theGroupedThreads), | ||
3587 | 52 | chatType(theChatType), chatRoomInfo(theChatRoomInfo) | ||
3588 | 49 | { | 53 | { |
3589 | 50 | } | 54 | } |
3590 | 51 | 55 | ||
3591 | @@ -63,11 +67,14 @@ | |||
3592 | 63 | Thread::Thread(const QString &accountId, | 67 | Thread::Thread(const QString &accountId, |
3593 | 64 | const QString &threadId, EventType type, | 68 | const QString &threadId, EventType type, |
3594 | 65 | const Participants &participants, | 69 | const Participants &participants, |
3595 | 70 | const QDateTime ×tamp, | ||
3596 | 66 | const Event &lastEvent, | 71 | const Event &lastEvent, |
3597 | 67 | int count, | 72 | int count, |
3598 | 68 | int unreadCount, | 73 | int unreadCount, |
3601 | 69 | const Threads &groupedThreads) | 74 | const Threads &groupedThreads, |
3602 | 70 | : d_ptr(new ThreadPrivate(accountId, threadId, type, participants, lastEvent, count, unreadCount, groupedThreads)) | 75 | ChatType chatType, |
3603 | 76 | const QVariantMap &chatRoomInfo) | ||
3604 | 77 | : d_ptr(new ThreadPrivate(accountId, threadId, type, participants, timestamp, lastEvent, count, unreadCount, groupedThreads, chatType, chatRoomInfo)) | ||
3605 | 71 | { | 78 | { |
3606 | 72 | qDBusRegisterMetaType<QList<QVariantMap> >(); | 79 | qDBusRegisterMetaType<QList<QVariantMap> >(); |
3607 | 73 | qRegisterMetaType<QList<QVariantMap> >(); | 80 | qRegisterMetaType<QList<QVariantMap> >(); |
3608 | @@ -115,6 +122,12 @@ | |||
3609 | 115 | return d->participants; | 122 | return d->participants; |
3610 | 116 | } | 123 | } |
3611 | 117 | 124 | ||
3612 | 125 | QDateTime Thread::timestamp() const | ||
3613 | 126 | { | ||
3614 | 127 | Q_D(const Thread); | ||
3615 | 128 | return d->timestamp; | ||
3616 | 129 | } | ||
3617 | 130 | |||
3618 | 118 | Event Thread::lastEvent() const | 131 | Event Thread::lastEvent() const |
3619 | 119 | { | 132 | { |
3620 | 120 | Q_D(const Thread); | 133 | Q_D(const Thread); |
3621 | @@ -139,6 +152,18 @@ | |||
3622 | 139 | return d->groupedThreads; | 152 | return d->groupedThreads; |
3623 | 140 | } | 153 | } |
3624 | 141 | 154 | ||
3625 | 155 | ChatType Thread::chatType() const | ||
3626 | 156 | { | ||
3627 | 157 | Q_D(const Thread); | ||
3628 | 158 | return d->chatType; | ||
3629 | 159 | } | ||
3630 | 160 | |||
3631 | 161 | QVariantMap Thread::chatRoomInfo() const | ||
3632 | 162 | { | ||
3633 | 163 | Q_D(const Thread); | ||
3634 | 164 | return d->chatRoomInfo; | ||
3635 | 165 | } | ||
3636 | 166 | |||
3637 | 142 | bool Thread::isNull() const | 167 | bool Thread::isNull() const |
3638 | 143 | { | 168 | { |
3639 | 144 | Q_D(const Thread); | 169 | Q_D(const Thread); |
3640 | @@ -182,11 +207,14 @@ | |||
3641 | 182 | map[FieldAccountId] = d->accountId; | 207 | map[FieldAccountId] = d->accountId; |
3642 | 183 | map[FieldThreadId] = d->threadId; | 208 | map[FieldThreadId] = d->threadId; |
3643 | 184 | map[FieldType] = d->type; | 209 | map[FieldType] = d->type; |
3644 | 210 | map[FieldChatType] = d->chatType; | ||
3645 | 185 | map[FieldParticipants] = d->participants.toVariantList(); | 211 | map[FieldParticipants] = d->participants.toVariantList(); |
3646 | 212 | map[FieldTimestamp] = d->timestamp; | ||
3647 | 186 | map[FieldCount] = d->count; | 213 | map[FieldCount] = d->count; |
3648 | 187 | map[FieldUnreadCount] = d->unreadCount; | 214 | map[FieldUnreadCount] = d->unreadCount; |
3649 | 188 | map[FieldLastEventId] = lastEvent().eventId(); | 215 | map[FieldLastEventId] = lastEvent().eventId(); |
3651 | 189 | map[FieldLastEventTimestamp] = lastEvent().timestamp(); | 216 | map[FieldLastEventTimestamp] = d->timestamp; |
3652 | 217 | map[FieldChatRoomInfo] = d->chatRoomInfo; | ||
3653 | 190 | 218 | ||
3654 | 191 | QList<QVariantMap> groupedThreads; | 219 | QList<QVariantMap> groupedThreads; |
3655 | 192 | Q_FOREACH(const Thread &thread, d->groupedThreads) { | 220 | Q_FOREACH(const Thread &thread, d->groupedThreads) { |
3656 | @@ -210,8 +238,9 @@ | |||
3657 | 210 | QString accountId = properties[FieldAccountId].toString(); | 238 | QString accountId = properties[FieldAccountId].toString(); |
3658 | 211 | QString threadId = properties[FieldThreadId].toString(); | 239 | QString threadId = properties[FieldThreadId].toString(); |
3659 | 212 | EventType type = (EventType) properties[FieldType].toInt(); | 240 | EventType type = (EventType) properties[FieldType].toInt(); |
3661 | 213 | 241 | ChatType chatType = (ChatType) properties[FieldChatType].toInt(); | |
3662 | 214 | Participants participants = Participants::fromVariant(properties[FieldParticipants]); | 242 | Participants participants = Participants::fromVariant(properties[FieldParticipants]); |
3663 | 243 | QDateTime timestamp = QDateTime::fromString(properties[FieldTimestamp].toString(), Qt::ISODate); | ||
3664 | 215 | int count = properties[FieldCount].toInt(); | 244 | int count = properties[FieldCount].toInt(); |
3665 | 216 | int unreadCount = properties[FieldUnreadCount].toInt(); | 245 | int unreadCount = properties[FieldUnreadCount].toInt(); |
3666 | 217 | 246 | ||
3667 | @@ -227,6 +256,11 @@ | |||
3668 | 227 | argument >> groupedThreads; | 256 | argument >> groupedThreads; |
3669 | 228 | } | 257 | } |
3670 | 229 | } | 258 | } |
3671 | 259 | QVariantMap chatRoomInfo = qdbus_cast<QVariantMap>(properties[FieldChatRoomInfo]); | ||
3672 | 260 | // dbus_cast fails if the map was generated by a qml app, so we demarshal it by hand | ||
3673 | 261 | if (chatRoomInfo.isEmpty()) { | ||
3674 | 262 | chatRoomInfo = properties[FieldChatRoomInfo].toMap(); | ||
3675 | 263 | } | ||
3676 | 230 | 264 | ||
3677 | 231 | Event event; | 265 | Event event; |
3678 | 232 | switch (type) { | 266 | switch (type) { |
3679 | @@ -237,7 +271,7 @@ | |||
3680 | 237 | event = VoiceEvent::fromProperties(properties); | 271 | event = VoiceEvent::fromProperties(properties); |
3681 | 238 | break; | 272 | break; |
3682 | 239 | } | 273 | } |
3684 | 240 | return Thread(accountId, threadId, type, participants, event, count, unreadCount, groupedThreads); | 274 | return Thread(accountId, threadId, type, participants, timestamp, event, count, unreadCount, groupedThreads, chatType, chatRoomInfo); |
3685 | 241 | } | 275 | } |
3686 | 242 | 276 | ||
3687 | 243 | const QDBusArgument &operator>>(const QDBusArgument &argument, Threads &threads) | 277 | const QDBusArgument &operator>>(const QDBusArgument &argument, Threads &threads) |
3688 | 244 | 278 | ||
3689 | === modified file 'src/thread.h' | |||
3690 | --- src/thread.h 2015-10-08 19:35:40 +0000 | |||
3691 | +++ src/thread.h 2016-11-24 12:52:24 +0000 | |||
3692 | @@ -1,5 +1,5 @@ | |||
3693 | 1 | /* | 1 | /* |
3695 | 2 | * Copyright (C) 2013-2015 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
3696 | 3 | * | 3 | * |
3697 | 4 | * Authors: | 4 | * Authors: |
3698 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
3699 | @@ -51,10 +51,13 @@ | |||
3700 | 51 | const QString &threadId, | 51 | const QString &threadId, |
3701 | 52 | EventType type, | 52 | EventType type, |
3702 | 53 | const Participants &participants, | 53 | const Participants &participants, |
3703 | 54 | const QDateTime ×tamp = QDateTime(), | ||
3704 | 54 | const Event &lastEvent = Event(), | 55 | const Event &lastEvent = Event(), |
3705 | 55 | int count = 0, | 56 | int count = 0, |
3706 | 56 | int unreadCount = 0, | 57 | int unreadCount = 0, |
3708 | 57 | const Threads &groupedThreads = Threads()); | 58 | const Threads &groupedThreads = Threads(), |
3709 | 59 | ChatType chatType = ChatTypeNone, | ||
3710 | 60 | const QVariantMap &chatRoomInfo = QVariantMap()); | ||
3711 | 58 | Thread(const Thread &other); | 61 | Thread(const Thread &other); |
3712 | 59 | virtual ~Thread(); | 62 | virtual ~Thread(); |
3713 | 60 | Thread& operator=(const Thread &other); | 63 | Thread& operator=(const Thread &other); |
3714 | @@ -63,10 +66,13 @@ | |||
3715 | 63 | QString threadId() const; | 66 | QString threadId() const; |
3716 | 64 | EventType type() const; | 67 | EventType type() const; |
3717 | 65 | Participants participants() const; | 68 | Participants participants() const; |
3718 | 69 | QDateTime timestamp() const; | ||
3719 | 66 | Event lastEvent() const; | 70 | Event lastEvent() const; |
3720 | 67 | int count() const; | 71 | int count() const; |
3721 | 68 | int unreadCount() const; | 72 | int unreadCount() const; |
3722 | 73 | ChatType chatType() const; | ||
3723 | 69 | Threads groupedThreads() const; | 74 | Threads groupedThreads() const; |
3724 | 75 | QVariantMap chatRoomInfo() const; | ||
3725 | 70 | 76 | ||
3726 | 71 | bool isNull() const; | 77 | bool isNull() const; |
3727 | 72 | bool operator==(const Thread &other) const; | 78 | bool operator==(const Thread &other) const; |
3728 | 73 | 79 | ||
3729 | === modified file 'src/thread_p.h' | |||
3730 | --- src/thread_p.h 2015-10-08 19:35:40 +0000 | |||
3731 | +++ src/thread_p.h 2016-11-24 12:52:24 +0000 | |||
3732 | @@ -1,5 +1,5 @@ | |||
3733 | 1 | /* | 1 | /* |
3735 | 2 | * Copyright (C) 2013-2015 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
3736 | 3 | * | 3 | * |
3737 | 4 | * Authors: | 4 | * Authors: |
3738 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
3739 | @@ -38,20 +38,26 @@ | |||
3740 | 38 | const QString &theThreadId, | 38 | const QString &theThreadId, |
3741 | 39 | EventType theType, | 39 | EventType theType, |
3742 | 40 | const Participants &theParticipants, | 40 | const Participants &theParticipants, |
3743 | 41 | const QDateTime &theTimestamp, | ||
3744 | 41 | const Event &theLastEvent, | 42 | const Event &theLastEvent, |
3745 | 42 | int theCount, | 43 | int theCount, |
3746 | 43 | int theUnreadCount, | 44 | int theUnreadCount, |
3748 | 44 | const Threads &theGroupedThreads); | 45 | const Threads &theGroupedThreads, |
3749 | 46 | ChatType chatType, | ||
3750 | 47 | const QVariantMap &chatRoomInfo); | ||
3751 | 45 | virtual ~ThreadPrivate(); | 48 | virtual ~ThreadPrivate(); |
3752 | 46 | 49 | ||
3753 | 47 | QString accountId; | 50 | QString accountId; |
3754 | 48 | QString threadId; | 51 | QString threadId; |
3755 | 49 | Participants participants; | 52 | Participants participants; |
3756 | 50 | EventType type; | 53 | EventType type; |
3757 | 54 | QDateTime timestamp; | ||
3758 | 51 | Event lastEvent; | 55 | Event lastEvent; |
3759 | 52 | int count; | 56 | int count; |
3760 | 53 | int unreadCount; | 57 | int unreadCount; |
3761 | 54 | Threads groupedThreads; | 58 | Threads groupedThreads; |
3762 | 59 | ChatType chatType; | ||
3763 | 60 | QVariantMap chatRoomInfo; | ||
3764 | 55 | }; | 61 | }; |
3765 | 56 | 62 | ||
3766 | 57 | } | 63 | } |
3767 | 58 | 64 | ||
3768 | === modified file 'src/types.h' | |||
3769 | --- src/types.h 2015-10-08 12:28:23 +0000 | |||
3770 | +++ src/types.h 2016-11-24 12:52:24 +0000 | |||
3771 | @@ -1,5 +1,5 @@ | |||
3772 | 1 | /* | 1 | /* |
3774 | 2 | * Copyright (C) 2013 Canonical, Ltd. | 2 | * Copyright (C) 2013-2016 Canonical, Ltd. |
3775 | 3 | * | 3 | * |
3776 | 4 | * Authors: | 4 | * Authors: |
3777 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
3778 | @@ -75,6 +75,32 @@ | |||
3779 | 75 | MessageTypeInformation = 2 | 75 | MessageTypeInformation = 2 |
3780 | 76 | }; | 76 | }; |
3781 | 77 | 77 | ||
3782 | 78 | enum InformationType | ||
3783 | 79 | { | ||
3784 | 80 | InformationTypeNone = 0, | ||
3785 | 81 | InformationTypeSimChange = 1, | ||
3786 | 82 | InformationTypeText = 2, | ||
3787 | 83 | InformationTypeSelfJoined = 3, | ||
3788 | 84 | InformationTypeJoined = 4, | ||
3789 | 85 | InformationTypeTitleChanged = 5, | ||
3790 | 86 | InformationTypeInvitationSent = 6, | ||
3791 | 87 | InformationTypeLeaving = 7, | ||
3792 | 88 | InformationTypeSelfLeaving = 8, | ||
3793 | 89 | InformationTypeAdminGranted = 9, | ||
3794 | 90 | InformationTypeAdminRemoved = 10, | ||
3795 | 91 | InformationTypeSelfAdminGranted = 11, | ||
3796 | 92 | InformationTypeSelfAdminRemoved = 12, | ||
3797 | 93 | InformationTypeSelfKicked = 13, | ||
3798 | 94 | InformationTypeGroupGone = 14 | ||
3799 | 95 | }; | ||
3800 | 96 | |||
3801 | 97 | enum ChatType | ||
3802 | 98 | { | ||
3803 | 99 | ChatTypeNone = 0, | ||
3804 | 100 | ChatTypeContact = 1, | ||
3805 | 101 | ChatTypeRoom = 2 | ||
3806 | 102 | }; | ||
3807 | 103 | |||
3808 | 78 | // FIXME (boiko): I think this needs to be changed to a simple enum and not flags, | 104 | // FIXME (boiko): I think this needs to be changed to a simple enum and not flags, |
3809 | 79 | // as the statuses are mutually exclusive | 105 | // as the statuses are mutually exclusive |
3810 | 80 | enum AttachmentFlag | 106 | enum AttachmentFlag |
3811 | @@ -86,6 +112,20 @@ | |||
3812 | 86 | 112 | ||
3813 | 87 | Q_DECLARE_FLAGS(AttachmentFlags, AttachmentFlag) | 113 | Q_DECLARE_FLAGS(AttachmentFlags, AttachmentFlag) |
3814 | 88 | 114 | ||
3815 | 115 | enum ParticipantState | ||
3816 | 116 | { | ||
3817 | 117 | ParticipantStateRegular = 0, | ||
3818 | 118 | ParticipantStateLocalPending = 1, | ||
3819 | 119 | ParticipantStateRemotePending = 2 | ||
3820 | 120 | }; | ||
3821 | 121 | |||
3822 | 122 | enum ParticipantRoles | ||
3823 | 123 | { | ||
3824 | 124 | ParticipantRoleNone = 0, | ||
3825 | 125 | ParticipantRoleMember = 1, | ||
3826 | 126 | ParticipantRoleAdmin = 2 | ||
3827 | 127 | }; | ||
3828 | 128 | |||
3829 | 89 | // Event writing results | 129 | // Event writing results |
3830 | 90 | enum EventWriteResult { | 130 | enum EventWriteResult { |
3831 | 91 | EventWriteCreated, | 131 | EventWriteCreated, |
3832 | @@ -106,12 +146,35 @@ | |||
3833 | 106 | static const char* FieldEventId = "eventId"; | 146 | static const char* FieldEventId = "eventId"; |
3834 | 107 | static const char* FieldType = "type"; | 147 | static const char* FieldType = "type"; |
3835 | 108 | static const char* FieldParticipants = "participants"; | 148 | static const char* FieldParticipants = "participants"; |
3836 | 149 | static const char* FieldParticipantIds = "participantIds"; | ||
3837 | 109 | static const char* FieldCount = "count"; | 150 | static const char* FieldCount = "count"; |
3838 | 110 | static const char* FieldUnreadCount = "unreadCount"; | 151 | static const char* FieldUnreadCount = "unreadCount"; |
3839 | 111 | static const char* FieldSenderId = "senderId"; | 152 | static const char* FieldSenderId = "senderId"; |
3840 | 112 | static const char* FieldTimestamp = "timestamp"; | 153 | static const char* FieldTimestamp = "timestamp"; |
3841 | 113 | static const char* FieldDate = "date"; | 154 | static const char* FieldDate = "date"; |
3842 | 114 | static const char* FieldNewEvent = "newEvent"; | 155 | static const char* FieldNewEvent = "newEvent"; |
3843 | 156 | static const char* FieldChatType = "chatType"; | ||
3844 | 157 | static const char* FieldChatRoomInfo = "chatRoomInfo"; | ||
3845 | 158 | static const char* FieldChatRoomJoined = "joined"; | ||
3846 | 159 | static const char* FieldChatRoomSelfRoles = "selfRoles"; | ||
3847 | 160 | |||
3848 | 161 | // Chat Room Info Fields | ||
3849 | 162 | static const char* FieldChatRoomName = "roomName"; | ||
3850 | 163 | static const char* FieldChatRoomServer = "server"; | ||
3851 | 164 | static const char* FieldChatRoomCreator = "creator"; | ||
3852 | 165 | static const char* FieldChatRoomCreationTimestamp = "creationTimestamp"; | ||
3853 | 166 | static const char* FieldChatRoomAnonymous = "anonymous"; | ||
3854 | 167 | static const char* FieldChatRoomInviteOnly = "inviteOnly"; | ||
3855 | 168 | static const char* FieldChatRoomParticipantLimit = "participantLimit"; | ||
3856 | 169 | static const char* FieldChatRoomModerated = "moderated"; | ||
3857 | 170 | static const char* FieldChatRoomTitle = "title"; | ||
3858 | 171 | static const char* FieldChatRoomDescription = "description"; | ||
3859 | 172 | static const char* FieldChatRoomPersistent = "persistent"; | ||
3860 | 173 | static const char* FieldChatRoomPrivate = "private"; | ||
3861 | 174 | static const char* FieldChatRoomPasswordProtected = "passwordProtected"; | ||
3862 | 175 | static const char* FieldChatRoomPassword = "password"; | ||
3863 | 176 | static const char* FieldChatRoomPasswordHint = "passwordHint"; | ||
3864 | 177 | static const char* FieldChatRoomCanUpdateConfiguration = "canUpdateConfiguration"; | ||
3865 | 115 | 178 | ||
3866 | 116 | // thread fields | 179 | // thread fields |
3867 | 117 | static const char* FieldLastEventId = "lastEventId"; | 180 | static const char* FieldLastEventId = "lastEventId"; |
3868 | @@ -124,6 +187,7 @@ | |||
3869 | 124 | static const char* FieldMessageStatus = "messageStatus"; | 187 | static const char* FieldMessageStatus = "messageStatus"; |
3870 | 125 | static const char* FieldReadTimestamp = "readTimestamp"; | 188 | static const char* FieldReadTimestamp = "readTimestamp"; |
3871 | 126 | static const char* FieldSubject = "subject"; | 189 | static const char* FieldSubject = "subject"; |
3872 | 190 | static const char* FieldInformationType = "informationType"; | ||
3873 | 127 | static const char* FieldAttachments = "attachments"; | 191 | static const char* FieldAttachments = "attachments"; |
3874 | 128 | 192 | ||
3875 | 129 | // text attachment fields | 193 | // text attachment fields |
3876 | @@ -157,6 +221,8 @@ | |||
3877 | 157 | static const char* FieldAvatar = "avatar"; | 221 | static const char* FieldAvatar = "avatar"; |
3878 | 158 | static const char* FieldIdentifier = "identifier"; | 222 | static const char* FieldIdentifier = "identifier"; |
3879 | 159 | static const char* FieldDetailProperties = "detailProperties"; | 223 | static const char* FieldDetailProperties = "detailProperties"; |
3880 | 224 | static const char* FieldParticipantState = "state"; | ||
3881 | 225 | static const char* FieldParticipantRoles = "roles"; | ||
3882 | 160 | 226 | ||
3883 | 161 | } | 227 | } |
3884 | 162 | 228 | ||
3885 | 163 | 229 | ||
3886 | === modified file 'src/utils.cpp' | |||
3887 | --- src/utils.cpp 2015-10-08 19:36:57 +0000 | |||
3888 | +++ src/utils.cpp 2016-11-24 12:52:24 +0000 | |||
3889 | @@ -1,5 +1,5 @@ | |||
3890 | 1 | /* | 1 | /* |
3892 | 2 | * Copyright (C) 2015 Canonical, Ltd. | 2 | * Copyright (C) 2015-2016 Canonical, Ltd. |
3893 | 3 | * | 3 | * |
3894 | 4 | * Authors: | 4 | * Authors: |
3895 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
3896 | @@ -19,10 +19,14 @@ | |||
3897 | 19 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 19 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3898 | 20 | */ | 20 | */ |
3899 | 21 | 21 | ||
3900 | 22 | #include <unistd.h> | ||
3901 | 22 | #include "utils_p.h" | 23 | #include "utils_p.h" |
3902 | 23 | #include "phoneutils_p.h" | 24 | #include "phoneutils_p.h" |
3903 | 24 | #include <QDebug> | 25 | #include <QDebug> |
3904 | 25 | #include <QStringList> | 26 | #include <QStringList> |
3905 | 27 | #include <QDBusInterface> | ||
3906 | 28 | #include <QDBusConnection> | ||
3907 | 29 | #include <QDBusReply> | ||
3908 | 26 | #include <QMap> | 30 | #include <QMap> |
3909 | 27 | 31 | ||
3910 | 28 | namespace History { | 32 | namespace History { |
3911 | @@ -32,9 +36,12 @@ | |||
3912 | 32 | } | 36 | } |
3913 | 33 | 37 | ||
3914 | 34 | // FIXME: find a better way to determine when accounts should be grouped | 38 | // FIXME: find a better way to determine when accounts should be grouped |
3916 | 35 | bool Utils::shouldGroupAccount(const QString &accountId) | 39 | bool Utils::shouldGroupThread(const Thread &thread) |
3917 | 36 | { | 40 | { |
3919 | 37 | return (matchFlagsForAccount(accountId) & MatchPhoneNumber); | 41 | if (protocolFromAccountId(thread.accountId()) == "multimedia") { |
3920 | 42 | return thread.chatType() != History::ChatTypeRoom; | ||
3921 | 43 | } | ||
3922 | 44 | return (matchFlagsForAccount(thread.accountId()) & MatchPhoneNumber); | ||
3923 | 38 | } | 45 | } |
3924 | 39 | 46 | ||
3925 | 40 | MatchFlags Utils::matchFlagsForAccount(const QString &accountId) | 47 | MatchFlags Utils::matchFlagsForAccount(const QString &accountId) |
3926 | @@ -150,4 +157,22 @@ | |||
3927 | 150 | return normalizedId; | 157 | return normalizedId; |
3928 | 151 | } | 158 | } |
3929 | 152 | 159 | ||
3930 | 160 | QVariant Utils::getUserValue(const QString &interface, const QString &propName) | ||
3931 | 161 | { | ||
3932 | 162 | QString uid = QString::number(getuid()); | ||
3933 | 163 | QString activeUser = "/org/freedesktop/Accounts/User" + uid; | ||
3934 | 164 | |||
3935 | 165 | QDBusInterface iface("org.freedesktop.Accounts", | ||
3936 | 166 | activeUser, | ||
3937 | 167 | "org.freedesktop.DBus.Properties", | ||
3938 | 168 | QDBusConnection::systemBus()); | ||
3939 | 169 | QDBusReply<QVariant> reply = iface.call("Get", interface, propName); | ||
3940 | 170 | if (reply.isValid()) { | ||
3941 | 171 | return reply.value(); | ||
3942 | 172 | } else { | ||
3943 | 173 | qWarning() << "Failed to get user property " << propName << " from AccountsService:" << reply.error().message(); | ||
3944 | 174 | } | ||
3945 | 175 | return QVariant(); | ||
3946 | 176 | } | ||
3947 | 177 | |||
3948 | 153 | } | 178 | } |
3949 | 154 | 179 | ||
3950 | === modified file 'src/utils_p.h' | |||
3951 | --- src/utils_p.h 2015-10-02 18:28:47 +0000 | |||
3952 | +++ src/utils_p.h 2016-11-24 12:52:24 +0000 | |||
3953 | @@ -1,5 +1,5 @@ | |||
3954 | 1 | /* | 1 | /* |
3956 | 2 | * Copyright (C) 2015 Canonical, Ltd. | 2 | * Copyright (C) 2015-2016 Canonical, Ltd. |
3957 | 3 | * | 3 | * |
3958 | 4 | * Authors: | 4 | * Authors: |
3959 | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | 5 | * Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
3960 | @@ -23,6 +23,7 @@ | |||
3961 | 23 | #define UTILS_P_H | 23 | #define UTILS_P_H |
3962 | 24 | 24 | ||
3963 | 25 | #include "types.h" | 25 | #include "types.h" |
3964 | 26 | #include "thread.h" | ||
3965 | 26 | 27 | ||
3966 | 27 | namespace History { | 28 | namespace History { |
3967 | 28 | 29 | ||
3968 | @@ -34,8 +35,9 @@ | |||
3969 | 34 | static bool compareIds(const QString &accountId, const QString &id1, const QString & id2); | 35 | static bool compareIds(const QString &accountId, const QString &id1, const QString & id2); |
3970 | 35 | static bool compareParticipants(const QStringList &participants1, const QStringList &participants2, MatchFlags flags); | 36 | static bool compareParticipants(const QStringList &participants1, const QStringList &participants2, MatchFlags flags); |
3971 | 36 | static bool compareNormalizedParticipants(const QStringList &participants1, const QStringList &participants2, MatchFlags flags); | 37 | static bool compareNormalizedParticipants(const QStringList &participants1, const QStringList &participants2, MatchFlags flags); |
3973 | 37 | static bool shouldGroupAccount(const QString &accountId); | 38 | static bool shouldGroupThread(const Thread &thread); |
3974 | 38 | static QString normalizeId(const QString &accountId, const QString &id); | 39 | static QString normalizeId(const QString &accountId, const QString &id); |
3975 | 40 | static QVariant getUserValue(const QString &interface, const QString &propName); | ||
3976 | 39 | 41 | ||
3977 | 40 | private: | 42 | private: |
3978 | 41 | Utils(); | 43 | Utils(); |
3979 | 42 | 44 | ||
3980 | === modified file 'tests/Ubuntu.History/HistoryEventModelTest.cpp' | |||
3981 | --- tests/Ubuntu.History/HistoryEventModelTest.cpp 2016-03-30 16:53:04 +0000 | |||
3982 | +++ tests/Ubuntu.History/HistoryEventModelTest.cpp 2016-11-24 12:52:24 +0000 | |||
3983 | @@ -68,6 +68,7 @@ | |||
3984 | 68 | History::MessageStatusRead, | 68 | History::MessageStatusRead, |
3985 | 69 | QDateTime::currentDateTime(), | 69 | QDateTime::currentDateTime(), |
3986 | 70 | "The subject", | 70 | "The subject", |
3987 | 71 | History::InformationTypeNone, | ||
3988 | 71 | History::TextEventAttachments(), | 72 | History::TextEventAttachments(), |
3989 | 72 | textThread.participants()); | 73 | textThread.participants()); |
3990 | 73 | QVERIFY(mManager->writeEvents(History::Events() << event)); | 74 | QVERIFY(mManager->writeEvents(History::Events() << event)); |
3991 | 74 | 75 | ||
3992 | === modified file 'tests/Ubuntu.History/HistoryGroupedThreadsModelTest.cpp' | |||
3993 | --- tests/Ubuntu.History/HistoryGroupedThreadsModelTest.cpp 2015-10-05 22:54:47 +0000 | |||
3994 | +++ tests/Ubuntu.History/HistoryGroupedThreadsModelTest.cpp 2016-11-24 12:52:24 +0000 | |||
3995 | @@ -123,7 +123,7 @@ | |||
3996 | 123 | 123 | ||
3997 | 124 | // insert another event in second thread | 124 | // insert another event in second thread |
3998 | 125 | History::TextEvent secondEvent = History::TextEvent(textThread.accountId(), textThread.threadId(), QString("eventId2%1").arg(QString::number(qrand() % 1024)), | 125 | History::TextEvent secondEvent = History::TextEvent(textThread.accountId(), textThread.threadId(), QString("eventId2%1").arg(QString::number(qrand() % 1024)), |
4000 | 126 | QString("1234567"), QDateTime::currentDateTime(), false, "Random Message2", | 126 | QString("1234567"), QDateTime::currentDateTime().addSecs(1), false, "Random Message2", |
4001 | 127 | History::MessageTypeText); | 127 | History::MessageTypeText); |
4002 | 128 | mManager->writeEvents(History::Events() << secondEvent); | 128 | mManager->writeEvents(History::Events() << secondEvent); |
4003 | 129 | QTRY_COMPARE(dataChanged.count(), 1); | 129 | QTRY_COMPARE(dataChanged.count(), 1); |
4004 | 130 | 130 | ||
4005 | === modified file 'tests/common/mock/CMakeLists.txt' | |||
4006 | --- tests/common/mock/CMakeLists.txt 2015-04-07 14:40:58 +0000 | |||
4007 | +++ tests/common/mock/CMakeLists.txt 2016-11-24 12:52:24 +0000 | |||
4008 | @@ -16,4 +16,4 @@ | |||
4009 | 16 | 16 | ||
4010 | 17 | add_executable(telepathy-mock ${mock_SRCS}) | 17 | add_executable(telepathy-mock ${mock_SRCS}) |
4011 | 18 | qt5_use_modules(telepathy-mock Core DBus) | 18 | qt5_use_modules(telepathy-mock Core DBus) |
4013 | 19 | target_link_libraries(telepathy-mock ${TP_QT5_LIBRARIES} ${TELEPATHY_QT5_SERVICE_LIBRARIES} ${OFONO_QT_LIBRARIES} ${PULSEAUDIO_LIBRARIES}) | 19 | target_link_libraries(telepathy-mock ${TP_QT5_LIBRARIES} ${TELEPATHY_QT5_SERVICE_LIBRARIES} ${OFONO_QT_LIBRARIES} ${PULSEAUDIO_LIBRARIES} ${Qt5Network_LIBRARIES}) |
4014 | 20 | 20 | ||
4015 | === modified file 'tests/common/mock/callchannel.cpp' | |||
4016 | --- tests/common/mock/callchannel.cpp 2015-06-16 16:16:54 +0000 | |||
4017 | +++ tests/common/mock/callchannel.cpp 2016-11-24 12:52:24 +0000 | |||
4018 | @@ -194,7 +194,8 @@ | |||
4019 | 194 | reason.reason = Tp::CallStateChangeReasonNoAnswer; | 194 | reason.reason = Tp::CallStateChangeReasonNoAnswer; |
4020 | 195 | } | 195 | } |
4021 | 196 | mCallChannel->setCallState(Tp::CallStateEnded, 0, reason, stateDetails); | 196 | mCallChannel->setCallState(Tp::CallStateEnded, 0, reason, stateDetails); |
4023 | 197 | mBaseChannel->close(); | 197 | // leave the channel opened for a bit longer so that the call state gets propagated correctly. |
4024 | 198 | QTimer::singleShot(10, mBaseChannel.data(), &Tp::BaseChannel::close); | ||
4025 | 198 | } else if (state == "active") { | 199 | } else if (state == "active") { |
4026 | 199 | qDebug() << "active"; | 200 | qDebug() << "active"; |
4027 | 200 | mHoldIface->setHoldState(Tp::LocalHoldStateUnheld, Tp::LocalHoldStateReasonNone); | 201 | mHoldIface->setHoldState(Tp::LocalHoldStateUnheld, Tp::LocalHoldStateReasonNone); |
4028 | 201 | 202 | ||
4029 | === modified file 'tests/common/mock/mockconnectiondbus.cpp' | |||
4030 | --- tests/common/mock/mockconnectiondbus.cpp 2015-04-07 14:40:58 +0000 | |||
4031 | +++ tests/common/mock/mockconnectiondbus.cpp 2016-11-24 12:52:24 +0000 | |||
4032 | @@ -70,16 +70,15 @@ | |||
4033 | 70 | 70 | ||
4034 | 71 | bool MockConnectionDBus::connectToBus() | 71 | bool MockConnectionDBus::connectToBus() |
4035 | 72 | { | 72 | { |
4036 | 73 | bool ok = QDBusConnection::sessionBus().registerService("com.canonical.MockConnection"); | ||
4037 | 74 | if (!ok) { | ||
4038 | 75 | return false; | ||
4039 | 76 | } | ||
4040 | 77 | |||
4041 | 78 | if (!mAdaptor) { | 73 | if (!mAdaptor) { |
4042 | 79 | mAdaptor = new MockConnectionAdaptor(this); | 74 | mAdaptor = new MockConnectionAdaptor(this); |
4043 | 80 | } | 75 | } |
4044 | 81 | 76 | ||
4046 | 82 | return QDBusConnection::sessionBus().registerObject(mObjectPath, this); | 77 | if (!QDBusConnection::sessionBus().registerObject(mObjectPath, this)) { |
4047 | 78 | return false; | ||
4048 | 79 | } | ||
4049 | 80 | |||
4050 | 81 | return QDBusConnection::sessionBus().registerService("com.canonical.MockConnection"); | ||
4051 | 83 | } | 82 | } |
4052 | 84 | 83 | ||
4053 | 85 | void MockConnectionDBus::PlaceIncomingMessage(const QString &message, const QVariantMap &properties) | 84 | void MockConnectionDBus::PlaceIncomingMessage(const QString &message, const QVariantMap &properties) |
4054 | 86 | 85 | ||
4055 | === modified file 'tests/common/mock/textchannel.cpp' | |||
4056 | --- tests/common/mock/textchannel.cpp 2015-08-28 10:15:47 +0000 | |||
4057 | +++ tests/common/mock/textchannel.cpp 2016-11-24 12:52:24 +0000 | |||
4058 | @@ -74,7 +74,9 @@ | |||
4059 | 74 | baseChannel->plugInterface(Tp::AbstractChannelInterfacePtr::dynamicCast(mMessagesIface)); | 74 | baseChannel->plugInterface(Tp::AbstractChannelInterfacePtr::dynamicCast(mMessagesIface)); |
4060 | 75 | 75 | ||
4061 | 76 | // group stuff | 76 | // group stuff |
4063 | 77 | mGroupIface = Tp::BaseChannelGroupInterface::create(Tp::ChannelGroupFlagCanAdd, conn->selfHandle()); | 77 | mGroupIface = Tp::BaseChannelGroupInterface::create(); |
4064 | 78 | mGroupIface->setGroupFlags(Tp::ChannelGroupFlagCanAdd); | ||
4065 | 79 | mGroupIface->setSelfHandle(conn->selfHandle()); | ||
4066 | 78 | mGroupIface->setAddMembersCallback(Tp::memFun(this,&MockTextChannel::onAddMembers)); | 80 | mGroupIface->setAddMembersCallback(Tp::memFun(this,&MockTextChannel::onAddMembers)); |
4067 | 79 | mGroupIface->setRemoveMembersCallback(Tp::memFun(this,&MockTextChannel::onRemoveMembers)); | 81 | mGroupIface->setRemoveMembersCallback(Tp::memFun(this,&MockTextChannel::onRemoveMembers)); |
4068 | 80 | baseChannel->plugInterface(Tp::AbstractChannelInterfacePtr::dynamicCast(mGroupIface)); | 82 | baseChannel->plugInterface(Tp::AbstractChannelInterfacePtr::dynamicCast(mGroupIface)); |
4069 | @@ -232,7 +234,7 @@ | |||
4070 | 232 | mMembers << handle; | 234 | mMembers << handle; |
4071 | 233 | } | 235 | } |
4072 | 234 | } | 236 | } |
4074 | 235 | mGroupIface->addMembers(handles, recipients); | 237 | mGroupIface->setMembers(mMembers, QVariantMap()); |
4075 | 236 | } | 238 | } |
4076 | 237 | 239 | ||
4077 | 238 | QStringList MockTextChannel::recipients() const | 240 | QStringList MockTextChannel::recipients() const |
4078 | @@ -250,7 +252,7 @@ | |||
4079 | 250 | addMembers(mConnection->inspectHandles(Tp::HandleTypeContact, handles, error)); | 252 | addMembers(mConnection->inspectHandles(Tp::HandleTypeContact, handles, error)); |
4080 | 251 | } | 253 | } |
4081 | 252 | 254 | ||
4083 | 253 | void MockTextChannel::onRemoveMembers(const Tp::UIntList &handles, const QString &message, Tp::DBusError *error) | 255 | void MockTextChannel::onRemoveMembers(const Tp::UIntList &handles, const QString &message, uint reason, Tp::DBusError *error) |
4084 | 254 | { | 256 | { |
4085 | 255 | Q_FOREACH(uint handle, handles) { | 257 | Q_FOREACH(uint handle, handles) { |
4086 | 256 | Q_FOREACH(const QString &recipient, mConnection->inspectHandles(Tp::HandleTypeContact, Tp::UIntList() << handle, error)) { | 258 | Q_FOREACH(const QString &recipient, mConnection->inspectHandles(Tp::HandleTypeContact, Tp::UIntList() << handle, error)) { |
4087 | @@ -258,5 +260,5 @@ | |||
4088 | 258 | } | 260 | } |
4089 | 259 | mMembers.removeAll(handle); | 261 | mMembers.removeAll(handle); |
4090 | 260 | } | 262 | } |
4092 | 261 | mGroupIface->removeMembers(handles); | 263 | mGroupIface->setMembers(mMembers, QVariantMap()); |
4093 | 262 | } | 264 | } |
4094 | 263 | 265 | ||
4095 | === modified file 'tests/common/mock/textchannel.h' | |||
4096 | --- tests/common/mock/textchannel.h 2015-04-07 14:40:58 +0000 | |||
4097 | +++ tests/common/mock/textchannel.h 2016-11-24 12:52:24 +0000 | |||
4098 | @@ -45,8 +45,8 @@ | |||
4099 | 45 | void addMembers(QStringList recipients); | 45 | void addMembers(QStringList recipients); |
4100 | 46 | QStringList recipients() const; | 46 | QStringList recipients() const; |
4101 | 47 | Tp::UIntList members(); | 47 | Tp::UIntList members(); |
4102 | 48 | void onRemoveMembers(const Tp::UIntList& handles, const QString& message, uint reason, Tp::DBusError* error); | ||
4103 | 48 | void onAddMembers(const Tp::UIntList& handles, const QString& message, Tp::DBusError* error); | 49 | void onAddMembers(const Tp::UIntList& handles, const QString& message, Tp::DBusError* error); |
4104 | 49 | void onRemoveMembers(const Tp::UIntList& handles, const QString& message, Tp::DBusError* error); | ||
4105 | 50 | 50 | ||
4106 | 51 | public Q_SLOTS: | 51 | public Q_SLOTS: |
4107 | 52 | void placeDeliveryReport(const QString &messageId, const QString &status); | 52 | void placeDeliveryReport(const QString &messageId, const QString &status); |
4108 | 53 | 53 | ||
4109 | === modified file 'tests/daemon/CMakeLists.txt' | |||
4110 | --- tests/daemon/CMakeLists.txt 2016-09-09 14:48:33 +0000 | |||
4111 | +++ tests/daemon/CMakeLists.txt 2016-11-24 12:52:24 +0000 | |||
4112 | @@ -5,7 +5,7 @@ | |||
4113 | 5 | ${TP_QT5_INCLUDE_DIRS} | 5 | ${TP_QT5_INCLUDE_DIRS} |
4114 | 6 | ) | 6 | ) |
4115 | 7 | 7 | ||
4120 | 8 | #generate_telepathy_test(DaemonTest | 8 | generate_telepathy_test(DaemonTest |
4121 | 9 | # SOURCES DaemonTest.cpp handler.cpp approver.cpp | 9 | SOURCES DaemonTest.cpp handler.cpp approver.cpp |
4122 | 10 | # TASKS --task ${CMAKE_BINARY_DIR}/daemon/history-daemon --ignore-return --task-name history-daemon | 10 | TASKS --task ${CMAKE_BINARY_DIR}/daemon/history-daemon --ignore-return --task-name history-daemon |
4123 | 11 | # WAIT_FOR com.canonical.HistoryService) | 11 | WAIT_FOR com.canonical.HistoryService) |
4124 | 12 | 12 | ||
4125 | === modified file 'tests/daemon/DaemonTest.cpp' | |||
4126 | --- tests/daemon/DaemonTest.cpp 2015-10-06 12:50:14 +0000 | |||
4127 | +++ tests/daemon/DaemonTest.cpp 2016-11-24 12:52:24 +0000 | |||
4128 | @@ -324,7 +324,7 @@ | |||
4129 | 324 | connect(mAccount->connection()->contactManager()->contactsForIdentifiers(QStringList() << phoneNumber), | 324 | connect(mAccount->connection()->contactManager()->contactsForIdentifiers(QStringList() << phoneNumber), |
4130 | 325 | SIGNAL(finished(Tp::PendingOperation*)), | 325 | SIGNAL(finished(Tp::PendingOperation*)), |
4131 | 326 | SLOT(onPendingContactsFinished(Tp::PendingOperation*))); | 326 | SLOT(onPendingContactsFinished(Tp::PendingOperation*))); |
4133 | 327 | QTRY_COMPARE(spy.count(), 1); | 327 | QVERIFY(spy.wait()); |
4134 | 328 | 328 | ||
4135 | 329 | QList<Tp::ContactPtr> contacts = spy.first().first().value<QList<Tp::ContactPtr> >(); | 329 | QList<Tp::ContactPtr> contacts = spy.first().first().value<QList<Tp::ContactPtr> >(); |
4136 | 330 | QCOMPARE(contacts.count(), 1); | 330 | QCOMPARE(contacts.count(), 1); |
4137 | @@ -335,7 +335,7 @@ | |||
4138 | 335 | Q_FOREACH(Tp::ContactPtr contact, contacts) { | 335 | Q_FOREACH(Tp::ContactPtr contact, contacts) { |
4139 | 336 | mAccount->ensureAudioCall(contact, "audio", QDateTime::currentDateTime(), TP_QT_IFACE_CLIENT + ".HistoryTestHandler"); | 336 | mAccount->ensureAudioCall(contact, "audio", QDateTime::currentDateTime(), TP_QT_IFACE_CLIENT + ".HistoryTestHandler"); |
4140 | 337 | } | 337 | } |
4142 | 338 | QTRY_COMPARE(spyCallChannel.count(), 1); | 338 | QVERIFY(spyCallChannel.wait()); |
4143 | 339 | 339 | ||
4144 | 340 | Tp::CallChannelPtr channel = spyCallChannel.first().first().value<Tp::CallChannelPtr>(); | 340 | Tp::CallChannelPtr channel = spyCallChannel.first().first().value<Tp::CallChannelPtr>(); |
4145 | 341 | QVERIFY(channel); | 341 | QVERIFY(channel); |
4146 | 342 | 342 | ||
4147 | === modified file 'tests/libhistoryservice/ParticipantTest.cpp' | |||
4148 | --- tests/libhistoryservice/ParticipantTest.cpp 2015-10-05 22:20:00 +0000 | |||
4149 | +++ tests/libhistoryservice/ParticipantTest.cpp 2016-11-24 12:52:24 +0000 | |||
4150 | @@ -58,16 +58,20 @@ | |||
4151 | 58 | QString contactId("theContactId"); | 58 | QString contactId("theContactId"); |
4152 | 59 | QString alias("theAlias"); | 59 | QString alias("theAlias"); |
4153 | 60 | QString avatar("theAvatar"); | 60 | QString avatar("theAvatar"); |
4154 | 61 | uint state = History::ParticipantStateRegular; | ||
4155 | 62 | uint roles = History::ParticipantRoleMember; | ||
4156 | 61 | QVariantMap detailProperties; | 63 | QVariantMap detailProperties; |
4157 | 62 | detailProperties["someProperty"] = "someValue"; | 64 | detailProperties["someProperty"] = "someValue"; |
4158 | 63 | 65 | ||
4159 | 64 | 66 | ||
4161 | 65 | History::Participant participant(accountId, identifier, contactId, alias, avatar, detailProperties); | 67 | History::Participant participant(accountId, identifier, contactId, alias, avatar, state, roles, detailProperties); |
4162 | 66 | QCOMPARE(participant.accountId(), accountId); | 68 | QCOMPARE(participant.accountId(), accountId); |
4163 | 67 | QCOMPARE(participant.identifier(), identifier); | 69 | QCOMPARE(participant.identifier(), identifier); |
4164 | 68 | QCOMPARE(participant.contactId(), contactId); | 70 | QCOMPARE(participant.contactId(), contactId); |
4165 | 69 | QCOMPARE(participant.alias(), alias); | 71 | QCOMPARE(participant.alias(), alias); |
4166 | 70 | QCOMPARE(participant.avatar(), avatar); | 72 | QCOMPARE(participant.avatar(), avatar); |
4167 | 73 | QCOMPARE(participant.state(), state); | ||
4168 | 74 | QCOMPARE(participant.roles(), roles); | ||
4169 | 71 | QCOMPARE(participant.detailProperties(), detailProperties); | 75 | QCOMPARE(participant.detailProperties(), detailProperties); |
4170 | 72 | } | 76 | } |
4171 | 73 | 77 | ||
4172 | @@ -105,7 +109,7 @@ | |||
4173 | 105 | { | 109 | { |
4174 | 106 | QVariantMap detailProperties; | 110 | QVariantMap detailProperties; |
4175 | 107 | detailProperties["theProperty"] = "theValue"; | 111 | detailProperties["theProperty"] = "theValue"; |
4177 | 108 | History::Participant original("accountId", "identifier", "contactId", "alias", "avatar", detailProperties); | 112 | History::Participant original("accountId", "identifier", "contactId", "alias", "avatar", History::ParticipantStateRegular, History::ParticipantRoleAdmin, detailProperties); |
4178 | 109 | 113 | ||
4179 | 110 | History::Participant copy(original); | 114 | History::Participant copy(original); |
4180 | 111 | 115 | ||
4181 | @@ -114,6 +118,8 @@ | |||
4182 | 114 | QCOMPARE(copy.contactId(), original.contactId()); | 118 | QCOMPARE(copy.contactId(), original.contactId()); |
4183 | 115 | QCOMPARE(copy.alias(), original.alias()); | 119 | QCOMPARE(copy.alias(), original.alias()); |
4184 | 116 | QCOMPARE(copy.avatar(), original.avatar()); | 120 | QCOMPARE(copy.avatar(), original.avatar()); |
4185 | 121 | QCOMPARE(copy.state(), original.state()); | ||
4186 | 122 | QCOMPARE(copy.roles(), original.roles()); | ||
4187 | 117 | QCOMPARE(copy.detailProperties(), original.detailProperties()); | 123 | QCOMPARE(copy.detailProperties(), original.detailProperties()); |
4188 | 118 | } | 124 | } |
4189 | 119 | 125 | ||
4190 | @@ -121,7 +127,7 @@ | |||
4191 | 121 | { | 127 | { |
4192 | 122 | QVariantMap detailProperties; | 128 | QVariantMap detailProperties; |
4193 | 123 | detailProperties["theProperty2"] = "theValue2"; | 129 | detailProperties["theProperty2"] = "theValue2"; |
4195 | 124 | History::Participant original("accountId2", "identifier2", "contactId2", "alias2", "avatar2", detailProperties); | 130 | History::Participant original("accountId2", "identifier2", "contactId2", "alias2", "avatar2", History::ParticipantStateRegular, History::ParticipantRoleMember, detailProperties); |
4196 | 125 | 131 | ||
4197 | 126 | History::Participant copy; | 132 | History::Participant copy; |
4198 | 127 | copy = original; | 133 | copy = original; |
4199 | @@ -131,6 +137,8 @@ | |||
4200 | 131 | QCOMPARE(copy.contactId(), original.contactId()); | 137 | QCOMPARE(copy.contactId(), original.contactId()); |
4201 | 132 | QCOMPARE(copy.alias(), original.alias()); | 138 | QCOMPARE(copy.alias(), original.alias()); |
4202 | 133 | QCOMPARE(copy.avatar(), original.avatar()); | 139 | QCOMPARE(copy.avatar(), original.avatar()); |
4203 | 140 | QCOMPARE(copy.state(), original.state()); | ||
4204 | 141 | QCOMPARE(copy.roles(), original.roles()); | ||
4205 | 134 | QCOMPARE(copy.detailProperties(), original.detailProperties()); | 142 | QCOMPARE(copy.detailProperties(), original.detailProperties()); |
4206 | 135 | } | 143 | } |
4207 | 136 | 144 | ||
4208 | @@ -166,13 +174,15 @@ | |||
4209 | 166 | QVariantMap detailProperties; | 174 | QVariantMap detailProperties; |
4210 | 167 | detailProperties["someDetailProperty"] = "someValue"; | 175 | detailProperties["someDetailProperty"] = "someValue"; |
4211 | 168 | 176 | ||
4213 | 169 | History::Participant participant("theAccountId", "theIdentifier", "theContactId", "theAlias", "theAvatar", detailProperties); | 177 | History::Participant participant("theAccountId", "theIdentifier", "theContactId", "theAlias", "theAvatar", History::ParticipantStateRegular, History::ParticipantRoleAdmin, detailProperties); |
4214 | 170 | QVariantMap properties = participant.properties(); | 178 | QVariantMap properties = participant.properties(); |
4215 | 171 | QCOMPARE(properties[History::FieldAccountId].toString(), participant.accountId()); | 179 | QCOMPARE(properties[History::FieldAccountId].toString(), participant.accountId()); |
4216 | 172 | QCOMPARE(properties[History::FieldIdentifier].toString(), participant.identifier()); | 180 | QCOMPARE(properties[History::FieldIdentifier].toString(), participant.identifier()); |
4217 | 173 | QCOMPARE(properties[History::FieldContactId].toString(), participant.contactId()); | 181 | QCOMPARE(properties[History::FieldContactId].toString(), participant.contactId()); |
4218 | 174 | QCOMPARE(properties[History::FieldAlias].toString(), participant.alias()); | 182 | QCOMPARE(properties[History::FieldAlias].toString(), participant.alias()); |
4219 | 175 | QCOMPARE(properties[History::FieldAvatar].toString(), participant.avatar()); | 183 | QCOMPARE(properties[History::FieldAvatar].toString(), participant.avatar()); |
4220 | 184 | QCOMPARE(properties[History::FieldParticipantState].toUInt(), participant.state()); | ||
4221 | 185 | QCOMPARE(properties[History::FieldParticipantRoles].toUInt(), participant.roles()); | ||
4222 | 176 | QCOMPARE(properties[History::FieldDetailProperties].toMap(), participant.detailProperties()); | 186 | QCOMPARE(properties[History::FieldDetailProperties].toMap(), participant.detailProperties()); |
4223 | 177 | } | 187 | } |
4224 | 178 | 188 | ||
4225 | @@ -186,6 +196,8 @@ | |||
4226 | 186 | properties[History::FieldContactId] = "someContactId"; | 196 | properties[History::FieldContactId] = "someContactId"; |
4227 | 187 | properties[History::FieldAlias] = "someAlias"; | 197 | properties[History::FieldAlias] = "someAlias"; |
4228 | 188 | properties[History::FieldAvatar] = "someAvatar"; | 198 | properties[History::FieldAvatar] = "someAvatar"; |
4229 | 199 | properties[History::FieldParticipantState] = History::ParticipantStateRegular; | ||
4230 | 200 | properties[History::FieldParticipantRoles] = History::ParticipantRoleAdmin; | ||
4231 | 189 | detailProperties["someDetailProperty"] = "someValue"; | 201 | detailProperties["someDetailProperty"] = "someValue"; |
4232 | 190 | properties[History::FieldDetailProperties] = detailProperties; | 202 | properties[History::FieldDetailProperties] = detailProperties; |
4233 | 191 | 203 | ||
4234 | @@ -195,6 +207,8 @@ | |||
4235 | 195 | QCOMPARE(participant.contactId(), properties[History::FieldContactId].toString()); | 207 | QCOMPARE(participant.contactId(), properties[History::FieldContactId].toString()); |
4236 | 196 | QCOMPARE(participant.alias(), properties[History::FieldAlias].toString()); | 208 | QCOMPARE(participant.alias(), properties[History::FieldAlias].toString()); |
4237 | 197 | QCOMPARE(participant.avatar(), properties[History::FieldAvatar].toString()); | 209 | QCOMPARE(participant.avatar(), properties[History::FieldAvatar].toString()); |
4238 | 210 | QCOMPARE(participant.state(), properties[History::FieldParticipantState].toUInt()); | ||
4239 | 211 | QCOMPARE(participant.roles(), properties[History::FieldParticipantRoles].toUInt()); | ||
4240 | 198 | QCOMPARE(participant.detailProperties(), properties[History::FieldDetailProperties].toMap()); | 212 | QCOMPARE(participant.detailProperties(), properties[History::FieldDetailProperties].toMap()); |
4241 | 199 | } | 213 | } |
4242 | 200 | 214 | ||
4243 | 201 | 215 | ||
4244 | === modified file 'tests/libhistoryservice/TextEventTest.cpp' | |||
4245 | --- tests/libhistoryservice/TextEventTest.cpp 2015-09-28 23:13:21 +0000 | |||
4246 | +++ tests/libhistoryservice/TextEventTest.cpp 2016-11-24 12:52:24 +0000 | |||
4247 | @@ -53,33 +53,34 @@ | |||
4248 | 53 | QTest::addColumn<int>("messageStatus"); | 53 | QTest::addColumn<int>("messageStatus"); |
4249 | 54 | QTest::addColumn<QDateTime>("readTimestamp"); | 54 | QTest::addColumn<QDateTime>("readTimestamp"); |
4250 | 55 | QTest::addColumn<QString>("subject"); | 55 | QTest::addColumn<QString>("subject"); |
4251 | 56 | QTest::addColumn<int>("informationType"); | ||
4252 | 56 | QTest::addColumn<QStringList>("participants"); | 57 | QTest::addColumn<QStringList>("participants"); |
4253 | 57 | 58 | ||
4254 | 58 | QTest::newRow("unread message") << "testAccountId" << "testThreadId" << "testEventId" | 59 | QTest::newRow("unread message") << "testAccountId" << "testThreadId" << "testEventId" |
4255 | 59 | << "testSenderId" << QDateTime::currentDateTime().addDays(-10) | 60 | << "testSenderId" << QDateTime::currentDateTime().addDays(-10) |
4256 | 60 | << true << "One Test Message" << (int)History::MessageTypeText | 61 | << true << "One Test Message" << (int)History::MessageTypeText |
4258 | 61 | << 0 << QDateTime::currentDateTime().addDays(-5) << "Test Subject" | 62 | << 0 << QDateTime::currentDateTime().addDays(-5) << "Test Subject" << (int) History::InformationTypeJoined |
4259 | 62 | << (QStringList() << "testParticipant"); | 63 | << (QStringList() << "testParticipant"); |
4260 | 63 | QTest::newRow("read message") << "testAccountId2" << "testThreadId2" << "testEventId2" | 64 | QTest::newRow("read message") << "testAccountId2" << "testThreadId2" << "testEventId2" |
4261 | 64 | << "testSenderId2" << QDateTime::currentDateTime().addDays(-10) | 65 | << "testSenderId2" << QDateTime::currentDateTime().addDays(-10) |
4262 | 65 | << false << "One Test Message" << (int)History::MessageTypeText | 66 | << false << "One Test Message" << (int)History::MessageTypeText |
4264 | 66 | << 0 << QDateTime::currentDateTime().addDays(-5) << "Test Subject 2" | 67 | << 0 << QDateTime::currentDateTime().addDays(-5) << "Test Subject 2" << (int) History::InformationTypeLeaving |
4265 | 67 | << (QStringList() << "testParticipant2"); | 68 | << (QStringList() << "testParticipant2"); |
4266 | 68 | QTest::newRow("message status") << "testAccountId" << "testThreadId" << "testEventId" | 69 | QTest::newRow("message status") << "testAccountId" << "testThreadId" << "testEventId" |
4267 | 69 | << "testSenderId" << QDateTime::currentDateTime().addDays(-10) | 70 | << "testSenderId" << QDateTime::currentDateTime().addDays(-10) |
4268 | 70 | << true << "One Test Message" << (int)History::MessageTypeText | 71 | << true << "One Test Message" << (int)History::MessageTypeText |
4269 | 71 | << (int)History::MessageStatusAccepted | 72 | << (int)History::MessageStatusAccepted |
4271 | 72 | << QDateTime::currentDateTime().addDays(-5) << "Test Subject 3" | 73 | << QDateTime::currentDateTime().addDays(-5) << "Test Subject 3" << (int) History::InformationTypeSelfLeaving |
4272 | 73 | << (QStringList() << "testParticipant"); | 74 | << (QStringList() << "testParticipant"); |
4273 | 74 | QTest::newRow("multi party message") << "testAccountId" << "testThreadId" << "testEventId" | 75 | QTest::newRow("multi party message") << "testAccountId" << "testThreadId" << "testEventId" |
4274 | 75 | << "testSenderId" << QDateTime::currentDateTime().addDays(-10) | 76 | << "testSenderId" << QDateTime::currentDateTime().addDays(-10) |
4275 | 76 | << true << "One Test Message" << (int)History::MessageTypeMultiPart | 77 | << true << "One Test Message" << (int)History::MessageTypeMultiPart |
4277 | 77 | << 0 << QDateTime::currentDateTime().addDays(-5) << QString() | 78 | << 0 << QDateTime::currentDateTime().addDays(-5) << QString() << (int) History::InformationTypeNone |
4278 | 78 | << (QStringList() << "testParticipant"); | 79 | << (QStringList() << "testParticipant"); |
4279 | 79 | QTest::newRow("multiple participants") << "testAccountId2" << "testThreadId2" << "testEventId2" | 80 | QTest::newRow("multiple participants") << "testAccountId2" << "testThreadId2" << "testEventId2" |
4280 | 80 | << "testSenderId2" << QDateTime::currentDateTime().addDays(-7) | 81 | << "testSenderId2" << QDateTime::currentDateTime().addDays(-7) |
4281 | 81 | << true << "One Test Message 2" << (int)History::MessageTypeText | 82 | << true << "One Test Message 2" << (int)History::MessageTypeText |
4283 | 82 | << 0 << QDateTime::currentDateTime().addDays(-4) << QString() | 83 | << 0 << QDateTime::currentDateTime().addDays(-4) << QString() << (int) History::InformationTypeNone |
4284 | 83 | << (QStringList() << "one" << "two" << "three" << "four"); | 84 | << (QStringList() << "one" << "two" << "three" << "four"); |
4285 | 84 | } | 85 | } |
4286 | 85 | 86 | ||
4287 | @@ -96,10 +97,11 @@ | |||
4288 | 96 | QFETCH(int, messageStatus); | 97 | QFETCH(int, messageStatus); |
4289 | 97 | QFETCH(QDateTime, readTimestamp); | 98 | QFETCH(QDateTime, readTimestamp); |
4290 | 98 | QFETCH(QString, subject); | 99 | QFETCH(QString, subject); |
4291 | 100 | QFETCH(int, informationType); | ||
4292 | 99 | QFETCH(QStringList, participants); | 101 | QFETCH(QStringList, participants); |
4293 | 100 | History::TextEvent event(accountId, threadId, eventId, senderId, timestamp, newEvent, | 102 | History::TextEvent event(accountId, threadId, eventId, senderId, timestamp, newEvent, |
4294 | 101 | message, (History::MessageType)messageType, (History::MessageStatus)messageStatus, | 103 | message, (History::MessageType)messageType, (History::MessageStatus)messageStatus, |
4296 | 102 | readTimestamp, subject, History::TextEventAttachments(), | 104 | readTimestamp, subject, (History::InformationType) informationType, History::TextEventAttachments(), |
4297 | 103 | participantsFromIdentifiers(accountId, participants)); | 105 | participantsFromIdentifiers(accountId, participants)); |
4298 | 104 | 106 | ||
4299 | 105 | // check that the values are properly set | 107 | // check that the values are properly set |
4300 | @@ -150,33 +152,34 @@ | |||
4301 | 150 | QTest::addColumn<int>("messageStatus"); | 152 | QTest::addColumn<int>("messageStatus"); |
4302 | 151 | QTest::addColumn<QDateTime>("readTimestamp"); | 153 | QTest::addColumn<QDateTime>("readTimestamp"); |
4303 | 152 | QTest::addColumn<QString>("subject"); | 154 | QTest::addColumn<QString>("subject"); |
4304 | 155 | QTest::addColumn<int>("informationType"); | ||
4305 | 153 | QTest::addColumn<QStringList>("participants"); | 156 | QTest::addColumn<QStringList>("participants"); |
4306 | 154 | 157 | ||
4307 | 155 | QTest::newRow("unread message") << "testAccountId" << "testThreadId" << "testEventId" | 158 | QTest::newRow("unread message") << "testAccountId" << "testThreadId" << "testEventId" |
4308 | 156 | << "testSenderId" << QDateTime::currentDateTime().addDays(-10) | 159 | << "testSenderId" << QDateTime::currentDateTime().addDays(-10) |
4309 | 157 | << true << "One Test Message" << (int)History::MessageTypeText | 160 | << true << "One Test Message" << (int)History::MessageTypeText |
4311 | 158 | << 0 << QDateTime::currentDateTime().addDays(-5) << "Test Subject" | 161 | << 0 << QDateTime::currentDateTime().addDays(-5) << "Test Subject" << (int) History::InformationTypeJoined |
4312 | 159 | << (QStringList() << "testParticipant"); | 162 | << (QStringList() << "testParticipant"); |
4313 | 160 | QTest::newRow("read message") << "testAccountId2" << "testThreadId2" << "testEventId2" | 163 | QTest::newRow("read message") << "testAccountId2" << "testThreadId2" << "testEventId2" |
4314 | 161 | << "testSenderId2" << QDateTime::currentDateTime().addDays(-10) | 164 | << "testSenderId2" << QDateTime::currentDateTime().addDays(-10) |
4315 | 162 | << false << "One Test Message" << (int)History::MessageTypeText | 165 | << false << "One Test Message" << (int)History::MessageTypeText |
4317 | 163 | << 0 << QDateTime::currentDateTime().addDays(-5) << "Test Subject 2" | 166 | << 0 << QDateTime::currentDateTime().addDays(-5) << "Test Subject 2" << (int) History::InformationTypeNone |
4318 | 164 | << (QStringList() << "testParticipant2"); | 167 | << (QStringList() << "testParticipant2"); |
4319 | 165 | QTest::newRow("message status") << "testAccountId" << "testThreadId" << "testEventId" | 168 | QTest::newRow("message status") << "testAccountId" << "testThreadId" << "testEventId" |
4320 | 166 | << "testSenderId" << QDateTime::currentDateTime().addDays(-10) | 169 | << "testSenderId" << QDateTime::currentDateTime().addDays(-10) |
4321 | 167 | << true << "One Test Message" << (int)History::MessageTypeText | 170 | << true << "One Test Message" << (int)History::MessageTypeText |
4322 | 168 | << (int)History::MessageStatusAccepted | 171 | << (int)History::MessageStatusAccepted |
4324 | 169 | << QDateTime::currentDateTime().addDays(-5) << "Test Subject 3" | 172 | << QDateTime::currentDateTime().addDays(-5) << "Test Subject 3" << (int) History::InformationTypeNone |
4325 | 170 | << (QStringList() << "testParticipant"); | 173 | << (QStringList() << "testParticipant"); |
4326 | 171 | QTest::newRow("multi party message") << "testAccountId" << "testThreadId" << "testEventId" | 174 | QTest::newRow("multi party message") << "testAccountId" << "testThreadId" << "testEventId" |
4327 | 172 | << "testSenderId" << QDateTime::currentDateTime().addDays(-10) | 175 | << "testSenderId" << QDateTime::currentDateTime().addDays(-10) |
4328 | 173 | << true << "One Test Message" << (int)History::MessageTypeMultiPart | 176 | << true << "One Test Message" << (int)History::MessageTypeMultiPart |
4330 | 174 | << 0 << QDateTime::currentDateTime().addDays(-5) << QString() | 177 | << 0 << QDateTime::currentDateTime().addDays(-5) << QString() << (int) History::InformationTypeNone |
4331 | 175 | << (QStringList() << "testParticipant"); | 178 | << (QStringList() << "testParticipant"); |
4332 | 176 | QTest::newRow("multiple participants") << "testAccountId2" << "testThreadId2" << "testEventId2" | 179 | QTest::newRow("multiple participants") << "testAccountId2" << "testThreadId2" << "testEventId2" |
4333 | 177 | << "testSenderId2" << QDateTime::currentDateTime().addDays(-7) | 180 | << "testSenderId2" << QDateTime::currentDateTime().addDays(-7) |
4334 | 178 | << true << "One Test Message 2" << (int)History::MessageTypeText | 181 | << true << "One Test Message 2" << (int)History::MessageTypeText |
4336 | 179 | << 0 << QDateTime::currentDateTime().addDays(-4) << QString() | 182 | << 0 << QDateTime::currentDateTime().addDays(-4) << QString() << (int) History::InformationTypeNone |
4337 | 180 | << (QStringList() << "one" << "two" << "three" << "four"); | 183 | << (QStringList() << "one" << "two" << "three" << "four"); |
4338 | 181 | } | 184 | } |
4339 | 182 | 185 | ||
4340 | @@ -193,6 +196,7 @@ | |||
4341 | 193 | QFETCH(int, messageStatus); | 196 | QFETCH(int, messageStatus); |
4342 | 194 | QFETCH(QDateTime, readTimestamp); | 197 | QFETCH(QDateTime, readTimestamp); |
4343 | 195 | QFETCH(QString, subject); | 198 | QFETCH(QString, subject); |
4344 | 199 | QFETCH(int, informationType); | ||
4345 | 196 | QFETCH(QStringList, participants); | 200 | QFETCH(QStringList, participants); |
4346 | 197 | 201 | ||
4347 | 198 | QVariantMap properties; | 202 | QVariantMap properties; |
4348 | @@ -207,6 +211,7 @@ | |||
4349 | 207 | properties[History::FieldMessageStatus] = messageStatus; | 211 | properties[History::FieldMessageStatus] = messageStatus; |
4350 | 208 | properties[History::FieldReadTimestamp] = readTimestamp.toString("yyyy-MM-ddTHH:mm:ss.zzz"); | 212 | properties[History::FieldReadTimestamp] = readTimestamp.toString("yyyy-MM-ddTHH:mm:ss.zzz"); |
4351 | 209 | properties[History::FieldSubject] = subject; | 213 | properties[History::FieldSubject] = subject; |
4352 | 214 | properties[History::FieldInformationType] = informationType; | ||
4353 | 210 | properties[History::FieldParticipants] = participantsFromIdentifiers(accountId, participants).toVariantList(); | 215 | properties[History::FieldParticipants] = participantsFromIdentifiers(accountId, participants).toVariantList(); |
4354 | 211 | 216 | ||
4355 | 212 | History::TextEvent textEvent = History::TextEvent::fromProperties(properties); | 217 | History::TextEvent textEvent = History::TextEvent::fromProperties(properties); |
4356 | @@ -221,6 +226,7 @@ | |||
4357 | 221 | QCOMPARE(textEvent.messageStatus(), (History::MessageStatus) messageStatus); | 226 | QCOMPARE(textEvent.messageStatus(), (History::MessageStatus) messageStatus); |
4358 | 222 | QCOMPARE(textEvent.readTimestamp().toString(Qt::ISODate), readTimestamp.toString(Qt::ISODate)); | 227 | QCOMPARE(textEvent.readTimestamp().toString(Qt::ISODate), readTimestamp.toString(Qt::ISODate)); |
4359 | 223 | QCOMPARE(textEvent.subject(), subject); | 228 | QCOMPARE(textEvent.subject(), subject); |
4360 | 229 | QCOMPARE(textEvent.informationType(), (History::InformationType) informationType); | ||
4361 | 224 | QCOMPARE(textEvent.participants().identifiers(), participants); | 230 | QCOMPARE(textEvent.participants().identifiers(), participants); |
4362 | 225 | } | 231 | } |
4363 | 226 | 232 | ||
4364 | @@ -245,33 +251,34 @@ | |||
4365 | 245 | QTest::addColumn<int>("messageStatus"); | 251 | QTest::addColumn<int>("messageStatus"); |
4366 | 246 | QTest::addColumn<QDateTime>("readTimestamp"); | 252 | QTest::addColumn<QDateTime>("readTimestamp"); |
4367 | 247 | QTest::addColumn<QString>("subject"); | 253 | QTest::addColumn<QString>("subject"); |
4368 | 254 | QTest::addColumn<int>("informationType"); | ||
4369 | 248 | QTest::addColumn<QStringList>("participants"); | 255 | QTest::addColumn<QStringList>("participants"); |
4370 | 249 | 256 | ||
4371 | 250 | QTest::newRow("unread message") << "testAccountId" << "testThreadId" << "testEventId" | 257 | QTest::newRow("unread message") << "testAccountId" << "testThreadId" << "testEventId" |
4372 | 251 | << "testSenderId" << QDateTime::currentDateTime().addDays(-10) | 258 | << "testSenderId" << QDateTime::currentDateTime().addDays(-10) |
4373 | 252 | << true << "One Test Message" << (int)History::MessageTypeText | 259 | << true << "One Test Message" << (int)History::MessageTypeText |
4375 | 253 | << 0 << QDateTime::currentDateTime().addDays(-5) << "Test Subject" | 260 | << 0 << QDateTime::currentDateTime().addDays(-5) << "Test Subject" << (int) History::InformationTypeNone |
4376 | 254 | << (QStringList() << "testParticipant"); | 261 | << (QStringList() << "testParticipant"); |
4377 | 255 | QTest::newRow("read message") << "testAccountId2" << "testThreadId2" << "testEventId2" | 262 | QTest::newRow("read message") << "testAccountId2" << "testThreadId2" << "testEventId2" |
4378 | 256 | << "testSenderId2" << QDateTime::currentDateTime().addDays(-10) | 263 | << "testSenderId2" << QDateTime::currentDateTime().addDays(-10) |
4379 | 257 | << false << "One Test Message" << (int)History::MessageTypeText | 264 | << false << "One Test Message" << (int)History::MessageTypeText |
4381 | 258 | << 0 << QDateTime::currentDateTime().addDays(-5) << "Test Subject 2" | 265 | << 0 << QDateTime::currentDateTime().addDays(-5) << "Test Subject 2" << (int) History::InformationTypeNone |
4382 | 259 | << (QStringList() << "testParticipant2"); | 266 | << (QStringList() << "testParticipant2"); |
4383 | 260 | QTest::newRow("message status") << "testAccountId" << "testThreadId" << "testEventId" | 267 | QTest::newRow("message status") << "testAccountId" << "testThreadId" << "testEventId" |
4384 | 261 | << "testSenderId" << QDateTime::currentDateTime().addDays(-10) | 268 | << "testSenderId" << QDateTime::currentDateTime().addDays(-10) |
4385 | 262 | << true << "One Test Message" << (int)History::MessageTypeText | 269 | << true << "One Test Message" << (int)History::MessageTypeText |
4386 | 263 | << (int)History::MessageStatusAccepted | 270 | << (int)History::MessageStatusAccepted |
4388 | 264 | << QDateTime::currentDateTime().addDays(-5) << "Test Subject 3" | 271 | << QDateTime::currentDateTime().addDays(-5) << "Test Subject 3" << (int) History::InformationTypeNone |
4389 | 265 | << (QStringList() << "testParticipant"); | 272 | << (QStringList() << "testParticipant"); |
4390 | 266 | QTest::newRow("multi party message") << "testAccountId" << "testThreadId" << "testEventId" | 273 | QTest::newRow("multi party message") << "testAccountId" << "testThreadId" << "testEventId" |
4391 | 267 | << "testSenderId" << QDateTime::currentDateTime().addDays(-10) | 274 | << "testSenderId" << QDateTime::currentDateTime().addDays(-10) |
4392 | 268 | << true << "One Test Message" << (int)History::MessageTypeMultiPart | 275 | << true << "One Test Message" << (int)History::MessageTypeMultiPart |
4394 | 269 | << 0 << QDateTime::currentDateTime().addDays(-5) << QString() | 276 | << 0 << QDateTime::currentDateTime().addDays(-5) << QString() << (int) History::InformationTypeNone |
4395 | 270 | << (QStringList() << "testParticipant"); | 277 | << (QStringList() << "testParticipant"); |
4396 | 271 | QTest::newRow("multiple participants") << "testAccountId2" << "testThreadId2" << "testEventId2" | 278 | QTest::newRow("multiple participants") << "testAccountId2" << "testThreadId2" << "testEventId2" |
4397 | 272 | << "testSenderId2" << QDateTime::currentDateTime().addDays(-7) | 279 | << "testSenderId2" << QDateTime::currentDateTime().addDays(-7) |
4398 | 273 | << true << "One Test Message 2" << (int)History::MessageTypeText | 280 | << true << "One Test Message 2" << (int)History::MessageTypeText |
4400 | 274 | << 0 << QDateTime::currentDateTime().addDays(-4) << QString() | 281 | << 0 << QDateTime::currentDateTime().addDays(-4) << QString() << (int) History::InformationTypeNone |
4401 | 275 | << (QStringList() << "one" << "two" << "three" << "four"); | 282 | << (QStringList() << "one" << "two" << "three" << "four"); |
4402 | 276 | } | 283 | } |
4403 | 277 | 284 | ||
4404 | @@ -288,10 +295,11 @@ | |||
4405 | 288 | QFETCH(int, messageStatus); | 295 | QFETCH(int, messageStatus); |
4406 | 289 | QFETCH(QDateTime, readTimestamp); | 296 | QFETCH(QDateTime, readTimestamp); |
4407 | 290 | QFETCH(QString, subject); | 297 | QFETCH(QString, subject); |
4408 | 298 | QFETCH(int, informationType); | ||
4409 | 291 | QFETCH(QStringList, participants); | 299 | QFETCH(QStringList, participants); |
4410 | 292 | History::TextEvent event(accountId, threadId, eventId, senderId, timestamp, newEvent, | 300 | History::TextEvent event(accountId, threadId, eventId, senderId, timestamp, newEvent, |
4411 | 293 | message, (History::MessageType)messageType, (History::MessageStatus)messageStatus, | 301 | message, (History::MessageType)messageType, (History::MessageStatus)messageStatus, |
4413 | 294 | readTimestamp, subject, History::TextEventAttachments(), | 302 | readTimestamp, subject, History::InformationTypeNone, History::TextEventAttachments(), |
4414 | 295 | participantsFromIdentifiers(accountId, participants)); | 303 | participantsFromIdentifiers(accountId, participants)); |
4415 | 296 | 304 | ||
4416 | 297 | QVariantMap properties = event.properties(); | 305 | QVariantMap properties = event.properties(); |
4417 | @@ -306,6 +314,7 @@ | |||
4418 | 306 | QCOMPARE(properties[History::FieldMessageStatus].toInt(), messageStatus); | 314 | QCOMPARE(properties[History::FieldMessageStatus].toInt(), messageStatus); |
4419 | 307 | QCOMPARE(properties[History::FieldReadTimestamp].toString(), readTimestamp.toString("yyyy-MM-ddTHH:mm:ss.zzz")); | 315 | QCOMPARE(properties[History::FieldReadTimestamp].toString(), readTimestamp.toString("yyyy-MM-ddTHH:mm:ss.zzz")); |
4420 | 308 | QCOMPARE(properties[History::FieldSubject].toString(), subject); | 316 | QCOMPARE(properties[History::FieldSubject].toString(), subject); |
4421 | 317 | QCOMPARE(properties[History::FieldInformationType].toInt(), informationType); | ||
4422 | 309 | QCOMPARE(History::Participants::fromVariantList(properties[History::FieldParticipants].toList()).identifiers(), participants); | 318 | QCOMPARE(History::Participants::fromVariantList(properties[History::FieldParticipants].toList()).identifiers(), participants); |
4423 | 310 | } | 319 | } |
4424 | 311 | 320 | ||
4425 | 312 | 321 | ||
4426 | === modified file 'tests/libhistoryservice/ThreadTest.cpp' | |||
4427 | --- tests/libhistoryservice/ThreadTest.cpp 2015-10-02 16:48:19 +0000 | |||
4428 | +++ tests/libhistoryservice/ThreadTest.cpp 2016-11-24 12:52:24 +0000 | |||
4429 | @@ -102,11 +102,12 @@ | |||
4430 | 102 | break; | 102 | break; |
4431 | 103 | } | 103 | } |
4432 | 104 | 104 | ||
4434 | 105 | History::Thread threadItem(accountId, threadId, type, participantsFromIdentifiers(accountId, participants), event, count, unreadCount); | 105 | History::Thread threadItem(accountId, threadId, type, participantsFromIdentifiers(accountId, participants), event.timestamp(), event, count, unreadCount); |
4435 | 106 | QCOMPARE(threadItem.accountId(), accountId); | 106 | QCOMPARE(threadItem.accountId(), accountId); |
4436 | 107 | QCOMPARE(threadItem.threadId(), threadId); | 107 | QCOMPARE(threadItem.threadId(), threadId); |
4437 | 108 | QCOMPARE(threadItem.type(), type); | 108 | QCOMPARE(threadItem.type(), type); |
4438 | 109 | QCOMPARE(threadItem.participants().identifiers(), participants); | 109 | QCOMPARE(threadItem.participants().identifiers(), participants); |
4439 | 110 | QCOMPARE(threadItem.timestamp(), event.timestamp()); | ||
4440 | 110 | QCOMPARE(threadItem.lastEvent(), event); | 111 | QCOMPARE(threadItem.lastEvent(), event); |
4441 | 111 | QCOMPARE(threadItem.count(), count); | 112 | QCOMPARE(threadItem.count(), count); |
4442 | 112 | QCOMPARE(threadItem.unreadCount(), unreadCount); | 113 | QCOMPARE(threadItem.unreadCount(), unreadCount); |
4443 | @@ -172,6 +173,7 @@ | |||
4444 | 172 | QCOMPARE(thread.threadId(), threadId); | 173 | QCOMPARE(thread.threadId(), threadId); |
4445 | 173 | QCOMPARE(thread.type(), type); | 174 | QCOMPARE(thread.type(), type); |
4446 | 174 | QCOMPARE(thread.participants().identifiers(), participants); | 175 | QCOMPARE(thread.participants().identifiers(), participants); |
4447 | 176 | QCOMPARE(thread.timestamp(), event.timestamp()); | ||
4448 | 175 | QCOMPARE(thread.count(), count); | 177 | QCOMPARE(thread.count(), count); |
4449 | 176 | QCOMPARE(thread.unreadCount(), unreadCount); | 178 | QCOMPARE(thread.unreadCount(), unreadCount); |
4450 | 177 | QVERIFY(thread.lastEvent() == event); | 179 | QVERIFY(thread.lastEvent() == event); |
4451 | @@ -229,7 +231,7 @@ | |||
4452 | 229 | break; | 231 | break; |
4453 | 230 | } | 232 | } |
4454 | 231 | 233 | ||
4456 | 232 | History::Thread threadItem(accountId, threadId, type, participantsFromIdentifiers(accountId, participants), event, count, unreadCount); | 234 | History::Thread threadItem(accountId, threadId, type, participantsFromIdentifiers(accountId, participants), event.timestamp(), event, count, unreadCount); |
4457 | 233 | QVariantMap properties = threadItem.properties(); | 235 | QVariantMap properties = threadItem.properties(); |
4458 | 234 | QCOMPARE(properties[History::FieldAccountId].toString(), accountId); | 236 | QCOMPARE(properties[History::FieldAccountId].toString(), accountId); |
4459 | 235 | QCOMPARE(properties[History::FieldThreadId].toString(), threadId); | 237 | QCOMPARE(properties[History::FieldThreadId].toString(), threadId); |
4460 | 236 | 238 | ||
4461 | === modified file 'tests/plugins/sqlite/SqlitePluginTest.cpp' | |||
4462 | --- tests/plugins/sqlite/SqlitePluginTest.cpp 2015-09-23 22:27:38 +0000 | |||
4463 | +++ tests/plugins/sqlite/SqlitePluginTest.cpp 2016-11-24 12:52:24 +0000 | |||
4464 | @@ -249,36 +249,35 @@ | |||
4465 | 249 | { | 249 | { |
4466 | 250 | // clear the database | 250 | // clear the database |
4467 | 251 | SQLiteDatabase::instance()->reopen(); | 251 | SQLiteDatabase::instance()->reopen(); |
4468 | 252 | QSqlQuery query(SQLiteDatabase::instance()->database()); | ||
4469 | 252 | 253 | ||
4470 | 253 | QVERIFY(mPlugin->beginBatchOperation()); | 254 | QVERIFY(mPlugin->beginBatchOperation()); |
4474 | 254 | mPlugin->createThreadForParticipants("accountOne", History::EventTypeText, QStringList() << "participantOne"); | 255 | QVERIFY(query.exec("UPDATE schema_version SET version=123")); |
4472 | 255 | mPlugin->createThreadForParticipants("accountTwo", History::EventTypeText, QStringList() << "participantTwo"); | ||
4473 | 256 | mPlugin->createThreadForParticipants("accountThree", History::EventTypeText, QStringList() << "participantThree"); | ||
4475 | 257 | QVERIFY(mPlugin->endBatchOperation()); | 256 | QVERIFY(mPlugin->endBatchOperation()); |
4476 | 258 | 257 | ||
4477 | 259 | // check that the data was actually written | 258 | // check that the data was actually written |
4480 | 260 | QSqlQuery query(SQLiteDatabase::instance()->database()); | 259 | QVERIFY(query.exec("SELECT version FROM schema_version")); |
4479 | 261 | QVERIFY(query.exec("SELECT count(*) FROM threads")); | ||
4481 | 262 | QVERIFY(query.next()); | 260 | QVERIFY(query.next()); |
4483 | 263 | QCOMPARE(query.value(0).toInt(), 3); | 261 | QCOMPARE(query.value(0).toInt(), 123); |
4484 | 264 | } | 262 | } |
4485 | 265 | 263 | ||
4486 | 266 | void SqlitePluginTest::testRollback() | 264 | void SqlitePluginTest::testRollback() |
4487 | 267 | { | 265 | { |
4488 | 268 | // clear the database | 266 | // clear the database |
4489 | 269 | SQLiteDatabase::instance()->reopen(); | 267 | SQLiteDatabase::instance()->reopen(); |
4490 | 268 | QSqlQuery query(SQLiteDatabase::instance()->database()); | ||
4491 | 269 | QVERIFY(query.exec("SELECT version FROM schema_version")); | ||
4492 | 270 | QVERIFY(query.next()); | ||
4493 | 271 | int version = query.value(0).toInt(); | ||
4494 | 270 | 272 | ||
4495 | 271 | QVERIFY(mPlugin->beginBatchOperation()); | 273 | QVERIFY(mPlugin->beginBatchOperation()); |
4499 | 272 | mPlugin->createThreadForParticipants("accountOne", History::EventTypeText, QStringList() << "participantOne"); | 274 | QVERIFY(query.exec("UPDATE schema_version SET version=255")); |
4497 | 273 | mPlugin->createThreadForParticipants("accountTwo", History::EventTypeText, QStringList() << "participantTwo"); | ||
4498 | 274 | mPlugin->createThreadForParticipants("accountThree", History::EventTypeText, QStringList() << "participantThree"); | ||
4500 | 275 | QVERIFY(mPlugin->rollbackBatchOperation()); | 275 | QVERIFY(mPlugin->rollbackBatchOperation()); |
4501 | 276 | 276 | ||
4502 | 277 | // check that the steps were reverted | 277 | // check that the steps were reverted |
4505 | 278 | QSqlQuery query(SQLiteDatabase::instance()->database()); | 278 | QVERIFY(query.exec("SELECT version FROM schema_version")); |
4504 | 279 | QVERIFY(query.exec("SELECT count(*) FROM threads")); | ||
4506 | 280 | QVERIFY(query.next()); | 279 | QVERIFY(query.next()); |
4508 | 281 | QCOMPARE(query.value(0).toInt(), 0); | 280 | QCOMPARE(query.value(0).toInt(), version); |
4509 | 282 | } | 281 | } |
4510 | 283 | 282 | ||
4511 | 284 | void SqlitePluginTest::testQueryThreads() | 283 | void SqlitePluginTest::testQueryThreads() |
4512 | @@ -319,7 +318,7 @@ | |||
4513 | 319 | QTest::newRow("text event with attachments") << History::TextEvent("mmsAccountId", "mmsSender", "mmsEventId", "mmsSender", | 318 | QTest::newRow("text event with attachments") << History::TextEvent("mmsAccountId", "mmsSender", "mmsEventId", "mmsSender", |
4514 | 320 | QDateTime::currentDateTime(), false, "Hello with attachments", | 319 | QDateTime::currentDateTime(), false, "Hello with attachments", |
4515 | 321 | History::MessageTypeMultiPart, History::MessageStatusDelivered, | 320 | History::MessageTypeMultiPart, History::MessageStatusDelivered, |
4517 | 322 | QDateTime::currentDateTime(), "The Subject", attachments).properties(); | 321 | QDateTime::currentDateTime(), "The Subject", History::InformationTypeNone, attachments).properties(); |
4518 | 323 | } | 322 | } |
4519 | 324 | 323 | ||
4520 | 325 | void SqlitePluginTest::testWriteTextEvent() | 324 | void SqlitePluginTest::testWriteTextEvent() |
4521 | @@ -406,7 +405,7 @@ | |||
4522 | 406 | thread[History::FieldEventId].toString(), "theAttachmentId", "text/plain", "/file/path"); | 405 | thread[History::FieldEventId].toString(), "theAttachmentId", "text/plain", "/file/path"); |
4523 | 407 | History::TextEvent textEvent(thread[History::FieldAccountId].toString(), thread[History::FieldThreadId].toString(), "theEventId", | 406 | History::TextEvent textEvent(thread[History::FieldAccountId].toString(), thread[History::FieldThreadId].toString(), "theEventId", |
4524 | 408 | "theParticipant", QDateTime::currentDateTime(), true, "Hi there!", History::MessageTypeMultiPart, | 407 | "theParticipant", QDateTime::currentDateTime(), true, "Hi there!", History::MessageTypeMultiPart, |
4526 | 409 | History::MessageStatusPending, QDateTime::currentDateTime(), "theSubject", | 408 | History::MessageStatusPending, QDateTime::currentDateTime(), "theSubject", History::InformationTypeNone, |
4527 | 410 | History::TextEventAttachments() << attachment); | 409 | History::TextEventAttachments() << attachment); |
4528 | 411 | QCOMPARE(mPlugin->writeTextEvent(textEvent.properties()), History::EventWriteCreated); | 410 | QCOMPARE(mPlugin->writeTextEvent(textEvent.properties()), History::EventWriteCreated); |
4529 | 412 | 411 | ||
4530 | @@ -606,7 +605,7 @@ | |||
4531 | 606 | QString("textEventId%1").arg(QString::number(i)), "textParticipant", | 605 | QString("textEventId%1").arg(QString::number(i)), "textParticipant", |
4532 | 607 | QDateTime::currentDateTime(), true, "Hello World!", History::MessageTypeMultiPart, | 606 | QDateTime::currentDateTime(), true, "Hello World!", History::MessageTypeMultiPart, |
4533 | 608 | History::MessageStatusPending, QDateTime::currentDateTime(), | 607 | History::MessageStatusPending, QDateTime::currentDateTime(), |
4535 | 609 | "theSubject", History::TextEventAttachments() << attachment); | 608 | "theSubject", History::InformationTypeNone, History::TextEventAttachments() << attachment); |
4536 | 610 | QCOMPARE(mPlugin->writeTextEvent(textEvent.properties()), History::EventWriteCreated); | 609 | QCOMPARE(mPlugin->writeTextEvent(textEvent.properties()), History::EventWriteCreated); |
4537 | 611 | } | 610 | } |
4538 | 612 | 611 | ||
4539 | @@ -659,7 +658,7 @@ | |||
4540 | 659 | QTest::newRow("text event with attachments") << History::TextEvent("mmsAccountId", "mmsSender", "mmsEventId", "mmsSender", | 658 | QTest::newRow("text event with attachments") << History::TextEvent("mmsAccountId", "mmsSender", "mmsEventId", "mmsSender", |
4541 | 660 | QDateTime::currentDateTime(), false, "Hello with attachments", | 659 | QDateTime::currentDateTime(), false, "Hello with attachments", |
4542 | 661 | History::MessageTypeMultiPart, History::MessageStatusDelivered, | 660 | History::MessageTypeMultiPart, History::MessageStatusDelivered, |
4544 | 662 | QDateTime::currentDateTime(), "The Subject", attachments).properties(); | 661 | QDateTime::currentDateTime(), "The Subject", History::InformationTypeNone, attachments).properties(); |
4545 | 663 | QTest::newRow("missed call") << History::VoiceEvent("theAccountId", "theSenderId", "theEventId", "theSenderId", | 662 | QTest::newRow("missed call") << History::VoiceEvent("theAccountId", "theSenderId", "theEventId", "theSenderId", |
4546 | 664 | QDateTime::currentDateTime(), true, true).properties(); | 663 | QDateTime::currentDateTime(), true, true).properties(); |
4547 | 665 | QTest::newRow("incoming call") << History::VoiceEvent("otherAccountId", "otherSenderId", "otherEventId", "otherSenderId", | 664 | QTest::newRow("incoming call") << History::VoiceEvent("otherAccountId", "otherSenderId", "otherEventId", "otherSenderId", |
Left some comments