Merge lp:~libqtelegram-team/telegram-app/high-res-photos into lp:telegram-app/dev
- high-res-photos
- Merge into libqtelegram-dev
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 | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michał Karnicki (community) | Approve | ||
Review via email:
|
Commit message
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
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michał Karnicki (karni) wrote : | # |
- 189. By Roberto Mier Escandon
-
changed code as review comments
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Roberto Mier Escandon (rmescandon) wrote : | # |
answered inline
- 190. By Michał Karnicki
-
Properly locate PRAGMA fk toggles.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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.
- 191. By Michał Karnicki
-
Fix PRAGMA for realz.
Preview Diff
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); |
in-line comments. one notably is "Merge conflict in a block comment?"