306
306
return new SQLiteHistoryEventView(this, type, sort, filter);
309
QVariantMap SQLiteHistoryPlugin::markThreadAsRead(const QVariantMap &thread)
311
QSqlQuery query(SQLiteDatabase::instance()->database());
313
if (thread[History::FieldAccountId].toString().isEmpty() ||
314
thread[History::FieldThreadId].toString().isEmpty()) {
315
return QVariantMap();
318
// first check if the thread actually has anything to change
319
query.prepare("SELECT unreadCount from threads WHERE accountId=:accountId AND threadId=:threadId AND type=:type");
320
query.bindValue(":accountId", thread[History::FieldAccountId].toString());
321
query.bindValue(":threadId", thread[History::FieldThreadId].toString());
322
query.bindValue(":type", (uint)History::EventTypeText);
323
if (!query.exec() || !query.next()) {
324
qCritical() << "Failed to verify the unread messages of the thread. Error:" << query.lastError();
325
return QVariantMap();
329
int unreadCount = query.value(0).toUInt();
330
if (unreadCount == 0) {
331
// no messages to ack, so no need to update anything
332
return QVariantMap();
335
query.prepare("UPDATE text_events SET newEvent=:newEvent WHERE accountId=:accountId AND threadId=:threadId AND newEvent=1");
336
query.bindValue(":accountId", thread[History::FieldAccountId].toString());
337
query.bindValue(":threadId", thread[History::FieldThreadId].toString());
338
query.bindValue(":newEvent", false);
341
qCritical() << "Failed to mark thread as read: Error:" << query.lastError();
342
return QVariantMap();
345
QVariantMap existingThread = getSingleThread((History::EventType) thread[History::FieldType].toInt(),
346
thread[History::FieldAccountId].toString(),
347
thread[History::FieldThreadId].toString(),
349
if (!existingThread.isEmpty()) {
350
addThreadsToCache(QList<QVariantMap>() << existingThread);
351
return existingThread;
354
return QVariantMap();
309
357
QVariantMap SQLiteHistoryPlugin::threadForProperties(const QString &accountId,
310
358
History::EventType type,
311
359
const QVariantMap &properties,
332
378
return threadForParticipants(accountId, type, participants.identifiers(), matchFlags);
381
QString SQLiteHistoryPlugin::threadIdForProperties(const QString &accountId, History::EventType type, const QVariantMap &properties, History::MatchFlags matchFlags)
383
if (properties.isEmpty()) {
384
return QString::null;
387
// if chat type is room, just get the threadId directly
388
History::ChatType chatType = (History::ChatType)properties[History::FieldChatType].toUInt();
389
if (chatType == History::ChatTypeRoom) {
390
QString threadId = properties[History::FieldThreadId].toString();
394
// if chat type is anything else, fallback to returning the threadId from the participants list
395
History::Participants participants = History::Participants::fromVariant(properties[History::FieldParticipantIds]);
396
return threadForParticipants(accountId, type, participants.identifiers(), matchFlags)[History::FieldThreadId].toString();
399
QList<QVariantMap> SQLiteHistoryPlugin::participantsForThreads(const QList<QVariantMap> &threadIds)
401
QList<QVariantMap> results;
402
Q_FOREACH(const QVariantMap &thread, threadIds) {
403
QString accountId = thread[History::FieldAccountId].toString();
404
QString threadId = thread[History::FieldThreadId].toString();
405
History::EventType type = (History::EventType)thread[History::FieldType].toUInt();
406
QVariantMap result = thread;
409
query.prepare("SELECT normalizedId, alias, state, roles FROM thread_participants "
410
"WHERE accountId=:accountId AND threadId=:threadId AND type=:type");
411
query.bindValue(":accountId", accountId);
412
query.bindValue(":threadId", threadId);
413
query.bindValue(":type", type);
414
QVariantList participants;
416
qWarning() << "Failed to retrieve participants. Error:" << query.lastError().text() << query.lastQuery();
421
while (query.next()) {
422
QVariantMap participant;
423
QString identifier = query.value(0).toString();
424
participant[History::FieldIdentifier] = identifier;
425
participant[History::FieldAlias] = query.value(1);
426
participant[History::FieldParticipantState] = query.value(2);
427
participant[History::FieldParticipantRoles] = query.value(3);
428
participants << History::ContactMatcher::instance()->contactInfo(accountId, identifier, true, participant);
431
result[History::FieldParticipants] = participants;
335
437
QVariantMap SQLiteHistoryPlugin::threadForParticipants(const QString &accountId,
336
438
History::EventType type,
337
439
const QStringList &participants,
1093
1195
<< "threads.unreadCount"
1094
1196
<< "threads.lastEventTimestamp";
1096
// get the participants in the query already
1097
fields << "(SELECT group_concat(thread_participants.participantId, \"|,|\") "
1098
"FROM thread_participants WHERE thread_participants.accountId=threads.accountId "
1099
"AND thread_participants.threadId=threads.threadId "
1100
"AND thread_participants.type=threads.type GROUP BY accountId,threadId,type) as participants";
1102
fields << "(SELECT group_concat(thread_participants.state, \"|,|\") "
1103
"FROM thread_participants WHERE thread_participants.accountId=threads.accountId "
1104
"AND thread_participants.threadId=threads.threadId "
1105
"AND thread_participants.type=threads.type GROUP BY accountId,threadId,type) as state";
1107
fields << "(SELECT group_concat(thread_participants.roles, \"|,|\") "
1108
"FROM thread_participants WHERE thread_participants.accountId=threads.accountId "
1109
"AND thread_participants.threadId=threads.threadId "
1110
"AND thread_participants.type=threads.type GROUP BY accountId,threadId,type) as roles";
1112
1198
QStringList extraFields;
1136
1222
QList<QVariantMap> SQLiteHistoryPlugin::parseThreadResults(History::EventType type, QSqlQuery &query, const QVariantMap &properties)
1138
1224
QList<QVariantMap> threads;
1225
QList<QVariantMap> threadsWithoutParticipants;
1139
1226
QSqlQuery attachmentsQuery(SQLiteDatabase::instance()->database());
1140
1227
QList<QVariantMap> attachments;
1141
1228
bool grouped = false;
1170
1257
thread[History::FieldEventId] = query.value(2);
1171
1258
thread[History::FieldCount] = query.value(3);
1172
1259
thread[History::FieldUnreadCount] = query.value(4);
1173
QStringList participants = query.value(6).toString().split("|,|", QString::SkipEmptyParts);
1174
QList<int> participantStatus;
1175
QStringList participantStatusString = query.value(7).toString().split("|,|", QString::SkipEmptyParts);
1176
Q_FOREACH(const QString &statusString, participantStatusString) {
1177
participantStatus << statusString.toUInt();
1179
QStringList participantRolesString = query.value(8).toString().split("|,|", QString::SkipEmptyParts);
1180
QList<int> participantRoles;
1181
Q_FOREACH(const QString &rolesString, participantRolesString) {
1182
participantRoles << rolesString.toUInt();
1184
QVariantList contactList;
1185
QVariantList contactInfo = History::ContactMatcher::instance()->contactInfo(accountId, participants, true);
1186
for (int i = 0; i < contactInfo.count(); ++i) {
1187
QVariantMap map = contactInfo[i].toMap();
1188
map["state"] = participantStatus[i];
1189
map["roles"] = participantRoles[i];
1192
thread[History::FieldParticipants] = contactList;
1194
1261
// the generic event fields
1195
thread[History::FieldSenderId] = query.value(9);
1262
thread[History::FieldSenderId] = query.value(6);
1196
1263
thread[History::FieldTimestamp] = toLocalTimeString(query.value(5).toDateTime());
1197
thread[History::FieldNewEvent] = query.value(10).toBool();
1264
thread[History::FieldNewEvent] = query.value(7).toBool();
1199
1266
// the next step is to get the last event
1200
1267
switch (type) {
1225
1292
thread[History::FieldAttachments] = QVariant::fromValue(attachments);
1226
1293
attachments.clear();
1228
thread[History::FieldMessage] = query.value(11);
1229
thread[History::FieldMessageType] = query.value(12);
1230
thread[History::FieldMessageStatus] = query.value(13);
1231
thread[History::FieldReadTimestamp] = toLocalTimeString(query.value(14).toDateTime());
1232
thread[History::FieldChatType] = query.value(15).toUInt();
1295
thread[History::FieldMessage] = query.value(8);
1296
thread[History::FieldMessageType] = query.value(9);
1297
thread[History::FieldMessageStatus] = query.value(10);
1298
thread[History::FieldReadTimestamp] = toLocalTimeString(query.value(11).toDateTime());
1299
thread[History::FieldChatType] = query.value(12).toUInt();
1234
if (thread[History::FieldChatType].toInt() == 2) {
1301
if (thread[History::FieldChatType].toInt() == History::ChatTypeRoom) {
1235
1302
QVariantMap chatRoomInfo;
1236
1303
QSqlQuery query1(SQLiteDatabase::instance()->database());
1292
1359
thread[History::FieldChatRoomInfo] = chatRoomInfo;
1361
if (!History::Utils::shouldIncludeParticipants(History::Thread::fromProperties(thread))) {
1362
thread.remove(History::FieldParticipants);
1363
threadsWithoutParticipants << thread;
1295
1368
case History::EventTypeVoice:
1296
thread[History::FieldMissed] = query.value(12);
1297
thread[History::FieldDuration] = query.value(11);
1298
thread[History::FieldRemoteParticipant] = History::ContactMatcher::instance()->contactInfo(accountId, query.value(13).toString(), true);
1369
thread[History::FieldMissed] = query.value(9);
1370
thread[History::FieldDuration] = query.value(8);
1371
thread[History::FieldRemoteParticipant] = History::ContactMatcher::instance()->contactInfo(accountId, query.value(10).toString(), true);
1377
// get the participants
1378
threads = participantsForThreads(threads);
1380
// and append the threads with no participants
1381
threads << threadsWithoutParticipants;
1303
1383
return threads;
1317
1397
QString queryText;
1318
1398
switch (type) {
1319
1399
case History::EventTypeText:
1320
participantsField = participantsField.arg("text_events", QString::number(type));
1400
// for text events we don't need the participants at all
1401
participantsField = "\"\" as participants";
1321
1402
queryText = QString("SELECT accountId, threadId, eventId, senderId, timestamp, newEvent, %1, "
1322
1403
"message, messageType, messageStatus, readTimestamp, subject, informationType FROM text_events %2 %3").arg(participantsField, modifiedCondition, order);
1353
1434
event[History::FieldSenderId] = query.value(3);
1354
1435
event[History::FieldTimestamp] = toLocalTimeString(query.value(4).toDateTime());
1355
1436
event[History::FieldNewEvent] = query.value(5).toBool();
1356
QStringList participants = query.value(6).toString().split("|,|");
1357
event[History::FieldParticipants] = History::ContactMatcher::instance()->contactInfo(accountId, participants, true);
1437
if (type != History::EventTypeText) {
1438
QStringList participants = query.value(6).toString().split("|,|");
1439
event[History::FieldParticipants] = History::ContactMatcher::instance()->contactInfo(accountId, participants, true);
1359
1442
switch (type) {
1360
1443
case History::EventTypeText: