Merge lp:~libqtelegram-team/telegram-app/high-res-photos into lp:telegram-app/dev

Proposed by Roberto Mier Escandon
Status: Merged
Approved by: Michał Karnicki
Approved revision: 191
Merged at revision: 175
Proposed branch: lp:~libqtelegram-team/telegram-app/high-res-photos
Merge into: lp:telegram-app/dev
Diff against target: 1687 lines (+671/-191)
19 files modified
lib/types/filelocation.h (+15/-9)
qmlplugin/data.cpp (+450/-165)
qmlplugin/data.h (+25/-3)
qmlplugin/dbmanager.cpp (+42/-2)
qmlplugin/dbmanager.h (+2/-0)
qmlplugin/dbschema.h (+39/-8)
qmlplugin/models/contactitem.cpp (+2/-0)
qmlplugin/models/contactitem.h (+5/-0)
qmlplugin/models/dialogsmodel.cpp (+23/-2)
qmlplugin/models/dialogsmodel.h (+2/-0)
qmlplugin/models/dialogsview.cpp (+1/-0)
qmlplugin/models/groupmodel.cpp (+17/-2)
qmlplugin/models/groupmodel.h (+5/-0)
qmlplugin/models/messagesmodel.cpp (+13/-0)
qmlplugin/models/messagesmodel.h (+2/-0)
qmlplugin/telegramclient.cpp (+10/-0)
qmlplugin/telegramclient.h (+4/-0)
qmlplugin/telegramservice.cpp (+10/-0)
qmlplugin/telegramservice.h (+4/-0)
To merge this branch: bzr merge lp:~libqtelegram-team/telegram-app/high-res-photos
Reviewer Review Type Date Requested Status
Michał Karnicki (community) Approve
Review via email: mp+249977@code.launchpad.net

Description of the change

Changes:
- Updated database to hold "bigPhoto" field for chats and users
- Insert and update chats and users almost the same way.
- Download thumbnail of the user or chat always when the user or chat is inserted
- It is needed that all the users and chats have an entry of server location for thumbnail and bigPhoto when inserted into db. Due to this, all the previous registers are not valid anymore and must be downloaded again from server.
- Because we need to download users and chats from server, a "purge without modifying secret chats" is implemented

Tested:
- Installed click package of previous release / created secret chats / install this branch + related app branch => checked that secret chats remain while rest of data is fetched from server
- Checked that users and chats have entries for thumbnail and bigPhoto server location if that location is availabe
- Checked that all bigPhotos are downloaded well when required from the UI
- All the already downloaded big photos are not downloaded again
- Smoke test of the general features of application

To post a comment you must log in.
Revision history for this message
Michał Karnicki (karni) wrote :

in-line comments. one notably is "Merge conflict in a block comment?"

189. By Roberto Mier Escandon

changed code as review comments

Revision history for this message
Roberto Mier Escandon (rmescandon) wrote :

answered inline

190. By Michał Karnicki

Properly locate PRAGMA fk toggles.

Revision history for this message
Michał Karnicki (karni) wrote :

Good changes. I pushed up revno 190.

However, after upgrade, the only secret chat I had is gone from the dialogs list. I also can't receive messages to it.

review: Needs Fixing
191. By Michał Karnicki

Fix PRAGMA for realz.

Revision history for this message
Michał Karnicki (karni) wrote :

Tested.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/types/filelocation.h'
2--- lib/types/filelocation.h 2014-08-18 21:40:29 +0000
3+++ lib/types/filelocation.h 2015-02-17 16:07:22 +0000
4@@ -31,15 +31,7 @@
5 typeFileLocationUnavailable = 0x7c596b46
6 };
7
8- FileLocation() :
9- m_localId(0),
10- m_secret(0),
11- m_dcId(0),
12- m_volumeId(0),
13- m_classType(typeFileLocationUnavailable) {
14- }
15-
16- FileLocation(FileLocationType classType) :
17+ FileLocation(FileLocationType classType = typeFileLocationUnavailable) :
18 m_localId(0),
19 m_secret(0),
20 m_dcId(0),
21@@ -47,6 +39,20 @@
22 m_classType = classType;
23 }
24
25+ bool operator==(const FileLocation &other) const {
26+ if (this->dcId() == other.dcId() &&
27+ this->localId() == other.localId() &&
28+ this->secret() == other.secret() &&
29+ this->volumeId() == other.volumeId()) {
30+ return true;
31+ }
32+ return false;
33+ }
34+
35+ bool operator!=(const FileLocation &other) const {
36+ return !((*this) == other);
37+ }
38+
39 void setDcId(qint32 dcId) {
40 m_dcId = dcId;
41 }
42
43=== modified file 'qmlplugin/data.cpp'
44--- qmlplugin/data.cpp 2015-02-12 12:57:55 +0000
45+++ qmlplugin/data.cpp 2015-02-17 16:07:22 +0000
46@@ -333,10 +333,15 @@
47 const User *user = mentionedUsers.value(peer.userId());
48 item.setIsChat(false);
49 item.setId(peer.userId());
50- item.setName(user->firstName() + " " + user->lastName());
51+ QString fullName = user->firstName() + " " + user->lastName();
52+ item.setName(fullName);
53 item.setPeerType(user->classType());
54 photoToDownload = user->photo().photoSmall();
55 isUserPhoto = true;
56+
57+ //TODO Roberto: this line is needed for this release to update the title of old secret chats
58+ // After this release, this line can be commented out or removed
59+ notifySecretChatsTitleUpdated(peer.userId(), fullName);
60 }
61 item.setDate(thismessage.date());
62 item.setUnreadCount(thisdialog.unreadCount());
63@@ -345,13 +350,12 @@
64 MessageItem messageItem = getMessage(thismessage.id());
65 item.setTopMessage(messageItem);
66
67- bool newPhotoFetched = getProfilePhotoFileFromServer(photoToDownload, item.id(), isUserPhoto);
68- if (!newPhotoFetched && (photoToDownload.classType() != FileLocation::typeFileLocationUnavailable)){
69- QString thumbnail = getThumbnail(item.id(), isUserPhoto);
70+ QString thumbnail = getThumbnail(item.id(), isUserPhoto);
71+ if (!thumbnail.isEmpty()) {
72+ item.setThumbnail(thumbnail);
73 if (isUserPhoto) {
74 Q_EMIT contactThumbnailUpdated(item.id(), thumbnail);
75 }
76- item.setThumbnail(thumbnail);
77 }
78
79 dlgs.append(item);
80@@ -496,7 +500,7 @@
81
82 switch (incomingFileType) {
83 case IncomingFile::UserThumbnail: {
84- if (updateThumbnail(id, true, filePath, serverLocation) <= 0) {
85+ if (insertOrUpdateUserThumbnail(id, filePath, serverLocation) <= 0) {
86 qCCritical(TG_PLUGIN_LOGIC) << "Could not update thumbnail local path" << filePath << "for user" << id;
87 break;
88 }
89@@ -507,20 +511,36 @@
90
91 break;
92 }
93+ case IncomingFile::UserPhoto: {
94+ if (insertOrUpdateUserBigPhoto(id, filePath, serverLocation) <= 0) {
95+ qCCritical(TG_PLUGIN_LOGIC) << "Could not update big photo local path" << filePath << "for user" << id;
96+ break;
97+ }
98+ Q_EMIT contactBigPhotoUpdated(id, filePath);
99+ break;
100+ }
101 case IncomingFile::ChatThumbnail: {
102- if (updateThumbnail(id, false, filePath, serverLocation) <= 0) {
103+ if (insertOrUpdateChatThumbnail(id, filePath, serverLocation) <= 0) {
104 qCCritical(TG_PLUGIN_LOGIC) << "Could not update thumbnail local path" << filePath << "for chat" << id;
105 break;
106 }
107 Q_EMIT dialogThumbnailUpdated(id, filePath);
108 break;
109 }
110+ case IncomingFile::ChatPhoto: {
111+ if (insertOrUpdateChatBigPhoto(id, filePath, serverLocation) <= 0) {
112+ qCCritical(TG_PLUGIN_LOGIC) << "Could not update big photo local path" << filePath << "for chat" << id;
113+ break;
114+ }
115+ Q_EMIT chatBigPhotoUpdated(id, filePath);
116+ break;
117+ }
118 case IncomingFile::MessageActionPhoto: {
119
120 // check if must execute the message action
121 if (mMessageIdsToUpdatePhoto.take(id)) {
122 qint32 dialogId = getDialogIdFromMessageId(id);
123- if (dialogId == 0 || updateThumbnail(dialogId, false, filePath, serverLocation) <= 0) {
124+ if (dialogId == 0 || insertOrUpdateChatThumbnail(dialogId, filePath, serverLocation) <= 0) {
125 qCCritical(TG_PLUGIN_LOGIC) << "Could not update thumbnail local path" << filePath << "for dialog" << dialogId;
126 break;
127 }
128@@ -651,7 +671,7 @@
129 ContactItem contactItem(user);
130
131 FileLocation photoToDownload = user.photo().photoSmall();
132- bool newPhotoFetched = getProfilePhotoFileFromServer(photoToDownload, user.id(), true);
133+ bool newPhotoFetched = getProfilePhotoFileFromServer(photoToDownload, user.id(), true, true);
134 if (!newPhotoFetched && (photoToDownload.classType() != FileLocation::typeFileLocationUnavailable)){
135 QString thumbnail = getThumbnail(user.id(), true);
136 contactItem.setThumbnail(thumbnail);
137@@ -663,9 +683,9 @@
138
139
140 if (changedUsername) {
141- QString completeName = user.firstName() + " " + user.lastName();
142- Q_EMIT dialogTitleUpdated(user.id(), completeName);
143- notifySecretChatsTitleUpdated(user.id(), completeName);
144+ QString fullName = user.firstName() + " " + user.lastName();
145+ Q_EMIT dialogTitleUpdated(user.id(), fullName);
146+ notifySecretChatsTitleUpdated(user.id(), fullName);
147 }
148
149 Q_EMIT userInfo(contactItem);
150@@ -750,7 +770,7 @@
151 ContactItem contactItem(user);
152
153 FileLocation photoToDownload = user.photo().photoSmall();
154- bool newPhotoFetched = getProfilePhotoFileFromServer(photoToDownload, user.id(), true);
155+ bool newPhotoFetched = getProfilePhotoFileFromServer(photoToDownload, user.id(), true, true);
156 if (!newPhotoFetched && (photoToDownload.classType() != FileLocation::typeFileLocationUnavailable)){
157 QString thumbnail = getThumbnail(user.id(), true);
158 contactItem.setThumbnail(thumbnail);
159@@ -789,7 +809,7 @@
160 ContactItem contactItem(user);
161
162 FileLocation photoToDownload = user.photo().photoSmall();
163- bool newPhotoFetched = getProfilePhotoFileFromServer(photoToDownload, user.id(), true);
164+ bool newPhotoFetched = getProfilePhotoFileFromServer(photoToDownload, user.id(), true, true);
165 if (!newPhotoFetched && (photoToDownload.classType() != FileLocation::typeFileLocationUnavailable)){
166 QString thumbnail = getThumbnail(user.id(), true);
167 contactItem.setThumbnail(thumbnail);
168@@ -1210,7 +1230,7 @@
169 dialogItem.setTopMessage(messageItem);
170 }
171
172- bool newPhotoFetched = getProfilePhotoFileFromServer(photoToDownload, dialogItem.id(), false);
173+ bool newPhotoFetched = getProfilePhotoFileFromServer(photoToDownload, dialogItem.id(), false, true);
174 if (!newPhotoFetched && (photoToDownload.classType() != FileLocation::typeFileLocationUnavailable)){
175 QString thumbnail = getThumbnail(dialogItem.id(), false);
176 dialogItem.setThumbnail(thumbnail);
177@@ -1867,7 +1887,7 @@
178 }
179
180 // Big photo location and photo size
181- FileLocation serverLocation;
182+ FileLocation serverLocation(FileLocation::typeFileLocation);
183 serverLocation.setDcId(attachment.dcId());
184 fileLocationId = insertFileLocation(serverLocation);
185 if (fileLocationId <= 0) {
186@@ -2115,9 +2135,9 @@
187 if (updateUserName(userId, firstName, lastName)) {
188 Q_EMIT contactNameUpdated(userId, firstName, lastName);
189
190- QString completeName = firstName + " " + lastName;
191- Q_EMIT dialogTitleUpdated(userId, completeName);
192- notifySecretChatsTitleUpdated(userId, completeName);
193+ QString fullName = firstName + " " + lastName;
194+ Q_EMIT dialogTitleUpdated(userId, fullName);
195+ notifySecretChatsTitleUpdated(userId, fullName);
196 }
197 }
198
199@@ -2125,7 +2145,8 @@
200 qint32 userId = update.userId();
201 const FileLocation &photoToDownload = update.photo().photoSmall();
202 bool isUserPhoto = true;
203- getProfilePhotoFileFromServer(photoToDownload, userId, isUserPhoto);
204+ bool isThumbnail = true;
205+ getProfilePhotoFileFromServer(photoToDownload, userId, isUserPhoto, isThumbnail);
206 }
207
208 bool Data::processUpdate(const Update &update, const QList<User> &users, const QList<Chat> &chats) {
209@@ -2138,7 +2159,7 @@
210 return false;
211 }
212 // request user photo if it has changed
213- getProfilePhotoFileFromServer(user.photo().photoSmall(), user.id(), true);
214+ getProfilePhotoFileFromServer(user.photo().photoSmall(), user.id(), true, true);
215 }
216 Q_FOREACH (const Chat &chat, chats) {
217 if (!insertOrUpdateChat(chat)) {
218@@ -2367,66 +2388,127 @@
219 }
220 }
221
222-bool Data::getProfilePhotoFileFromServer(const FileLocation &photoToDownload, qint32 id, bool isUser) {
223-
224- if (photoToDownload.classType() != FileLocation::typeFileLocationUnavailable) {
225-
226+bool Data::downloadUserBigPhoto(qint32 userId) {
227+ return downloadProfilePhoto(userId, true, false);
228+}
229+
230+bool Data::downloadChatBigPhoto(qint32 chatId) {
231+ return downloadProfilePhoto(chatId, false, false);
232+}
233+
234+bool Data::downloadProfilePhoto(qint32 id, bool isUser, bool isThumbnail) {
235+
236+ QPair<QString, FileLocation> fullFileLocation = getFullFileLocation(id, isUser, isThumbnail);
237+
238+ QString localPath = fullFileLocation.first;
239+ if (!localPath.isEmpty()) {
240+ qCWarning(TG_PLUGIN_LOGIC) << "profile photo for" << id << "has been previously downloaded. Skipping";
241+ return false;
242+ }
243+
244+ FileLocation serverLocation = fullFileLocation.second;
245+ return downloadPhotoFileFromServer(serverLocation, id, isUser, isThumbnail);
246+}
247+
248+QPair<QString, FileLocation> Data::getFullFileLocation(qint32 id, bool isUser, bool isThumbnail) {
249+
250+ QPair<QString, FileLocation> locationPair;
251+
252+ QString queryString("SELECT localPath, dcId, localId, secret, volumeId FROM fileLocations,%1 "
253+ "WHERE %1.%2=fileLocations.rowid AND %1.id=:id");
254+
255+ QString table = isUser ? "users" : "chats";
256+ QString field = isThumbnail ? "thumbnail" : "bigPhoto";
257+
258+ queryString = queryString.arg(table, field);
259+
260+ QSqlQuery query(mDbManager.database());
261+ query.prepare(queryString);
262+ query.bindValue(":id", id);
263+ if (!query.exec()) {
264+ qCCritical(TG_PLUGIN_LOGIC) << "Could not get" << field << "for" << table << " register with id" << id
265+ << query.lastError() << query.lastQuery();
266+ return locationPair;
267+ }
268+
269+ if (!query.next()) {
270+ qCCritical(TG_PLUGIN_LOGIC) << "Could not find" << field << "for a register in table" << table << "with id" << id;
271+ return locationPair;
272+ }
273+
274+ QString localPath = query.value("localPath").toString();
275+
276+ qint32 dcId = query.value("dcId").toInt();
277+ qint32 localId = query.value("localId").toInt();
278+ qint64 secret = query.value("secret").toLongLong();
279+ qint64 volumeId = query.value("volumeId").toLongLong();
280+
281+ FileLocation serverLocation(FileLocation::typeFileLocation);
282+ serverLocation.setDcId(dcId);
283+ serverLocation.setLocalId(localId);
284+ serverLocation.setSecret(secret);
285+ serverLocation.setVolumeId(volumeId);
286+
287+ locationPair = QPair<QString, FileLocation>(localPath, serverLocation);
288+
289+ return locationPair;
290+}
291+
292+bool Data::getProfilePhotoFileFromServer(const FileLocation &serverLocation, qint32 id, bool isUser, bool isThumbnail) {
293+
294+ if (serverLocation.classType() != FileLocation::typeFileLocationUnavailable) {
295 // Search in database if same location parameter are stored for thumbnail that
296 // received ones. In that case don't download cos it's the same file
297- QSqlQuery query(mDbManager.database());
298-
299- QString queryString("SELECT localPath, dcId, localId, secret, volumeId FROM fileLocations,%1 "
300- "WHERE %1.thumbnail=fileLocations.rowid AND %1.id=:id");
301- if (isUser) {
302- queryString = queryString.arg("users");
303- } else {
304- queryString = queryString.arg("chats");
305- }
306-
307- query.prepare(queryString);
308- query.bindValue(":id", id);
309- if (!query.exec()) {
310- qCCritical(TG_PLUGIN_LOGIC) << "Error:" << query.lastError() << query.lastQuery();
311+ QPair<QString, FileLocation> dbFullFileLocation = getFullFileLocation(id, isUser, isThumbnail);
312+ QString localPath = dbFullFileLocation.first;
313+ FileLocation dbLocation = dbFullFileLocation.second;
314+
315+ if (!localPath.isEmpty() && dbLocation == serverLocation) {
316 return false;
317 }
318
319- // Don't download if server location data is same as db and local path is not empty
320- if (query.next()) {
321- QString localPath = query.value("localPath").toString();
322- if (!localPath.isEmpty()) {
323- qint32 dcId = query.value("dcId").toInt();
324- qint32 localId = query.value("localId").toInt();
325- qint64 secret = query.value("secret").toLongLong();
326- qint64 volumeId = query.value("volumeId").toLongLong();
327-
328- if (dcId == photoToDownload.dcId() &&
329- localId == photoToDownload.localId() &&
330- secret == photoToDownload.secret() &&
331- volumeId == photoToDownload.volumeId()) {
332- return false;
333- }
334- }
335- }
336-
337+ return downloadPhotoFileFromServer(serverLocation, id, isUser, isThumbnail);
338+ }
339+ return false;
340+}
341+
342+bool Data::downloadPhotoFileFromServer(const FileLocation &serverLocation, qint32 id, bool isUser, bool isThumbnail) {
343+
344+ if (serverLocation.classType() != FileLocation::typeFileLocationUnavailable) {
345 // create object with the data of the file to be downloaded
346 TelegramService *service = static_cast<TelegramService *>(mServiceRef);
347 QString downloadsPath = service->config().downloadsPath();
348 IncomingFile *incomingFile = new IncomingFile(downloadsPath);
349 incomingFile->setId(id);
350- isUser ? incomingFile->setIncomingFileType(IncomingFile::UserThumbnail) :
351- incomingFile->setIncomingFileType(IncomingFile::ChatThumbnail);
352+
353+ IncomingFile::IncomingFileType incomingFileType;
354+ if (isUser) {
355+ if (isThumbnail) {
356+ incomingFileType = IncomingFile::UserThumbnail;
357+ } else {
358+ incomingFileType = IncomingFile::UserPhoto;
359+ }
360+ } else {
361+ if (isThumbnail) {
362+ incomingFileType = IncomingFile::ChatThumbnail;
363+ } else {
364+ incomingFileType = IncomingFile::ChatPhoto;
365+ }
366+ }
367+
368+ incomingFile->setIncomingFileType(incomingFileType);
369 incomingFile->setMediaType(MessageMedia::typeMessageMediaPhoto);
370- incomingFile->setIsThumbnail(true);
371+ incomingFile->setIsThumbnail(isThumbnail);
372 // default extension for photos is jpeg. If incoming file is enough big, response will not inform us
373 // about the real type of the incoming photo, so use this extension
374 incomingFile->setExtension(".jpeg");
375- incomingFile->setServerLocation(photoToDownload);
376+ incomingFile->setServerLocation(serverLocation);
377
378 InputFileLocation inputFileLocation(InputFileLocation::typeInputFileLocation);
379- inputFileLocation.setLocalId(photoToDownload.localId());
380- inputFileLocation.setSecret(photoToDownload.secret());
381- inputFileLocation.setVolumeId(photoToDownload.volumeId());
382- qint64 fileId = service->uploadGetFile(inputFileLocation, 0, photoToDownload.dcId());
383+ inputFileLocation.setLocalId(serverLocation.localId());
384+ inputFileLocation.setSecret(serverLocation.secret());
385+ inputFileLocation.setVolumeId(serverLocation.volumeId());
386+ qint64 fileId = service->uploadGetFile(inputFileLocation, 0, serverLocation.dcId());
387
388 mFiles.insert(fileId, incomingFile);
389 mActiveDownloads.insert(id, fileId);
390@@ -3596,6 +3678,10 @@
391
392 qint32 Data::insertFileLocation(const QString &localPath) {
393
394+ if (localPath.isEmpty()) {
395+ return 0;
396+ }
397+
398 QSqlQuery query(mDbManager.database());
399
400 query.prepare("INSERT INTO fileLocations (localPath) VALUES (:localPath)");
401@@ -3610,6 +3696,10 @@
402
403 qint32 Data::insertFileLocation(const FileLocation &fileLocation) {
404
405+ if (fileLocation.classType() == FileLocation::typeFileLocationUnavailable) {
406+ return 0;
407+ }
408+
409 QSqlQuery query(mDbManager.database());
410
411 query.prepare("INSERT INTO fileLocations (dcId, localId, secret, volumeId) "
412@@ -3629,28 +3719,6 @@
413 return -1;
414 }
415
416-qint32 Data::insertFileLocation(const FileLocation &fileLocation, const QString &localPath) {
417-
418- QSqlQuery query(mDbManager.database());
419-
420- query.prepare("INSERT INTO fileLocations (localPath, dcId, localId, secret, volumeId) "
421- "VALUES (:localPath, :dcId, :localId, :secret, :volumeId)");
422- query.bindValue(":localPath", localPath);
423- query.bindValue(":dcId", fileLocation.dcId());
424- query.bindValue(":localId", fileLocation.localId());
425- query.bindValue(":secret", fileLocation.secret());
426- query.bindValue(":volumeId", fileLocation.volumeId());
427- if (!query.exec()) {
428- qCCritical(TG_PLUGIN_LOGIC) << "Error when inserting new file location:" << query.lastError() << query.lastQuery();
429- return -1;
430- }
431-
432- if (query.numRowsAffected() > 0) {
433- return query.lastInsertId().toInt();
434- }
435- return -1;
436-}
437-
438 qint32 Data::updateFileLocation(qint32 fileLocationId, const FileLocation &fileLocation) {
439
440 QSqlQuery query(mDbManager.database());
441@@ -4429,9 +4497,11 @@
442
443 QSqlQuery query(mDbManager.database());
444
445- query.prepare("SELECT firstName, lastName, phone, localPath as thumbnail, "
446- "lastSeenOnline, online, type, accessHash "
447- "FROM users LEFT JOIN fileLocations ON fileLocations.rowid = users.thumbnail WHERE id=:id");
448+ query.prepare("SELECT firstName, lastName, phone, lastSeenOnline, online, type, accessHash, "
449+ "(SELECT localPath FROM fileLocations WHERE rowid=users.thumbnail) AS thumbnail, "
450+ "(SELECT localPath FROM fileLocations WHERE rowid=users.bigPhoto) AS bigPhoto "
451+ "FROM users "
452+ "WHERE id=:id");
453 query.bindValue(":id", id);
454 if (!query.exec()) {
455 qCCritical(TG_PLUGIN_LOGIC) << "Error when queried user with id:" << id << query.lastError() << query.lastQuery();
456@@ -4444,7 +4514,6 @@
457 contact.setFirstName(query.value("firstName").toString());
458 contact.setLastName(query.value("lastName").toString());
459 contact.setPhone(query.value("phone").toString());
460- contact.setThumbnail(query.value("thumbnail").toString());
461
462 UserStatus us(UserStatus::typeUserStatusOffline);
463 if (query.value("online").toBool()) {
464@@ -4453,6 +4522,8 @@
465 us.setWasOnline(query.value("lastSeenOnline").toInt());
466 contact.setClassType((User::UserType)query.value("type").toInt());
467 contact.setAccessHash(query.value("accessHash").toLongLong());
468+ contact.setThumbnail(query.value("thumbnail").toString());
469+ contact.setBigPhoto(query.value("bigPhoto").toString());
470
471 contact.setStatus(us);
472 } else {
473@@ -4466,7 +4537,10 @@
474
475 QSqlQuery query(mDbManager.database());
476
477- query.prepare("SELECT id, firstName, lastName, phone, thumbnail, lastSeenOnline, online, type, accessHash FROM users");
478+ query.prepare("SELECT id, firstName, lastName, phone, lastSeenOnline, online, type, accessHash, "
479+ "(SELECT localPath FROM fileLocations WHERE rowid=users.thumbnail) AS thumbnail, "
480+ "(SELECT localPath FROM fileLocations WHERE rowid=users.bigPhoto) AS bigPhoto "
481+ "FROM users");
482 if (!query.exec()) {
483 qCCritical(TG_PLUGIN_LOGIC) << "an error has happened when requesting complete contacts list";
484 return result;
485@@ -4478,6 +4552,7 @@
486 contact.setLastName(query.value("lastName").toString());
487 contact.setPhone(query.value("phone").toString());
488 contact.setThumbnail(query.value("thumbnail").toString());
489+ contact.setBigPhoto(query.value("bigPhoto").toString());
490 UserStatus us(UserStatus::typeUserStatusOffline);
491 if (query.value("online").toBool()) {
492 us.setClassType(UserStatus::typeUserStatusOnline);
493@@ -4529,56 +4604,207 @@
494 return true;
495 }
496
497+FileLocation Data::getFileLocation(qint32 fileLocationId) {
498+
499+ FileLocation serverLocation;
500+
501+ QSqlQuery query(mDbManager.database());
502+ query.prepare("SELECT dcId, localId, secret, volumeId FROM fileLocations WHERE rowid=:fileLocationId");
503+ query.bindValue(":fileLocationId", fileLocationId);
504+
505+ if (!query.exec()) {
506+ qCCritical(TG_PLUGIN_LOGIC) << "Could not get file location for rowid" << fileLocationId;
507+ } else if (query.next()) {
508+ serverLocation.setClassType(FileLocation::typeFileLocation);
509+ serverLocation.setDcId(query.value("dcId").toInt());
510+ serverLocation.setLocalId(query.value("localId").toInt());
511+ serverLocation.setSecret(query.value("secret").toLongLong());
512+ serverLocation.setVolumeId(query.value("volumeId").toLongLong());
513+ }
514+
515+ return serverLocation;
516+}
517+
518+bool Data::deleteFileLocation(qint32 fileLocationId) {
519+ QSqlQuery query(mDbManager.database());
520+ query.prepare("DELETE FROM fileLocations WHERE rowid=:fileLocationId");
521+ query.bindValue(":fileLocationId", fileLocationId);
522+ if (!query.exec()) {
523+ qCCritical(TG_PLUGIN_LOGIC) << "Could not delete file location with id" << fileLocationId;
524+ return false;
525+ }
526+ return query.numRowsAffected();
527+}
528+
529+qint32 Data::insertOrUpdateUserThumbnailFileLocation(const User &user) {
530+ return insertOrUpdateFileLocation(user.id(), user.photo().photoSmall(), true, true);
531+}
532+
533+qint32 Data::insertOrUpdateUserBigPhotoFileLocation(const User &user) {
534+ return insertOrUpdateFileLocation(user.id(), user.photo().photoBig(), true, false);
535+}
536+
537+qint32 Data::insertOrUpdateChatThumbnailFileLocation(const Chat &chat) {
538+ return insertOrUpdateFileLocation(chat.id(), chat.photo().photoSmall(), false, true);
539+}
540+
541+qint32 Data::insertOrUpdateChatBigPhotoFileLocation(const Chat &chat) {
542+ return insertOrUpdateFileLocation(chat.id(), chat.photo().photoBig(), false, false);
543+}
544+
545+
546+qint32 Data::insertOrUpdateFileLocation(qint32 id, const FileLocation &serverLocation, bool isUser, bool isThumbnail) {
547+ QString field = isThumbnail ? "thumbnail" : "bigPhoto";
548+ QString table = isUser ? "users" : "chats";
549+ QString sql = QString("SELECT %1 FROM %2 WHERE id=:id").arg(field, table);
550+
551+ QSqlQuery query(mDbManager.database());
552+ query.prepare(sql);
553+ query.bindValue(":id", id);
554+ if (!query.exec()) {
555+ qCCritical(TG_PLUGIN_LOGIC) << "Could not get" << field << "file location rowid in table" << table << "for" << id
556+ << query.lastError() << query.lastQuery();
557+ return -1;
558+ }
559+
560+ qint32 rowId = 0;
561+ if (query.next()) {
562+ rowId = query.value(field).toInt();
563+ if (rowId) {
564+ const FileLocation &dbLocation = getFileLocation(rowId);
565+ if (dbLocation == serverLocation) {
566+ return rowId;
567+ }
568+ }
569+ }
570+
571+ rowId = insertFileLocation(serverLocation);
572+
573+ if (rowId > 0 && isThumbnail) {
574+ getProfilePhotoFileFromServer(serverLocation, id, true, isThumbnail);
575+ }
576+
577+ return rowId;
578+}
579+
580+bool Data::existsUser(qint32 userId) {
581+ return exists(userId, true);
582+}
583+
584+bool Data::exists(qint32 id, bool isUser) {
585+
586+ QString table = isUser ? "users" : "chats";
587+ QString sql = QString("SELECT 1 FROM %1 WHERE id=:id").arg(table);
588+
589+ QSqlQuery query(mDbManager.database());
590+ query.prepare(sql);
591+ query.bindValue(":id", id);
592+ if (!query.exec()) {
593+ qCCritical(TG_PLUGIN_LOGIC) << "Could not check if exists" << id << "in" << table
594+ << query.lastError() << query.lastQuery();
595+ return false;
596+ }
597+
598+ return query.next();
599+}
600+
601+
602+bool Data::updateUser(const User &user) {
603+
604+ if (!existsUser(user.id())) {
605+ return false;
606+ }
607+
608+ bool online = user.status().classType() == UserStatus::typeUserStatusOnline;
609+
610+ qint32 thumbnailRowId = insertOrUpdateUserThumbnailFileLocation(user);
611+ if (thumbnailRowId < 0) {
612+ qCCritical(TG_PLUGIN_LOGIC) << "Could not update thumbnail for user" << user.id();
613+ return false;
614+ }
615+
616+ qint32 bigPhotoRowId = insertOrUpdateUserBigPhotoFileLocation(user);
617+ if (bigPhotoRowId < 0) {
618+ qCCritical(TG_PLUGIN_LOGIC) << "Could not update big photo for user" << user.id();
619+ if (thumbnailRowId > 0) {
620+ deleteFileLocation(thumbnailRowId);
621+ }
622+ return false;
623+ }
624+
625+ QSqlQuery query(mDbManager.database());
626+ query.prepare("UPDATE users SET firstName=:firstName, lastName=:lastName, phone=:phone, lastSeenOnline=:lastSeenOnline, "
627+ "online=:online, type=:type, accessHash=:accessHash, thumbnail=:thumbnail, bigPhoto=:bigPhoto WHERE id=:id");
628+ query.bindValue(":firstName", user.firstName());
629+ query.bindValue(":lastName", user.lastName());
630+ query.bindValue(":phone", user.phone());
631+ query.bindValue(":lastSeenOnline", user.status().wasOnline());
632+ query.bindValue(":online", online);
633+ query.bindValue(":type", user.classType());
634+ query.bindValue(":accessHash", user.accessHash());
635+ query.bindValue(":thumbnail", thumbnailRowId);
636+ query.bindValue(":bigPhoto", bigPhotoRowId);
637+ query.bindValue(":id", user.id());
638+ if (!query.exec()) {
639+ qCCritical(TG_PLUGIN_LOGIC) << "Could not update user" << user.id() << query.lastError() << query.lastQuery();
640+ return false;
641+ }
642+
643+ return query.numRowsAffected() > 0;
644+}
645+
646 bool Data::insertUser(const User &user) {
647
648 bool online = user.status().classType() == UserStatus::typeUserStatusOnline;
649
650+ mDbManager.beginTransaction();
651+
652 QSqlQuery query(mDbManager.database());
653
654+ FileLocation thumbnailServerLocation = user.photo().photoSmall();
655+ qint32 thumbnailRowId = insertFileLocation(thumbnailServerLocation);
656+ if (thumbnailRowId < 0) {
657+ qCCritical(TG_PLUGIN_LOGIC) << "Could not insert thumbnail server location related to user" << user.id();
658+ mDbManager.rollbackTransaction();
659+ return false;
660+ }
661+
662+ FileLocation photoBigServerLocation = user.photo().photoBig();
663+ qint32 bigPhotoRowId = insertFileLocation(photoBigServerLocation);
664+ if (bigPhotoRowId < 0) {
665+ qCCritical(TG_PLUGIN_LOGIC) << "Could not insert big photo server location related to user" << user.id();
666+ mDbManager.rollbackTransaction();
667+ return false;
668+ }
669+
670 // try to append user to database
671- query.prepare("INSERT INTO users (id, firstName, lastName, phone, lastSeenOnline, online, type, accessHash) "
672- "VALUES (:id, :firstName, :lastName, :phone, :lastSeenOnline, :online, :type, :accessHash)");
673- query.bindValue(":id", user.id());
674- query.bindValue(":firstName", user.firstName());
675- query.bindValue(":lastName", user.lastName());
676- query.bindValue(":phone", user.phone());
677- query.bindValue(":lastSeenOnline", user.status().wasOnline());
678- query.bindValue(":online", online);
679- query.bindValue(":type", user.classType());
680- query.bindValue(":accessHash", user.accessHash());
681-
682- if (!query.exec()) {
683- qCCritical(TG_PLUGIN_LOGIC) << "Error:" << query.lastError() << query.lastQuery();
684- return false;
685- }
686- return query.numRowsAffected() > 0;
687-}
688-
689-bool Data::updateUser(const User &user) {
690-
691- bool online = user.status().classType() == UserStatus::typeUserStatusOnline;
692-
693- QSqlQuery query(mDbManager.database());
694-
695- // try to update existant
696- query.prepare("UPDATE users SET firstName=:firstName, lastName=:lastName, phone=:phone, lastSeenOnline=:lastSeenOnline, "
697- "online=:online, type=:type, accessHash=:accessHash WHERE id=:id");
698-
699- query.bindValue(":firstName", user.firstName());
700- query.bindValue(":lastName", user.lastName());
701- query.bindValue(":phone", user.phone());
702- query.bindValue(":lastSeenOnline", user.status().wasOnline());
703- query.bindValue(":online", online);
704- query.bindValue(":type", user.classType());
705- query.bindValue(":accessHash", user.accessHash());
706- query.bindValue(":id", user.id());
707-
708- if (!query.exec()) {
709- qCCritical(TG_PLUGIN_LOGIC) << "Error:" << query.lastError() << query.lastQuery();
710- return false;
711- }
712- return query.numRowsAffected() > 0;
713-}
714+ query.prepare("INSERT INTO users (id, firstName, lastName, phone, lastSeenOnline, online, type, accessHash, thumbnail, bigPhoto) "
715+ "VALUES (:id, :firstName, :lastName, :phone, :lastSeenOnline, :online, :type, :accessHash, :thumbnail, :bigPhoto)");
716+ query.bindValue(":id", user.id());
717+ query.bindValue(":firstName", user.firstName());
718+ query.bindValue(":lastName", user.lastName());
719+ query.bindValue(":phone", user.phone());
720+ query.bindValue(":lastSeenOnline", user.status().wasOnline());
721+ query.bindValue(":online", online);
722+ query.bindValue(":type", user.classType());
723+ query.bindValue(":accessHash", user.accessHash());
724+ query.bindValue(":thumbnail", thumbnailRowId);
725+ query.bindValue(":bigPhoto", bigPhotoRowId);
726+ if (!query.exec()) {
727+ qCCritical(TG_PLUGIN_LOGIC) << "Could not insert new user:" << query.lastError() << query.lastQuery();
728+ mDbManager.rollbackTransaction();
729+ return false;
730+ }
731+
732+ mDbManager.finishTransaction();
733+
734+ if (thumbnailRowId > 0) {
735+ getProfilePhotoFileFromServer(thumbnailServerLocation, user.id(), true, true);
736+ }
737+
738+ return query.numRowsAffected() > 0;
739+}
740+
741
742 bool Data::updateUserName(qint32 userId, const QString &firstName, const QString &lastName) {
743
744@@ -4693,6 +4919,10 @@
745 return dialog;
746 }
747
748+bool Data::existsChat(qint32 chatId) {
749+ return exists(chatId, false);
750+}
751+
752 bool Data::insertOrUpdateChat(const Chat &chat) {
753 if (!updateChat(chat)) {
754 return insertChat(chat);
755@@ -4701,39 +4931,85 @@
756 return true;
757 }
758
759-void bindChatValuesForQuery(QSqlQuery &query, const Chat &chat) {
760+void bindChatValuesForQuery(QSqlQuery &query, const Chat &chat, qint32 thumbnailRowId, qint32 bigPhotoRowId) {
761 query.bindValue(":id", chat.id());
762 query.bindValue(":version", chat.version());
763 query.bindValue(":title", chat.title());
764 query.bindValue(":participantsCount", chat.participantsCount());
765+ query.bindValue(":thumbnail", thumbnailRowId);
766+ query.bindValue(":bigPhoto", bigPhotoRowId);
767 query.bindValue(":date", chat.date());
768 query.bindValue(":left", chat.left());
769 }
770
771 bool Data::insertChat(const Chat &chat) {
772+
773+ mDbManager.beginTransaction();
774+
775+ FileLocation thumbnailServerLocation = chat.photo().photoSmall();
776+ qint32 thumbnailRowId = insertFileLocation(thumbnailServerLocation);
777+ if (thumbnailRowId < 0) {
778+ qCCritical(TG_PLUGIN_LOGIC) << "Could not insert thumbnail server location related to chat" << chat.id();
779+ mDbManager.rollbackTransaction();
780+ return false;
781+ }
782+
783+ FileLocation bigPhotoServerLocation = chat.photo().photoBig();
784+ qint32 bigPhotoRowId = insertFileLocation(bigPhotoServerLocation);
785+ if (bigPhotoRowId < 0) {
786+ qCCritical(TG_PLUGIN_LOGIC) << "Could not insert big photo server location related to chat" << chat.id();
787+ mDbManager.rollbackTransaction();
788+ return false;
789+ }
790+
791 QSqlQuery query(mDbManager.database());
792- query.prepare("INSERT INTO chats (id, version, title, participantsCount, date, left) "
793- "VALUES (:id, :version, :title, :participantsCount, :date, :left)");
794- bindChatValuesForQuery(query, chat);
795-
796+ query.prepare("INSERT INTO chats (id, version, title, participantsCount, thumbnail, bigPhoto, date, left) "
797+ "VALUES (:id, :version, :title, :participantsCount, :thumbnail, :bigPhoto, :date, :left)");
798+ bindChatValuesForQuery(query, chat, thumbnailRowId, bigPhotoRowId);
799 if (!query.exec()) {
800 qCCritical(TG_PLUGIN_LOGIC) << "Error:" << query.lastError() << query.lastQuery();
801 return false;
802 }
803+
804+ if (thumbnailRowId > 0) {
805+ getProfilePhotoFileFromServer(thumbnailServerLocation, chat.id(), false, true);
806+ }
807+
808+ mDbManager.finishTransaction();
809 return query.numRowsAffected() > 0;
810 }
811
812 bool Data::updateChat(const Chat &chat) {
813+
814+ if (!existsChat(chat.id())) {
815+ return false;
816+ }
817+
818+ qint32 thumbnailRowId = insertOrUpdateChatThumbnailFileLocation(chat);
819+ if (thumbnailRowId < 0) {
820+ qCCritical(TG_PLUGIN_LOGIC) << "Could not update thumbnail for chat" << chat.id();
821+ return false;
822+ }
823+
824+ qint32 bigPhotoRowId = insertOrUpdateChatBigPhotoFileLocation(chat);
825+ if (bigPhotoRowId < 0) {
826+ qCCritical(TG_PLUGIN_LOGIC) << "Could not update big photo for chat" << chat.id();
827+ if (thumbnailRowId > 0) {
828+ deleteFileLocation(thumbnailRowId);
829+ }
830+ return false;
831+ }
832+
833 QSqlQuery query(mDbManager.database());
834 query.prepare("UPDATE chats SET version=:version, title=:title, "
835- "participantsCount=:participantsCount, date=:date, left=:left "
836+ "participantsCount=:participantsCount, thumbnail=:thumbnail, bigPhoto=:bigPhoto, date=:date, left=:left "
837 "WHERE id=:id");
838- bindChatValuesForQuery(query, chat);
839-
840+ bindChatValuesForQuery(query, chat, thumbnailRowId, bigPhotoRowId);
841 if (!query.exec()) {
842 qCCritical(TG_PLUGIN_LOGIC) << "Error:" << query.lastError() << query.lastQuery();
843 return false;
844 }
845+
846 return query.numRowsAffected() > 0;
847 }
848
849@@ -4799,19 +5075,33 @@
850 return query.numRowsAffected() > 0;
851 }
852
853-qint32 Data::updateThumbnail(qint32 id, bool isUser, const QString &localPath, const FileLocation &serverLocation) {
854-
855- mDbManager.beginTransaction();
856-
857- QSqlQuery query(mDbManager.database());
858+qint32 Data::insertOrUpdateUserThumbnail(qint32 id, const QString &localPath, const FileLocation &serverLocation) {
859+ return insertOrUpdateProfilePhoto(id, true, true, localPath, serverLocation);
860+}
861+
862+qint32 Data::insertOrUpdateChatThumbnail(qint32 id, const QString &localPath, const FileLocation &serverLocation) {
863+ return insertOrUpdateProfilePhoto(id, false, true, localPath, serverLocation);
864+}
865+
866+qint32 Data::insertOrUpdateUserBigPhoto(qint32 id, const QString &localPath, const FileLocation &serverLocation) {
867+ return insertOrUpdateProfilePhoto(id, true, false, localPath, serverLocation);
868+}
869+
870+qint32 Data::insertOrUpdateChatBigPhoto(qint32 id, const QString &localPath, const FileLocation &serverLocation) {
871+ return insertOrUpdateProfilePhoto(id, false, false, localPath, serverLocation);
872+}
873+
874+qint32 Data::insertOrUpdateProfilePhoto(qint32 id, bool isUser, bool isThumbnail, const QString &localPath, const FileLocation &serverLocation) {
875
876 QString queryString("UPDATE fileLocations SET localPath=:localPath, dcId=:dcId, localId=:localId, secret=:secret, volumeId=:volumeId "
877- "WHERE rowid IN (SELECT thumbnail FROM %1 WHERE id=:id)");
878- if (isUser) {
879- queryString = queryString.arg("users");
880- } else {
881- queryString = queryString.arg("chats");
882- }
883+ "WHERE rowid IN (SELECT %1 FROM %2 WHERE id=:id)");
884+
885+ QString table = isUser ? "users" : "chats";
886+ QString field = isThumbnail ? "thumbnail" : "bigPhoto";
887+ queryString = queryString.arg(field, table);
888+
889+ mDbManager.beginTransaction();
890+ QSqlQuery query(mDbManager.database());
891 query.prepare(queryString);
892 query.bindValue(":localPath", localPath);
893 query.bindValue(":dcId", serverLocation.dcId());
894@@ -4820,7 +5110,7 @@
895 query.bindValue(":volumeId", serverLocation.volumeId());
896 query.bindValue(":id", id);
897 if (!query.exec()) {
898- qCCritical(TG_PLUGIN_LOGIC) << "Error:" << query.lastError() << query.lastQuery();
899+ qCCritical(TG_PLUGIN_LOGIC) << "Could not update fileLocations table:" << query.lastError() << query.lastQuery();
900 mDbManager.rollbackTransaction();
901 return -1;
902 }
903@@ -4835,31 +5125,26 @@
904 query.bindValue(":secret", serverLocation.secret());
905 query.bindValue(":volumeId", serverLocation.volumeId());
906 if (!query.exec()) {
907- qCCritical(TG_PLUGIN_LOGIC) << "Error:" << query.lastError() << query.lastQuery();
908+ qCCritical(TG_PLUGIN_LOGIC) << "Could not insert fileLocations new register:" << query.lastError() << query.lastQuery();
909 mDbManager.rollbackTransaction();
910 return -1;
911 }
912
913 qint32 lastRowId = query.lastInsertId().toInt();
914
915- queryString = "UPDATE %1 SET thumbnail=:thumbnail WHERE id=:id";
916- if (isUser) {
917- queryString = queryString.arg("users");
918- } else {
919- queryString = queryString.arg("chats");
920- }
921+ queryString = QString("UPDATE %1 SET %2=:rowid WHERE id=:id").arg(table, field);
922 query.prepare(queryString);
923- query.bindValue(":thumbnail", lastRowId);
924+ query.bindValue(":rowid", lastRowId);
925 query.bindValue(":id", id);
926 if (!query.exec()) {
927- qCCritical(TG_PLUGIN_LOGIC) << "Error:" << query.lastError() << query.lastQuery();
928+ qCCritical(TG_PLUGIN_LOGIC) << "Could not update" << field << "for" << table << "register"
929+ << query.lastError() << query.lastQuery();
930 mDbManager.rollbackTransaction();
931 return -1;
932 }
933 }
934
935 mDbManager.finishTransaction();
936-
937 return query.numRowsAffected();
938 }
939
940
941=== modified file 'qmlplugin/data.h'
942--- qmlplugin/data.h 2015-02-12 12:56:32 +0000
943+++ qmlplugin/data.h 2015-02-17 16:07:22 +0000
944@@ -20,6 +20,7 @@
945 #include <QObject>
946 #include <QList>
947 #include <QLoggingCategory>
948+#include <QPair>
949 #include <types/message.h>
950 #include <types/dialog.h>
951 #include <types/user.h>
952@@ -69,11 +70,17 @@
953 qint32 getUnreadCount(qint32 dialogId);
954
955 // user operations
956+ bool existsUser(qint32 userId);
957 bool insertOrUpdateUser(const User &user);
958 bool insertUser(const User &user);
959 bool updateUser(const User &user);
960 bool updateUserName(qint32 userId, const QString &firstName, const QString &lastName);
961 bool updateUserIsContact(qint32 userId, bool isContact, bool hasPhone);
962+ qint32 insertOrUpdateUserThumbnailFileLocation(const User &user);
963+ qint32 insertOrUpdateUserBigPhotoFileLocation(const User &user);
964+ qint32 insertOrUpdateChatThumbnailFileLocation(const Chat &chat);
965+ qint32 insertOrUpdateChatBigPhotoFileLocation(const Chat &chat);
966+ qint32 insertOrUpdateFileLocation(qint32 id, const FileLocation &serverLocation, bool isUser, bool isThumbnail);
967 bool deleteUsers();
968 bool hasChangedUsername(const User &user);
969 ContactItem getUser(qint32 id);
970@@ -86,6 +93,7 @@
971 bool updateContactsLink(qint32 userId, const ContactsMyLink &myLink, const ContactsForeignLink &foreignLink);
972
973 // chat operations
974+ bool existsChat(qint32 chatId);
975 bool insertOrUpdateChat(const Chat &chat);
976 bool insertChat(const Chat &chat);
977 bool updateChat(const Chat &chat);
978@@ -129,7 +137,10 @@
979 MessageItem topMessage(qint32 dialogId);
980
981 QString getThumbnail(qint32 id, bool isUser);
982- qint32 updateThumbnail(qint32 id, bool isUser, const QString &localPath, const FileLocation &serverLocation);
983+ qint32 insertOrUpdateUserThumbnail(qint32 id, const QString &localPath, const FileLocation &serverLocation);
984+ qint32 insertOrUpdateUserBigPhoto(qint32 id, const QString &localPath, const FileLocation &serverLocation);
985+ qint32 insertOrUpdateChatThumbnail(qint32 id, const QString &localPath, const FileLocation &serverLocation);
986+ qint32 insertOrUpdateChatBigPhoto(qint32 id, const QString &localPath, const FileLocation &serverLocation);
987
988 qint32 existsPhoto(qint64 photoId);
989 qint32 insertPhoto(const Photo &photo);
990@@ -139,6 +150,8 @@
991 void downloadThumbnail(qint32 id, const Photo &photo, IncomingFile::IncomingFileType incomingFileType);
992 void downloadPhoto(qint32 id, const Photo &photo, IncomingFile::IncomingFileType incomingFileType);
993 bool downloadPhoto(qint32 messageId);
994+ bool downloadUserBigPhoto(qint32 userId);
995+ bool downloadChatBigPhoto(qint32 chatId);
996
997 PhotoSize getPhotoSize(qint32 id);
998 qint32 getPhotoMsgId(qint32 id);
999@@ -150,9 +163,10 @@
1000 QString getVideoLocalPath(qint64 videoId);
1001 bool downloadVideo(qint32 messageId);
1002 qint32 insertOrUpdatePhotoSize(qint64 oldMediaId, qint64 newMediaId, const PhotoSize &photoSize);
1003+ FileLocation getFileLocation(qint32 fileLocationId);
1004+ bool deleteFileLocation(qint32 fileLocationId);
1005 qint32 insertFileLocation(const QString &localPath);
1006 qint32 insertFileLocation(const FileLocation &fileLocation);
1007- qint32 insertFileLocation(const FileLocation &fileLocation, const QString &localPath);
1008 qint32 updateFileLocation(qint32 fileLocationId, const QString &localPath);
1009 qint32 updateFileLocation(qint32 fileLocationId, const FileLocation &fileLocation);
1010 qint32 insertPhotoSize(qint64 photoId, const PhotoSize &photoSize, qint32 fileLocationId);
1011@@ -193,6 +207,8 @@
1012 void dialogsAdded(const QList<DialogItem> &dialogs, qint32 totalCount = -1);
1013 void chatUpdated(const qint32 chatId);
1014 void contactThumbnailUpdated(qint32 userId, const QString &thumbnail);
1015+ void contactBigPhotoUpdated(qint32 userId, const QString &bigPhoto);
1016+ void chatBigPhotoUpdated(qint32 chatId, const QString &bigPhoto);
1017 void dialogThumbnailUpdated(qint32 dialogId, const QString &thumbnail);
1018 void contactNameUpdated(qint32 userId, const QString &firstName, const QString lastName);
1019 void dialogTitleUpdated(qint32 dialogId, const QString &title);
1020@@ -254,12 +270,16 @@
1021 QMap<qint64, qint32> mMuteInProgress;
1022 QMap<qint64, qint32> mUnmuteInProgress;
1023
1024+ QPair<QString, FileLocation> getFullFileLocation(qint32 id, bool isUser, bool isThumbnail);
1025 QString getThumbnailLocalPath(qint64 photoId);
1026 QString getPhotoLocalPath(qint64 photoId, bool isThumbnail = false);
1027 QList<qint32> getMediaMessages(qint64 mediaId);
1028+ qint32 insertOrUpdateProfilePhoto(qint32 id, bool isUser, bool isThumbnail, const QString &localPath, const FileLocation &serverLocation);
1029
1030 // returns true if queried server to get the photo file
1031- bool getProfilePhotoFileFromServer(const FileLocation &photo, qint32 id, bool isUser);
1032+ bool downloadProfilePhoto(qint32 id, bool isUser, bool isThumbnail);
1033+ bool getProfilePhotoFileFromServer(const FileLocation &serverLocation, qint32 id, bool isUser, bool isThumbnail);
1034+ bool downloadPhotoFileFromServer(const FileLocation &serverLocation, qint32 id, bool isUser, bool isThumbnail);
1035 void selectSizeAndDownloadPhoto(qint32 id, const Photo &photo, IncomingFile::IncomingFileType incomingFileType, bool thumbnail = true);
1036 void downloadPhotoSize(qint32 id, qint64 mediaId, qint32 date, IncomingFile::IncomingFileType incomingFileType,
1037 bool thumbnail, const PhotoSize &photoSize, qint32 fileLocationId);
1038@@ -304,6 +324,8 @@
1039
1040 void surfaceUnreadCount();
1041
1042+ bool exists(qint32 id, bool isUser);
1043+
1044 private Q_SLOTS:
1045 void onUpdatesGetStateAnswer(qint64 id, qint32 pts, qint32 qts, qint32 date, qint32 seq, qint32 unreadCount);
1046 void onUpdatesGetDifferenceAnswer(qint64 id, qint32 date, qint32 seq);
1047
1048=== modified file 'qmlplugin/dbmanager.cpp'
1049--- qmlplugin/dbmanager.cpp 2015-02-03 16:38:05 +0000
1050+++ qmlplugin/dbmanager.cpp 2015-02-17 16:07:22 +0000
1051@@ -39,9 +39,10 @@
1052 const qint32 VERSION_READ_HISTORY = 8;
1053 const qint32 VERSION_ENCRYPTED_MEDIA_KEYS = 9;
1054 const qint32 VERSION_ENCRYPTED_TTL = 10;
1055+const qint32 VERSION_PROFILE_BIG_PHOTO = 11;
1056
1057 // Update this line when creating new upgrade version.
1058-const qint32 DATABASE_VERSION = VERSION_ENCRYPTED_TTL;
1059+const qint32 DATABASE_VERSION = VERSION_PROFILE_BIG_PHOTO;
1060
1061
1062 DbManager::DbManager(QObject *parent) :
1063@@ -163,6 +164,7 @@
1064
1065 bool DbManager::create() {
1066 QStringList queries;
1067+
1068 queries << Schema::CREATE_USERS;
1069 queries << Schema::CREATE_DIALOGS;
1070 queries << Schema::CREATE_CHATS;
1071@@ -205,7 +207,6 @@
1072 queries << QString("DROP VIEW %1").arg(name);
1073 }
1074
1075- // after views, delete tables in reverse orden of creation
1076 queries << UpgradeSecretChats::DROP_SECRET_CHATS;
1077 queries << UpgradeGroupChat::DROP_PARTICIPANTS;
1078 queries << Schema::DROP_MESSAGE_ACTIONS;
1079@@ -273,6 +274,10 @@
1080 // fall-through
1081 case VERSION_ENCRYPTED_TTL:
1082 version = VERSION_ENCRYPTED_TTL;
1083+ if (!upgradeProfilesBigPhotos()) break;
1084+ // fall-through
1085+ case VERSION_PROFILE_BIG_PHOTO:
1086+ version = VERSION_PROFILE_BIG_PHOTO;
1087
1088 // Upgrade cases go here.
1089 }
1090@@ -418,6 +423,41 @@
1091 return executeSqlQueries(queries);
1092 }
1093
1094+bool DbManager::upgradeProfilesBigPhotos() {
1095+ qCDebug(LOG_DATABASE) << "Upgrading database: adding bigPhoto to users and chats tables";
1096+ return purgeButSecret();
1097+}
1098+
1099+bool DbManager::purgeButSecret() {
1100+ qCDebug(LOG_DATABASE) << "Purging database but secret chats data...";
1101+
1102+ QSqlQuery query(mDatabase);
1103+ query.exec("PRAGMA foreign_keys = false");
1104+
1105+ QStringList queries;
1106+
1107+ queries << PurgeButSecret::DELETE_FILE_LOCATIONS_BUT_SECRET;
1108+ queries << PurgeButSecret::DELETE_PHOTO_SIZES_BUT_SECRET;
1109+ queries << PurgeButSecret::DELETE_MEDIA_PHOTOS_BUT_SECRET;
1110+ queries << PurgeButSecret::DELETE_MEDIA_VIDEOS_BUT_SECRET;
1111+ queries << PurgeButSecret::DELETE_MESSAGE_ACTIONS_BUT_SECRET;
1112+ queries << PurgeButSecret::DELETE_MESSAGES_BUT_SECRET;
1113+ queries << PurgeButSecret::DELETE_DIALOGS_BUT_SECRET;
1114+
1115+ queries << UpgradeGroupChat::DROP_PARTICIPANTS;
1116+ queries << Schema::DROP_CHATS;
1117+ queries << Schema::DROP_USERS;
1118+ queries << Schema::CREATE_USERS;
1119+ queries << Schema::CREATE_CHATS;
1120+ queries << UpgradeGroupChat::CREATE_PARTICIPANTS;
1121+
1122+ bool result = executeSqlQueries(queries);
1123+
1124+ query.exec("PRAGMA foreign_keys = true");
1125+
1126+ return result;
1127+}
1128+
1129 bool DbManager::beginTransaction() {
1130 mTransactionsDepth++;
1131 if (mTransactionsDepth == 1) {
1132
1133=== modified file 'qmlplugin/dbmanager.h'
1134--- qmlplugin/dbmanager.h 2015-02-03 16:38:05 +0000
1135+++ qmlplugin/dbmanager.h 2015-02-17 16:07:22 +0000
1136@@ -51,6 +51,7 @@
1137
1138 bool create();
1139 bool purge();
1140+ bool purgeButSecret(); // removes all database data except the one related with secret chats that would be missed if deleted
1141 void upgrade(qint32 oldVersion, qint32 newVersion);
1142
1143 bool upgradeMessageActionsRemovePhotoId();
1144@@ -62,6 +63,7 @@
1145 bool upgradeReadHistory();
1146 bool upgradeEncryptedMediaKeys();
1147 bool upgradeEncryptedTtl();
1148+ bool upgradeProfilesBigPhotos();
1149
1150 private:
1151 QString mDatabasePath;
1152
1153=== modified file 'qmlplugin/dbschema.h'
1154--- qmlplugin/dbschema.h 2015-02-03 16:38:05 +0000
1155+++ qmlplugin/dbschema.h 2015-02-17 16:07:22 +0000
1156@@ -32,13 +32,15 @@
1157 " firstName VARCHAR(255),\n"
1158 " lastName VARCHAR(255),\n"
1159 " phone VARCHAR(15),\n"
1160-" thumbnail INT,\n"
1161+" thumbnail INT DEFAULT 0,\n"
1162+" bigPhoto INT DEFAULT 0,\n"
1163 " lastSeenOnline INT,\n"
1164 " online BOOL,\n"
1165 " type INT,\n"
1166 " accessHash LONG,\n"
1167 " CONSTRAINT pk_users_id PRIMARY KEY (id),\n"
1168-" CONSTRAINT fk_users_thumbnail FOREIGN KEY (thumbnail) REFERENCES fileLocations(rowid)\n"
1169+" CONSTRAINT fk_users_thumbnail FOREIGN KEY (thumbnail) REFERENCES fileLocations(rowid),\n"
1170+" CONSTRAINT fk_users_bigPhoto FOREIGN KEY (bigPhoto) REFERENCES fileLocations(rowid)\n"
1171 ")");
1172
1173 const QString DROP_USERS("DROP TABLE IF EXISTS users");
1174@@ -51,7 +53,8 @@
1175 " muted BOOL DEFAULT 0,\n"
1176 " date INT,\n"
1177 " isSecret BOOL DEFAULT 0,\n"
1178-" CONSTRAINT pk_dialogs_id PRIMARY KEY (id)\n"
1179+" CONSTRAINT pk_dialogs_id PRIMARY KEY (id),\n"
1180+" CONSTRAINT fk_secretChats_id FOREIGN KEY (id) REFERENCES secretChats(id)\n"
1181 ")");
1182
1183 const QString DROP_DIALOGS("DROP TABLE IF EXISTS dialogs");
1184@@ -61,12 +64,14 @@
1185 " id INT NOT NULL,\n"
1186 " title VARCHAR(255),\n"
1187 " participantsCount TINYINT,\n"
1188-" thumbnail INT,\n"
1189+" thumbnail INT DEFAULT 0,\n"
1190+" bigPhoto INT DEFAULT 0,\n"
1191 " date INT,\n"
1192 " left BOOL,\n"
1193 " version INT,\n"
1194 " CONSTRAINT pk_chats_id PRIMARY KEY (id),\n"
1195-" CONSTRAINT fk_chat_thumbnail FOREIGN KEY (thumbnail) REFERENCES fileLocations(rowid)\n"
1196+" CONSTRAINT fk_chat_thumbnail FOREIGN KEY (thumbnail) REFERENCES fileLocations(rowid),\n"
1197+" CONSTRAINT fk_chat_bigPhoto FOREIGN KEY (bigPhoto) REFERENCES fileLocations(rowid)\n"
1198 ")");
1199
1200 const QString DROP_CHATS("DROP TABLE IF EXISTS chats");
1201@@ -89,7 +94,9 @@
1202 " mediaType INT,\n"
1203 " mediaId LONG,\n"
1204 " CONSTRAINT pk_messages_id PRIMARY KEY (id),\n"
1205-" CONSTRAINT fk_mediaId_mediaPhotos FOREIGN KEY (mediaId) REFERENCES fileLocations(rowid)\n"
1206+" CONSTRAINT fk_mediaId_mediaPhotos FOREIGN KEY (mediaId) REFERENCES mediaPhotos(id),\n"
1207+" CONSTRAINT fk_mediaId_mediaVideos FOREIGN KEY (mediaId) REFERENCES mediaVideos(id),\n"
1208+" CONSTRAINT fk_id_messageActions FOREIGN KEY (id) REFERENCES messageActions(messageId)\n"
1209 ")");
1210
1211 const QString DROP_MESSAGES("DROP TABLE IF EXISTS messages");
1212@@ -124,7 +131,8 @@
1213 " geoLong LONG,\n"
1214 " key TEXT,\n"
1215 " iv TEXT,\n"
1216-" CONSTRAINT pk_mediaPhotos_id PRIMARY KEY (id)\n"
1217+" CONSTRAINT pk_mediaPhotos_id PRIMARY KEY (id),\n"
1218+" CONSTRAINT fk_mediaPhotos_id FOREIGN KEY (id) REFERENCES photoSizes(photoId)"
1219 ")");
1220
1221 const QString DROP_MEDIA_PHOTOS("DROP TABLE IF EXISTS mediaPhotos");
1222@@ -137,7 +145,7 @@
1223 " height INT,\n"
1224 " size INT,\n"
1225 " fileLocationId INT,\n"
1226-" CONSTRAINT fk_photoSizes_photoId FOREIGN KEY (photoId) REFERENCES mediaPhotos(id)\n"
1227+" CONSTRAINT fk_photoSizes_fileLocationId FOREIGN KEY (fileLocationId) REFERENCES fileLocations(rowid)\n"
1228 ")");
1229
1230 const QString DROP_PHOTO_SIZES("DROP TABLE IF EXISTS photoSizes");
1231@@ -315,4 +323,27 @@
1232 const QString ALTER_MESSAGES_ADD_TTL("ALTER TABLE messages ADD COLUMN ttl INT DEFAULT 0");
1233
1234 }
1235+
1236+namespace PurgeButSecret {
1237+
1238+const QString DELETE_FILE_LOCATIONS_BUT_SECRET("DELETE FROM fileLocations WHERE rowid IN "
1239+ "(SELECT fileLocationId FROM photoSizes WHERE photoId IN "
1240+ "(SELECT mediaId FROM messages WHERE dialogId NOT IN "
1241+ "(SELECT id FROM secretChats)));");
1242+const QString DELETE_PHOTO_SIZES_BUT_SECRET("DELETE FROM photoSizes WHERE photoId IN "
1243+ "(SELECT mediaId FROM messages WHERE dialogId NOT IN "
1244+ "(SELECT id FROM secretChats))");
1245+const QString DELETE_MEDIA_PHOTOS_BUT_SECRET("DELETE FROM mediaPhotos WHERE id IN "
1246+ "(SELECT mediaId FROM messages WHERE dialogId NOT IN "
1247+ "(SELECT id FROM secretChats))");
1248+const QString DELETE_MEDIA_VIDEOS_BUT_SECRET("DELETE FROM mediaVideos WHERE id IN "
1249+ "(SELECT mediaId FROM messages WHERE dialogId NOT IN "
1250+ "(SELECT id FROM secretChats))");
1251+const QString DELETE_MESSAGE_ACTIONS_BUT_SECRET("DELETE FROM messageActions WHERE messageId IN "
1252+ "(SELECT id FROM messages WHERE dialogId NOT IN"
1253+ "(SELECT id FROM secretChats))");
1254+const QString DELETE_MESSAGES_BUT_SECRET("DELETE FROM messages WHERE dialogId NOT IN (SELECT id FROM secretChats)");
1255+const QString DELETE_DIALOGS_BUT_SECRET("DELETE FROM dialogs WHERE isSecret=0");
1256+
1257+}
1258 #endif // DBSCHEMA_H
1259
1260=== modified file 'qmlplugin/models/contactitem.cpp'
1261--- qmlplugin/models/contactitem.cpp 2014-09-17 12:37:00 +0000
1262+++ qmlplugin/models/contactitem.cpp 2015-02-17 16:07:22 +0000
1263@@ -43,6 +43,7 @@
1264 setLastName(contactItem.lastName());
1265 setPhone(contactItem.phone());
1266 setThumbnail(contactItem.thumbnail());
1267+ setBigPhoto(contactItem.bigPhoto());
1268 setStatus(*contactItem.status());
1269 setAccessHash(contactItem.accessHash());
1270 setClassType(contactItem.classType());
1271@@ -67,6 +68,7 @@
1272 qCDebug(TG_PLUGIN_LOGIC) << "LatsName" << lastName();
1273 qCDebug(TG_PLUGIN_LOGIC) << "phone" << phone();
1274 qCDebug(TG_PLUGIN_LOGIC) << "thumbnail" << thumbnail();
1275+ qCDebug(TG_PLUGIN_LOGIC) << "bigPhoto" << bigPhoto();
1276 qCDebug(TG_PLUGIN_LOGIC) << "lastSeenOnline" << lastSeenOnline();
1277 qCDebug(TG_PLUGIN_LOGIC) << "online" << online();
1278 qCDebug(TG_PLUGIN_LOGIC) << "---";
1279
1280=== modified file 'qmlplugin/models/contactitem.h'
1281--- qmlplugin/models/contactitem.h 2014-08-18 18:49:11 +0000
1282+++ qmlplugin/models/contactitem.h 2015-02-17 16:07:22 +0000
1283@@ -27,6 +27,7 @@
1284 Q_PROPERTY(qint32 lastSeenOnline READ lastSeenOnline NOTIFY lastSeenOnlineChanged)
1285 Q_PROPERTY(bool online READ online NOTIFY onlineChanged)
1286 Q_PROPERTY(QString thumbnail READ thumbnail NOTIFY thumbnailChanged)
1287+ Q_PROPERTY(QString bigPhoto READ bigPhoto WRITE setBigPhoto NOTIFY bigPhotoChanged)
1288
1289 public:
1290
1291@@ -38,6 +39,8 @@
1292
1293 QString thumbnail() const { return m_thumbnail; }
1294 void setThumbnail(const QString &thumbnail) { m_thumbnail = thumbnail; }
1295+ QString bigPhoto() const { return mBigPhoto; }
1296+ void setBigPhoto(const QString &bigPhoto) { mBigPhoto = bigPhoto; }
1297
1298 qint32 lastSeenOnline() const;
1299 bool online() const;
1300@@ -49,9 +52,11 @@
1301 void lastSeenOnlineChanged(qint32);
1302 void onlineChanged(bool);
1303 void thumbnailChanged(QString);
1304+ void bigPhotoChanged(QString);
1305
1306 private:
1307 QString m_thumbnail;
1308+ QString mBigPhoto;
1309 };
1310 Q_DECLARE_METATYPE(ContactItem)
1311
1312
1313=== modified file 'qmlplugin/models/dialogsmodel.cpp'
1314--- qmlplugin/models/dialogsmodel.cpp 2015-02-04 22:36:12 +0000
1315+++ qmlplugin/models/dialogsmodel.cpp 2015-02-17 16:07:22 +0000
1316@@ -27,6 +27,7 @@
1317 QAbstractListModel(parent),
1318 mCanFetchMore(true),
1319 mState(Created),
1320+ mSecretDialogsCount(0),
1321 mTelegramClient(0) {
1322 }
1323
1324@@ -253,6 +254,7 @@
1325 beginRemoveRows(QModelIndex(), 0, mDialogs.count() - 1);
1326 mDialogs.clear();
1327 endRemoveRows();
1328+ mSecretDialogsCount = 0;
1329 }
1330
1331 mCanFetchMore = true;
1332@@ -268,6 +270,7 @@
1333 }
1334
1335 void DialogsModel::initialize() {
1336+
1337 switch (mState) {
1338 case Created:
1339 updateQuery();
1340@@ -275,7 +278,7 @@
1341 case Initializing:
1342 break;
1343 case Ready:
1344- if (!mDialogs.count()) {
1345+ if (regularDialogsCount() == 0) {
1346 fetchMore();
1347 }
1348 break;
1349@@ -316,7 +319,7 @@
1350 } else if (!mTelegramClient->connected()) {
1351 qCWarning(TG_PLUGIN_LOGIC) << "Could not get dialogs. Telegram client reference is not connected";
1352 } else {
1353- mTelegramClient->messagesGetDialogs(mDialogs.count(), 0, 20);
1354+ mTelegramClient->messagesGetDialogs(regularDialogsCount(), 0, 20);
1355 }
1356 } else {
1357 insertOrUpdateDialogs(dialogs);
1358@@ -331,6 +334,10 @@
1359 mTopMessageIdsMap.insert(dialog.topMessage().id(), dialog.id());
1360 mDialogs.append(dialog);
1361 endInsertRows();
1362+
1363+ if (dialog.isSecret()) {
1364+ mSecretDialogsCount++;
1365+ }
1366 }
1367
1368 void DialogsModel::clear() {
1369@@ -338,6 +345,7 @@
1370 mDlgIdsMap.clear();
1371 mTopMessageIdsMap.clear();
1372 mDialogs.clear();
1373+ mSecretDialogsCount = 0;
1374 endResetModel();
1375 }
1376
1377@@ -368,6 +376,10 @@
1378 mDlgIdsMap.insert(newDialog.id(), mDialogs.count());
1379 mTopMessageIdsMap.insert(newDialog.topMessage().id(), newDialog.id());
1380 mDialogs << newDialog;
1381+
1382+ if (newDialog.isSecret()) {
1383+ mSecretDialogsCount++;
1384+ }
1385 }
1386 endInsertRows();
1387 }
1388@@ -385,6 +397,10 @@
1389 mCanFetchMore = totalCount > 0 && totalCount > mDialogs.count();
1390 }
1391
1392+qint32 DialogsModel::regularDialogsCount() {
1393+ return mDialogs.count() - mSecretDialogsCount;
1394+}
1395+
1396 void DialogsModel::onThumbnailUpdated(qint32 id, const QString &thumbnail) {
1397 qint32 pos = mDlgIdsMap.value(id, -1);
1398 if (pos >= 0) {
1399@@ -697,6 +713,11 @@
1400
1401 qint32 pos = mDlgIdsMap.value(dialogId, -1);
1402 if (0 <= pos && pos < mDialogs.size()) {
1403+
1404+ if (mDialogs.at(pos).isSecret()) {
1405+ mSecretDialogsCount--;
1406+ }
1407+
1408 mDlgIdsMap.clear();
1409 beginRemoveRows(QModelIndex(), pos, pos);
1410 mDialogs.removeAt(pos);
1411
1412=== modified file 'qmlplugin/models/dialogsmodel.h'
1413--- qmlplugin/models/dialogsmodel.h 2015-02-03 12:25:51 +0000
1414+++ qmlplugin/models/dialogsmodel.h 2015-02-17 16:07:22 +0000
1415@@ -104,12 +104,14 @@
1416
1417 bool mCanFetchMore;
1418 ModelState mState;
1419+ qint32 mSecretDialogsCount;
1420
1421 // reference to telegram client
1422 TelegramClient *mTelegramClient;
1423
1424 void deleteDialog(qint32 dialogId);
1425 void insertOrUpdateDialogs(const QList<DialogItem> &dialogs);
1426+ qint32 regularDialogsCount();
1427
1428 private Q_SLOTS:
1429 void onNextPage(const QList<DialogItem> &dialogs);
1430
1431=== modified file 'qmlplugin/models/dialogsview.cpp'
1432--- qmlplugin/models/dialogsview.cpp 2015-01-12 19:33:57 +0000
1433+++ qmlplugin/models/dialogsview.cpp 2015-02-17 16:07:22 +0000
1434@@ -36,6 +36,7 @@
1435 qCCritical(TG_PLUGIN_LOGIC) << "Error:" << mQuery.lastError() << mQuery.lastQuery();
1436 }
1437
1438+
1439 while (mQuery.next()) {
1440 DialogItem dialog;
1441
1442
1443=== modified file 'qmlplugin/models/groupmodel.cpp'
1444--- qmlplugin/models/groupmodel.cpp 2015-01-12 09:03:06 +0000
1445+++ qmlplugin/models/groupmodel.cpp 2015-02-17 16:07:22 +0000
1446@@ -69,6 +69,17 @@
1447 }
1448 }
1449
1450+QString GroupModel::getThumbnail() const {
1451+ return mThumbnail;
1452+}
1453+
1454+void GroupModel::setThumbnail(const QString &thumbnail) {
1455+ if (mThumbnail != thumbnail) {
1456+ mThumbnail = thumbnail;
1457+ Q_EMIT thumbnailChanged(thumbnail);
1458+ }
1459+}
1460+
1461 QString GroupModel::getPhoto() const {
1462 return mPhoto;
1463 }
1464@@ -105,6 +116,7 @@
1465 void GroupModel::resetGroupDetails() {
1466 mChatId = 0;
1467 setTitle(QString());
1468+ setThumbnail("");
1469 setPhoto("");
1470 setCount(0);
1471 setMuted(false);
1472@@ -116,7 +128,8 @@
1473
1474 QSqlQuery query;
1475 query.prepare(QString("SELECT title, "
1476- "(SELECT localPath FROM fileLocations WHERE fileLocations.rowid=thumbnail) AS photo, "
1477+ "(SELECT localPath FROM fileLocations WHERE fileLocations.rowid=thumbnail) AS thumbnail, "
1478+ "(SELECT localPath FROM fileLocations WHERE fileLocations.rowid=bigPhoto) AS photo, "
1479 "participantsCount AS count, muted "
1480 "FROM chats JOIN dialogs ON chats.id = dialogs.id "
1481 "WHERE dialogs.id = :id"));
1482@@ -129,6 +142,8 @@
1483 } else if (query.next()) {
1484 QString title = query.value("title").toString();
1485 setTitle(title);
1486+ QString thumbnail = query.value("thumbnail").toString();
1487+ setThumbnail(thumbnail);
1488 QString photo = query.value("photo").toString();
1489 setPhoto(photo);
1490 qint32 count = query.value("count").toInt();
1491@@ -146,7 +161,7 @@
1492
1493 void GroupModel::chatThumbnailUpdated(qint32 chatId, QString thumbnail) {
1494 if (mChatId != chatId) return;
1495- setPhoto(thumbnail);
1496+ setThumbnail(thumbnail);
1497 }
1498
1499 void GroupModel::chatMuted(qint32 chatId, bool muted) {
1500
1501=== modified file 'qmlplugin/models/groupmodel.h'
1502--- qmlplugin/models/groupmodel.h 2014-12-12 14:02:13 +0000
1503+++ qmlplugin/models/groupmodel.h 2015-02-17 16:07:22 +0000
1504@@ -29,6 +29,7 @@
1505 Q_OBJECT
1506 Q_PROPERTY(qint32 chatId READ getChatId WRITE setChatId NOTIFY chatIdChanged)
1507 Q_PROPERTY(QString title READ getTitle NOTIFY titleChanged)
1508+ Q_PROPERTY(QString thumbnail READ getThumbnail NOTIFY thumbnailChanged)
1509 Q_PROPERTY(QString photo READ getPhoto NOTIFY photoChanged)
1510 Q_PROPERTY(qint32 count READ getCount NOTIFY countChanged)
1511 Q_PROPERTY(bool muted READ getMuted NOTIFY mutedChanged)
1512@@ -43,6 +44,7 @@
1513 void setChatId(qint32 chatId);
1514 qint32 getChatId() const;
1515 QString getTitle() const;
1516+ QString getThumbnail() const;
1517 QString getPhoto() const;
1518 qint32 getCount() const;
1519 bool getMuted() const;
1520@@ -58,6 +60,7 @@
1521
1522 private:
1523 void setTitle(const QString &title);
1524+ void setThumbnail(const QString &thumbnail);
1525 void setPhoto(const QString &photo);
1526 void setCount(const qint32 count);
1527 void setMuted(bool muted);
1528@@ -65,6 +68,7 @@
1529 Q_SIGNALS:
1530 void chatIdChanged(qint32 chatId);
1531 void titleChanged(QString title);
1532+ void thumbnailChanged(QString thumbnail);
1533 void photoChanged(QString photo);
1534 void countChanged(qint32 count);
1535 void mutedChanged(bool muted);
1536@@ -74,6 +78,7 @@
1537
1538 qint32 mChatId;
1539 QString mTitle;
1540+ QString mThumbnail;
1541 QString mPhoto;
1542 qint32 mCount;
1543 bool mMuted;
1544
1545=== modified file 'qmlplugin/models/messagesmodel.cpp'
1546--- qmlplugin/models/messagesmodel.cpp 2015-02-04 21:49:12 +0000
1547+++ qmlplugin/models/messagesmodel.cpp 2015-02-17 16:07:22 +0000
1548@@ -90,6 +90,8 @@
1549 connect(mTelegramClient, SIGNAL(downloadedPercentageUpdated(qint32,qint8)), SLOT(onMessageDownloadedPercentageUpdated(qint32,qint8)));
1550
1551 connect(mTelegramClient, SIGNAL(messagesNextPage(QList<MessageItem>)), SLOT(onNextPage(QList<MessageItem>)));
1552+
1553+ connect(mTelegramClient, SIGNAL(contactThumbnailUpdated(qint32,QString)), SLOT(onContactThumbnailUpdated(qint32,QString)));
1554 }
1555 }
1556
1557@@ -552,6 +554,17 @@
1558 clear();
1559 }
1560
1561+void MessagesModel::onContactThumbnailUpdated(qint32 userId, const QString &localPath) {
1562+ for (qint32 pos = 0; pos < mMessages.count(); pos++) {
1563+ MessageItem &message = mMessages[pos];
1564+ if (message.fromId() == userId) {
1565+ message.setFromThumbnail(localPath);
1566+ const QVector<qint32> changedRoles(QVector<qint32>() << FromThumbnailRole);
1567+ Q_EMIT dataChanged(index(pos), index(pos), changedRoles);
1568+ }
1569+ }
1570+}
1571+
1572 bool MessagesModel::exists(const MessageItem &message) {
1573 return mKeysMap.value(message.id(), 0) != 0;
1574 }
1575
1576=== modified file 'qmlplugin/models/messagesmodel.h'
1577--- qmlplugin/models/messagesmodel.h 2015-02-04 09:37:32 +0000
1578+++ qmlplugin/models/messagesmodel.h 2015-02-17 16:07:22 +0000
1579@@ -114,6 +114,8 @@
1580 void onMessageDownloadingUpdated(qint32 msgId, bool downloading);
1581 void onMessageDownloadedPercentageUpdated(qint32 msgId, qint8 downloadedPercentage);
1582
1583+ void onContactThumbnailUpdated(qint32 userId, const QString &localPath);
1584+
1585 private:
1586 const QVector<qint32> DOWNLOADED_PERCENTAGE_CHANGED_ROLES;
1587
1588
1589=== modified file 'qmlplugin/telegramclient.cpp'
1590--- qmlplugin/telegramclient.cpp 2015-02-03 19:23:45 +0000
1591+++ qmlplugin/telegramclient.cpp 2015-02-17 16:07:22 +0000
1592@@ -53,6 +53,8 @@
1593 // connect signal-signal comming from data updates
1594 connect(mTelegramService, SIGNAL(contactsAdded(QList<ContactItem>)), SIGNAL(contactsAdded(QList<ContactItem>)), Qt::QueuedConnection);
1595 connect(mTelegramService, SIGNAL(contactThumbnailUpdated(qint32,QString)), SIGNAL(contactThumbnailUpdated(qint32,QString)), Qt::QueuedConnection);
1596+ connect(mTelegramService, SIGNAL(contactBigPhotoUpdated(qint32,QString)), SIGNAL(contactBigPhotoUpdated(qint32,QString)), Qt::QueuedConnection);
1597+ connect(mTelegramService, SIGNAL(chatBigPhotoUpdated(qint32,QString)), SIGNAL(chatBigPhotoUpdated(qint32,QString)), Qt::QueuedConnection);
1598 connect(mTelegramService, SIGNAL(dialogThumbnailUpdated(qint32,QString)), SIGNAL(dialogThumbnailUpdated(qint32,QString)), Qt::QueuedConnection);
1599 connect(mTelegramService, SIGNAL(dialogTitleUpdated(qint32,QString)), SIGNAL(dialogTitleUpdated(qint32,QString)), Qt::QueuedConnection);
1600 connect(mTelegramService, SIGNAL(dialogMuted(qint32,bool)), SIGNAL(dialogMuted(qint32,bool)), Qt::QueuedConnection);
1601@@ -252,6 +254,14 @@
1602 QMetaObject::invokeMethod(mTelegramService, "downloadVideo", Qt::QueuedConnection, Q_ARG(qint32, messageId));
1603 }
1604
1605+void TelegramClient::downloadUserBigPhoto(qint32 userId) {
1606+ QMetaObject::invokeMethod(mTelegramService, "downloadUserBigPhoto", Qt::QueuedConnection, Q_ARG(qint32, userId));
1607+}
1608+
1609+void TelegramClient::downloadChatBigPhoto(qint32 chatId) {
1610+ QMetaObject::invokeMethod(mTelegramService, "downloadChatBigPhoto", Qt::QueuedConnection, Q_ARG(qint32, chatId));
1611+}
1612+
1613 void TelegramClient::cancelDownload(qint32 id) {
1614 QMetaObject::invokeMethod(mTelegramService, "cancelDownload", Qt::QueuedConnection, Q_ARG(qint32, id));
1615 }
1616
1617=== modified file 'qmlplugin/telegramclient.h'
1618--- qmlplugin/telegramclient.h 2015-02-03 19:23:45 +0000
1619+++ qmlplugin/telegramclient.h 2015-02-17 16:07:22 +0000
1620@@ -61,6 +61,8 @@
1621 Q_INVOKABLE void getUser(qint32 userId);
1622 Q_INVOKABLE void downloadPhoto(qint32 messageId);
1623 Q_INVOKABLE void downloadVideo(qint32 messageId);
1624+ Q_INVOKABLE void downloadUserBigPhoto(qint32 userId);
1625+ Q_INVOKABLE void downloadChatBigPhoto(qint32 chatId);
1626 Q_INVOKABLE void cancelDownload(qint32 id);
1627 Q_INVOKABLE void mute(qint32 peerId);
1628 Q_INVOKABLE void unmute(qint32 peerId);
1629@@ -115,6 +117,8 @@
1630 void contactsAdded(const QList<ContactItem> &contacts);
1631 void dialogsAdded(const QList<DialogItem> &dialogs, qint32 totalCount);
1632 void contactThumbnailUpdated(qint32 userId, const QString &thumbnail);
1633+ void contactBigPhotoUpdated(qint32 userId, const QString &bigPhoto);
1634+ void chatBigPhotoUpdated(qint32 chatId, const QString &bigPhoto);
1635 void dialogThumbnailUpdated(qint32 dialogId, const QString &thumbnail);
1636 void dialogTitleUpdated(qint32 dialogId, const QString &title);
1637 void dialogMuted(qint32 dialogId, bool muted);
1638
1639=== modified file 'qmlplugin/telegramservice.cpp'
1640--- qmlplugin/telegramservice.cpp 2015-02-17 11:35:00 +0000
1641+++ qmlplugin/telegramservice.cpp 2015-02-17 16:07:22 +0000
1642@@ -39,6 +39,8 @@
1643 //Data signals linked to 'this' signals
1644 connect(&mData, SIGNAL(contactsAdded(QList<ContactItem>)), SIGNAL(contactsAdded(QList<ContactItem>)));
1645 connect(&mData, SIGNAL(contactThumbnailUpdated(qint32,QString)), SIGNAL(contactThumbnailUpdated(qint32,QString)));
1646+ connect(&mData, SIGNAL(contactBigPhotoUpdated(qint32,QString)), SIGNAL(contactBigPhotoUpdated(qint32,QString)));
1647+ connect(&mData, SIGNAL(chatBigPhotoUpdated(qint32,QString)), SIGNAL(chatBigPhotoUpdated(qint32,QString)));
1648 connect(&mData, SIGNAL(dialogThumbnailUpdated(qint32,QString)), SIGNAL(dialogThumbnailUpdated(qint32,QString)));
1649 connect(&mData, SIGNAL(dialogTitleUpdated(qint32,QString)), SIGNAL(dialogTitleUpdated(qint32,QString)));
1650 connect(&mData, SIGNAL(dialogMuted(qint32,bool)), SIGNAL(dialogMuted(qint32,bool)));
1651@@ -514,6 +516,14 @@
1652 return mData.downloadPhoto(messageId);
1653 }
1654
1655+bool TelegramService::downloadUserBigPhoto(qint32 userId) {
1656+ return mData.downloadUserBigPhoto(userId);
1657+}
1658+
1659+bool TelegramService::downloadChatBigPhoto(qint32 chatId) {
1660+ return mData.downloadChatBigPhoto(chatId);
1661+}
1662+
1663 qint64 TelegramService::sendVideo(qint32 peerId, const QString &videoPath, qint32 duration, qint32 width, qint32 height, const QString &thumbnailPath) {
1664
1665 QString videoLocalPath = copyToDownloadsPath(videoPath);
1666
1667=== modified file 'qmlplugin/telegramservice.h'
1668--- qmlplugin/telegramservice.h 2015-02-17 11:35:00 +0000
1669+++ qmlplugin/telegramservice.h 2015-02-17 16:07:22 +0000
1670@@ -61,6 +61,8 @@
1671 qint64 messagesSetTyping(const InputPeer peer);
1672 qint64 messagesDeleteMessages(const QList<qint32> &msgIds, bool isSecret = false);
1673 bool downloadPhoto(qint32 messageId);
1674+ bool downloadUserBigPhoto(qint32 userId);
1675+ bool downloadChatBigPhoto(qint32 chatId);
1676 qint64 sendVideo(qint32 peerId, const QString &videoFilePath, qint32 duration = 0, qint32 width = 0, qint32 height = 0, const QString &thumbnailFilePath = "");
1677 bool downloadVideo(qint32 messageId);
1678 qint64 cancelDownload(qint32 id);
1679@@ -112,6 +114,8 @@
1680 // models signals
1681 void contactsAdded(const QList<ContactItem> &contacts);
1682 void contactThumbnailUpdated(qint32 userId, const QString &thumbnail);
1683+ void contactBigPhotoUpdated(qint32 userId, const QString &bigPhoto);
1684+ void chatBigPhotoUpdated(qint32 chatId, const QString &bigPhoto);
1685 void dialogThumbnailUpdated(qint32 dialogId, const QString &thumbnail);
1686 void dialogTitleUpdated(qint32 dialogId, const QString &title);
1687 void dialogMuted(qint32 dialogId, bool muted);

Subscribers

People subscribed via source and target branches

to all changes: