Merge lp:~mzanetti/reminders-app/enable-deleting-notebooks-and-tags into lp:reminders-app
- enable-deleting-notebooks-and-tags
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Riccardo Padovani |
Approved revision: | 453 |
Merged at revision: | 451 |
Proposed branch: | lp:~mzanetti/reminders-app/enable-deleting-notebooks-and-tags |
Merge into: | lp:reminders-app |
Diff against target: |
761 lines (+303/-38) 16 files modified
src/app/qml/components/NotebooksDelegate.qml (+1/-0) src/app/qml/components/TagsDelegate.qml (+1/-0) src/app/qml/reminders.qml (+2/-1) src/libqtevernote/CMakeLists.txt (+1/-0) src/libqtevernote/jobs/expungetagjob.cpp (+52/-0) src/libqtevernote/jobs/expungetagjob.h (+46/-0) src/libqtevernote/notebook.cpp (+17/-0) src/libqtevernote/notebook.h (+5/-0) src/libqtevernote/notebooks.cpp (+11/-0) src/libqtevernote/notebooks.h (+3/-1) src/libqtevernote/notesstore.cpp (+127/-35) src/libqtevernote/notesstore.h (+1/-0) src/libqtevernote/tag.cpp (+17/-0) src/libqtevernote/tag.h (+5/-0) src/libqtevernote/tags.cpp (+11/-0) src/libqtevernote/tags.h (+3/-1) |
To merge this branch: | bzr merge lp:~mzanetti/reminders-app/enable-deleting-notebooks-and-tags |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Phone Apps Jenkins Bot | continuous-integration | Approve | |
Riccardo Padovani | Approve | ||
Review via email: mp+261774@code.launchpad.net |
Commit message
Enable deleting notebooks and tags on Evernote
Description of the change
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
Riccardo Padovani (rpadovani) wrote : | # |
There are a lot of warnings due your changes: http://
Also, there is a strange warning in qml when you delete a tag which has notes attached: it says
`Sync: Save tag job finished, but tag can't be found any more`
This is really a minor issue, but as console output doesn't make any sense
- 452. By Michael Zanetti
-
fix networkingstatus check
- 453. By Michael Zanetti
-
fix warnings, drop unneeded save call before deleting
Michael Zanetti (mzanetti) wrote : | # |
> There are a lot of warnings due your changes:
> http://
>
> Also, there is a strange warning in qml when you delete a tag which has notes
> attached: it says
>
> `Sync: Save tag job finished, but tag can't be found any more`
>
> This is really a minor issue, but as console output doesn't make any sense
All fixed. thanks a lot
Riccardo Padovani (rpadovani) wrote : | # |
Tested deeply, looks all good to me now, thanks!
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
PASSED: Continuous integration, rev:453
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'src/app/qml/components/NotebooksDelegate.qml' |
2 | --- src/app/qml/components/NotebooksDelegate.qml 2015-03-15 20:00:21 +0000 |
3 | +++ src/app/qml/components/NotebooksDelegate.qml 2015-06-11 21:38:48 +0000 |
4 | @@ -89,6 +89,7 @@ |
5 | color: root.notebookColor |
6 | fontSize: "large" |
7 | Layout.fillWidth: true |
8 | + font.strikeout: model.deleted |
9 | } |
10 | |
11 | Label { |
12 | |
13 | === modified file 'src/app/qml/components/TagsDelegate.qml' |
14 | --- src/app/qml/components/TagsDelegate.qml 2015-03-15 20:00:21 +0000 |
15 | +++ src/app/qml/components/TagsDelegate.qml 2015-06-11 21:38:48 +0000 |
16 | @@ -80,6 +80,7 @@ |
17 | text: model.name |
18 | fontSize: "large" |
19 | Layout.fillWidth: true |
20 | + font.strikeout: model.deleted |
21 | } |
22 | } |
23 | |
24 | |
25 | === modified file 'src/app/qml/reminders.qml' |
26 | --- src/app/qml/reminders.qml 2015-06-01 09:56:30 +0000 |
27 | +++ src/app/qml/reminders.qml 2015-06-11 21:38:48 +0000 |
28 | @@ -383,7 +383,8 @@ |
29 | onAuthenticated: { |
30 | EvernoteConnection.token = reply.AccessToken; |
31 | print("token is:", EvernoteConnection.token) |
32 | - if (NetworkingStatus.online) { |
33 | + print("NetworkingStatus.online:", NetworkingStatus.Online) |
34 | + if (NetworkingStatus.Online) { |
35 | EvernoteConnection.connectToEvernote(); |
36 | } |
37 | } |
38 | |
39 | === modified file 'src/libqtevernote/CMakeLists.txt' |
40 | --- src/libqtevernote/CMakeLists.txt 2015-03-06 00:42:42 +0000 |
41 | +++ src/libqtevernote/CMakeLists.txt 2015-06-11 21:38:48 +0000 |
42 | @@ -32,6 +32,7 @@ |
43 | jobs/fetchtagsjob.cpp |
44 | jobs/createtagjob.cpp |
45 | jobs/savetagjob.cpp |
46 | + jobs/expungetagjob.cpp |
47 | resourceimageprovider.cpp |
48 | utils/enmldocument.cpp |
49 | utils/organizeradapter.cpp |
50 | |
51 | === added file 'src/libqtevernote/jobs/expungetagjob.cpp' |
52 | --- src/libqtevernote/jobs/expungetagjob.cpp 1970-01-01 00:00:00 +0000 |
53 | +++ src/libqtevernote/jobs/expungetagjob.cpp 2015-06-11 21:38:48 +0000 |
54 | @@ -0,0 +1,52 @@ |
55 | +/* |
56 | + * Copyright: 2015 Canonical, Ltd |
57 | + * |
58 | + * This file is part of reminders |
59 | + * |
60 | + * reminders is free software: you can redistribute it and/or modify |
61 | + * it under the terms of the GNU General Public License as published by |
62 | + * the Free Software Foundation; version 3. |
63 | + * |
64 | + * reminders is distributed in the hope that it will be useful, |
65 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
66 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
67 | + * GNU General Public License for more details. |
68 | + * |
69 | + * You should have received a copy of the GNU General Public License |
70 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
71 | + * |
72 | + * Authors: Michael Zanetti <michael.zanetti@canonical.com> |
73 | + */ |
74 | + |
75 | +#include "expungetagjob.h" |
76 | + |
77 | +ExpungeTagJob::ExpungeTagJob(const QString &guid, QObject *parent) : |
78 | + NotesStoreJob(parent), |
79 | + m_guid(guid) |
80 | +{ |
81 | +} |
82 | + |
83 | +bool ExpungeTagJob::operator==(const EvernoteJob *other) const |
84 | +{ |
85 | + const ExpungeTagJob *otherJob = qobject_cast<const ExpungeTagJob*>(other); |
86 | + if (!otherJob) { |
87 | + return false; |
88 | + } |
89 | + return this->m_guid == otherJob->m_guid; |
90 | +} |
91 | + |
92 | +void ExpungeTagJob::attachToDuplicate(const EvernoteJob *other) |
93 | +{ |
94 | + const ExpungeTagJob *otherJob = static_cast<const ExpungeTagJob*>(other); |
95 | + connect(otherJob, &ExpungeTagJob::jobDone, this, &ExpungeTagJob::jobDone); |
96 | +} |
97 | + |
98 | +void ExpungeTagJob::startJob() |
99 | +{ |
100 | + client()->expungeTag(token().toStdString(), m_guid.toStdString()); |
101 | +} |
102 | + |
103 | +void ExpungeTagJob::emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage) |
104 | +{ |
105 | + emit jobDone(errorCode, errorMessage, m_guid); |
106 | +} |
107 | |
108 | === added file 'src/libqtevernote/jobs/expungetagjob.h' |
109 | --- src/libqtevernote/jobs/expungetagjob.h 1970-01-01 00:00:00 +0000 |
110 | +++ src/libqtevernote/jobs/expungetagjob.h 2015-06-11 21:38:48 +0000 |
111 | @@ -0,0 +1,46 @@ |
112 | +/* |
113 | + * Copyright: 2015 Canonical, Ltd |
114 | + * |
115 | + * This file is part of reminders |
116 | + * |
117 | + * reminders is free software: you can redistribute it and/or modify |
118 | + * it under the terms of the GNU General Public License as published by |
119 | + * the Free Software Foundation; version 3. |
120 | + * |
121 | + * reminders is distributed in the hope that it will be useful, |
122 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
123 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
124 | + * GNU General Public License for more details. |
125 | + * |
126 | + * You should have received a copy of the GNU General Public License |
127 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
128 | + * |
129 | + * Authors: Michael Zanetti <michael.zanetti@canonical.com> |
130 | + */ |
131 | + |
132 | +#ifndef EXPUNGETAGJOB_H |
133 | +#define EXPUNGETAGJOB_H |
134 | + |
135 | +#include "notesstorejob.h" |
136 | + |
137 | +class ExpungeTagJob : public NotesStoreJob |
138 | +{ |
139 | + Q_OBJECT |
140 | +public: |
141 | + explicit ExpungeTagJob(const QString &guid, QObject *parent = 0); |
142 | + |
143 | + virtual bool operator==(const EvernoteJob *other) const override; |
144 | + virtual void attachToDuplicate(const EvernoteJob *other) override; |
145 | + |
146 | +signals: |
147 | + void jobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const QString &guid); |
148 | + |
149 | +private slots: |
150 | + void startJob(); |
151 | + void emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage); |
152 | + |
153 | +private: |
154 | + QString m_guid; |
155 | +}; |
156 | + |
157 | +#endif // EXPUNGETAGJOB_H |
158 | |
159 | === modified file 'src/libqtevernote/notebook.cpp' |
160 | --- src/libqtevernote/notebook.cpp 2015-03-06 00:47:45 +0000 |
161 | +++ src/libqtevernote/notebook.cpp 2015-06-11 21:38:48 +0000 |
162 | @@ -33,6 +33,7 @@ |
163 | m_guid(guid), |
164 | m_published(false), |
165 | m_isDefaultNotebook(false), |
166 | + m_deleted(false), |
167 | m_loading(false), |
168 | m_syncError(false) |
169 | { |
170 | @@ -44,6 +45,7 @@ |
171 | m_lastSyncedSequenceNumber = infoFile.value("lastSyncedSequenceNumber", 0).toUInt(); |
172 | m_isDefaultNotebook = infoFile.value("isDefaultNotebook", false).toBool(); |
173 | m_synced = m_lastSyncedSequenceNumber == m_updateSequenceNumber; |
174 | + m_deleted = infoFile.value("deleted", false).toBool(); |
175 | |
176 | foreach (Note *note, NotesStore::instance()->notes()) { |
177 | if (note->notebookGuid() == m_guid) { |
178 | @@ -155,6 +157,7 @@ |
179 | notebook->setName(m_name); |
180 | notebook->setLastUpdated(m_lastUpdated); |
181 | notebook->setPublished(m_published); |
182 | + notebook->setDeleted(m_deleted); |
183 | |
184 | return notebook; |
185 | } |
186 | @@ -232,6 +235,7 @@ |
187 | infoFile.value("lastUpdated", m_lastUpdated); |
188 | infoFile.setValue("lastSyncedSequenceNumber", m_lastSyncedSequenceNumber); |
189 | infoFile.setValue("isDefaultNotebook", m_isDefaultNotebook); |
190 | + infoFile.setValue("deleted", m_deleted); |
191 | } |
192 | |
193 | void Notebook::deleteInfoFile() |
194 | @@ -257,6 +261,11 @@ |
195 | return m_syncError; |
196 | } |
197 | |
198 | +bool Notebook::deleted() const |
199 | +{ |
200 | + return m_deleted; |
201 | +} |
202 | + |
203 | qint32 Notebook::updateSequenceNumber() const |
204 | { |
205 | return m_updateSequenceNumber; |
206 | @@ -287,6 +296,14 @@ |
207 | } |
208 | } |
209 | |
210 | +void Notebook::setDeleted(bool deleted) |
211 | +{ |
212 | + if (m_deleted != deleted) { |
213 | + m_deleted = deleted; |
214 | + emit deletedChanged(); |
215 | + } |
216 | +} |
217 | + |
218 | void Notebook::setLoading(bool loading) |
219 | { |
220 | if (m_loading != loading) { |
221 | |
222 | === modified file 'src/libqtevernote/notebook.h' |
223 | --- src/libqtevernote/notebook.h 2015-03-04 20:30:55 +0000 |
224 | +++ src/libqtevernote/notebook.h 2015-06-11 21:38:48 +0000 |
225 | @@ -37,6 +37,7 @@ |
226 | Q_PROPERTY(QDateTime lastUpdated READ lastUpdated NOTIFY lastUpdatedChanged) |
227 | Q_PROPERTY(QString lastUpdatedString READ lastUpdatedString NOTIFY lastUpdatedChanged) |
228 | Q_PROPERTY(bool isDefaultNotebook READ isDefaultNotebook WRITE setIsDefaultNotebook NOTIFY isDefaultNotebookChanged) |
229 | + Q_PROPERTY(bool deleted READ deleted NOTIFY deletedChanged) |
230 | // Don't forget to update clone() if you add new properties |
231 | |
232 | Q_PROPERTY(bool loading READ loading NOTIFY loadingChanged) |
233 | @@ -71,6 +72,7 @@ |
234 | bool loading() const; |
235 | bool synced() const; |
236 | bool syncError() const; |
237 | + bool deleted() const; |
238 | |
239 | Notebook *clone(); |
240 | |
241 | @@ -87,6 +89,7 @@ |
242 | void syncedChanged(); |
243 | void syncErrorChanged(); |
244 | void isDefaultNotebookChanged(); |
245 | + void deletedChanged(); |
246 | |
247 | private slots: |
248 | void noteAdded(const QString ¬eGuid, const QString ¬ebookGuid); |
249 | @@ -101,6 +104,7 @@ |
250 | void setSyncError(bool syncError); |
251 | void setUpdateSequenceNumber(qint32 updateSequenceNumber); |
252 | void setLastSyncedSequenceNumber(qint32 lastSyncedSequenceNumber); |
253 | + void setDeleted(bool deleted); |
254 | |
255 | void syncToInfoFile(); |
256 | void deleteInfoFile(); |
257 | @@ -114,6 +118,7 @@ |
258 | QDateTime m_lastUpdated; |
259 | bool m_isDefaultNotebook; |
260 | QList<QString> m_notesList; |
261 | + bool m_deleted; |
262 | |
263 | QString m_infoFile; |
264 | |
265 | |
266 | === modified file 'src/libqtevernote/notebooks.cpp' |
267 | --- src/libqtevernote/notebooks.cpp 2015-03-06 00:47:45 +0000 |
268 | +++ src/libqtevernote/notebooks.cpp 2015-06-11 21:38:48 +0000 |
269 | @@ -70,6 +70,8 @@ |
270 | return notebook->syncError(); |
271 | case RoleIsDefaultNotebook: |
272 | return notebook->isDefaultNotebook(); |
273 | + case RoleDeleted: |
274 | + return notebook->deleted(); |
275 | } |
276 | return QVariant(); |
277 | } |
278 | @@ -94,6 +96,7 @@ |
279 | roles.insert(RoleSynced, "synced"); |
280 | roles.insert(RoleSyncError, "syncError"); |
281 | roles.insert(RoleIsDefaultNotebook, "isDefaultNotebook"); |
282 | + roles.insert(RoleDeleted, "deleted"); |
283 | return roles; |
284 | } |
285 | |
286 | @@ -121,6 +124,7 @@ |
287 | connect(notebook, &Notebook::loadingChanged, this, &Notebooks::notebookLoadingChanged); |
288 | connect(notebook, &Notebook::syncErrorChanged, this, &Notebooks::syncErrorChanged); |
289 | connect(notebook, &Notebook::isDefaultNotebookChanged, this, &Notebooks::isDefaultNotebookChanged); |
290 | + connect(notebook, &Notebook::deletedChanged, this, &Notebooks::deletedChanged); |
291 | |
292 | beginInsertRows(QModelIndex(), m_list.count(), m_list.count()); |
293 | m_list.append(guid); |
294 | @@ -150,6 +154,13 @@ |
295 | emit dataChanged(idx, idx, QVector<int>() << RoleIsDefaultNotebook); |
296 | } |
297 | |
298 | +void Notebooks::deletedChanged() |
299 | +{ |
300 | + Notebook *notebook = static_cast<Notebook*>(sender()); |
301 | + QModelIndex idx = index(m_list.indexOf(notebook->guid())); |
302 | + emit dataChanged(idx, idx, QVector<int>() << RoleDeleted); |
303 | +} |
304 | + |
305 | void Notebooks::nameChanged() |
306 | { |
307 | Notebook *notebook = static_cast<Notebook*>(sender()); |
308 | |
309 | === modified file 'src/libqtevernote/notebooks.h' |
310 | --- src/libqtevernote/notebooks.h 2015-03-04 00:23:45 +0000 |
311 | +++ src/libqtevernote/notebooks.h 2015-06-11 21:38:48 +0000 |
312 | @@ -42,7 +42,8 @@ |
313 | RoleLoading, |
314 | RoleSynced, |
315 | RoleSyncError, |
316 | - RoleIsDefaultNotebook |
317 | + RoleIsDefaultNotebook, |
318 | + RoleDeleted |
319 | }; |
320 | explicit Notebooks(QObject *parent = 0); |
321 | |
322 | @@ -76,6 +77,7 @@ |
323 | void notebookLoadingChanged(); |
324 | void syncErrorChanged(); |
325 | void isDefaultNotebookChanged(); |
326 | + void deletedChanged(); |
327 | |
328 | private: |
329 | QList<QString> m_list; |
330 | |
331 | === modified file 'src/libqtevernote/notesstore.cpp' |
332 | --- src/libqtevernote/notesstore.cpp 2015-03-30 19:01:49 +0000 |
333 | +++ src/libqtevernote/notesstore.cpp 2015-06-11 21:38:48 +0000 |
334 | @@ -41,6 +41,7 @@ |
335 | #include "jobs/fetchtagsjob.h" |
336 | #include "jobs/createtagjob.h" |
337 | #include "jobs/savetagjob.h" |
338 | +#include "jobs/expungetagjob.h" |
339 | |
340 | #include "libintl.h" |
341 | |
342 | @@ -404,12 +405,17 @@ |
343 | |
344 | void NotesStore::expungeNotebook(const QString &guid) |
345 | { |
346 | +#ifdef NO_EXPUNGE_NOTEBOOKS |
347 | + // This snipped can be used if the app is compiled with a restricted api key |
348 | + // that can't expunge notebooks on Evernote. Compile with |
349 | + // cmake -DNO_EXPUNGE_NOTEBOOKS=1 |
350 | if (m_username != "@local") { |
351 | qCWarning(dcNotesStore) << "Account managed by Evernote. Cannot delete notebooks."; |
352 | m_errorQueue.append(QString(gettext("This account is managed by Evernote. Use the Evernote website to delete notebooks."))); |
353 | emit errorChanged(); |
354 | return; |
355 | } |
356 | +#endif |
357 | |
358 | Notebook* notebook = m_notebooksHash.value(guid); |
359 | if (!notebook) { |
360 | @@ -453,17 +459,32 @@ |
361 | } |
362 | } |
363 | |
364 | - m_notebooks.removeAll(notebook); |
365 | - m_notebooksHash.remove(notebook->guid()); |
366 | - emit notebookRemoved(notebook->guid()); |
367 | - |
368 | - QSettings settings(m_cacheFile, QSettings::IniFormat); |
369 | - settings.beginGroup("notebooks"); |
370 | - settings.remove(notebook->guid()); |
371 | - settings.endGroup(); |
372 | - |
373 | - notebook->deleteInfoFile(); |
374 | - notebook->deleteLater(); |
375 | + if (notebook->lastSyncedSequenceNumber() == 0) { |
376 | + emit notebookRemoved(notebook->guid()); |
377 | + m_notebooks.removeAll(notebook); |
378 | + m_notebooksHash.remove(notebook->guid()); |
379 | + emit notebookRemoved(notebook->guid()); |
380 | + |
381 | + QSettings settings(m_cacheFile, QSettings::IniFormat); |
382 | + settings.beginGroup("notebooks"); |
383 | + settings.remove(notebook->guid()); |
384 | + settings.endGroup(); |
385 | + |
386 | + notebook->deleteInfoFile(); |
387 | + notebook->deleteLater(); |
388 | + } else { |
389 | + qCDebug(dcNotesStore) << "Setting notebook to deleted:" << notebook->guid(); |
390 | + notebook->setDeleted(true); |
391 | + notebook->setUpdateSequenceNumber(notebook->updateSequenceNumber()+1); |
392 | + emit notebookChanged(notebook->guid()); |
393 | + syncToCacheFile(notebook); |
394 | + |
395 | + if (EvernoteConnection::instance()->isConnected()) { |
396 | + ExpungeNotebookJob *job = new ExpungeNotebookJob(guid, this); |
397 | + connect(job, &ExpungeNotebookJob::jobDone, this, &NotesStore::expungeNotebookJobDone); |
398 | + EvernoteConnection::instance()->enqueue(job); |
399 | + } |
400 | + } |
401 | } |
402 | |
403 | QList<Tag *> NotesStore::tags() const |
404 | @@ -560,6 +581,33 @@ |
405 | syncToCacheFile(tag); |
406 | } |
407 | |
408 | +void NotesStore::expungeTagJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const QString &guid) |
409 | +{ |
410 | + handleUserError(errorCode); |
411 | + if (errorCode != EvernoteConnection::ErrorCodeNoError) { |
412 | + qCWarning(dcSync) << "Error expunging tag:" << errorMessage; |
413 | + return; |
414 | + } |
415 | + |
416 | + if (!m_tagsHash.contains(guid)) { |
417 | + qCWarning(dcSync) << "Received a response for a expungeTag call, but can't find tag around any more."; |
418 | + return; |
419 | + } |
420 | + |
421 | + emit tagRemoved(guid); |
422 | + Tag *tag = m_tagsHash.take(guid); |
423 | + m_tags.removeAll(tag); |
424 | + |
425 | + QSettings cacheFile(m_cacheFile, QSettings::IniFormat); |
426 | + cacheFile.beginGroup("tags"); |
427 | + cacheFile.remove(guid); |
428 | + cacheFile.endGroup(); |
429 | + tag->syncToInfoFile(); |
430 | + |
431 | + tag->deleteInfoFile(); |
432 | + tag->deleteLater(); |
433 | +} |
434 | + |
435 | void NotesStore::tagNote(const QString ¬eGuid, const QString &tagGuid) |
436 | { |
437 | Note *note = m_notesHash.value(noteGuid); |
438 | @@ -1030,14 +1078,19 @@ |
439 | syncToCacheFile(notebook); |
440 | } |
441 | } else { |
442 | - // Local notebook changed. See if we can push our changes |
443 | if (result.updateSequenceNum == notebook->lastSyncedSequenceNumber()) { |
444 | - qCDebug(dcNotesStore) << "Local Notebook changed. Uploading changes to Evernote:" << notebook->guid(); |
445 | - SaveNotebookJob *job = new SaveNotebookJob(notebook); |
446 | - connect(job, &SaveNotebookJob::jobDone, this, &NotesStore::saveNotebookJobDone); |
447 | - EvernoteConnection::instance()->enqueue(job); |
448 | - notebook->setLoading(true); |
449 | - emit notebookChanged(notebook->guid()); |
450 | + // Local notebook changed. See if we can push our changes |
451 | + if (notebook->deleted()) { |
452 | + qCDebug(dcNotesStore) << "Local notebook has been deleted. Deleting from server"; |
453 | + expungeNotebook(notebook->guid()); |
454 | + } else { |
455 | + qCDebug(dcNotesStore) << "Local Notebook changed. Uploading changes to Evernote:" << notebook->guid(); |
456 | + SaveNotebookJob *job = new SaveNotebookJob(notebook); |
457 | + connect(job, &SaveNotebookJob::jobDone, this, &NotesStore::saveNotebookJobDone); |
458 | + EvernoteConnection::instance()->enqueue(job); |
459 | + notebook->setLoading(true); |
460 | + emit notebookChanged(notebook->guid()); |
461 | + } |
462 | } else { |
463 | qCWarning(dcNotesStore) << "Sync conflict in notebook:" << notebook->name(); |
464 | qCWarning(dcNotesStore) << "Resolving of sync conflicts is not implemented yet."; |
465 | @@ -1134,11 +1187,16 @@ |
466 | } else { |
467 | // local tag changed. See if we can sync it to the server |
468 | if (result.updateSequenceNum == tag->lastSyncedSequenceNumber()) { |
469 | - SaveTagJob *job = new SaveTagJob(tag); |
470 | - connect(job, &SaveTagJob::jobDone, this, &NotesStore::saveTagJobDone); |
471 | - EvernoteConnection::instance()->enqueue(job); |
472 | - tag->setLoading(true); |
473 | - emit tagChanged(tag->guid()); |
474 | + if (tag->deleted()) { |
475 | + qCDebug(dcNotesStore) << "Tag has been deleted locally"; |
476 | + expungeTag(tag->guid()); |
477 | + } else { |
478 | + SaveTagJob *job = new SaveTagJob(tag); |
479 | + connect(job, &SaveTagJob::jobDone, this, &NotesStore::saveTagJobDone); |
480 | + EvernoteConnection::instance()->enqueue(job); |
481 | + tag->setLoading(true); |
482 | + emit tagChanged(tag->guid()); |
483 | + } |
484 | } else { |
485 | qCWarning(dcSync) << "CONFLICT in tag" << tag->name(); |
486 | tag->setSyncError(true); |
487 | @@ -1473,9 +1531,22 @@ |
488 | qCWarning(dcSync) << "Error expunging notebook:" << errorMessage; |
489 | return; |
490 | } |
491 | + |
492 | + if (!m_notebooksHash.contains(guid)) { |
493 | + qCWarning(dcSync) << "Received a response for a expungeNotebook call, but can't find notebook around any more."; |
494 | + return; |
495 | + } |
496 | + |
497 | emit notebookRemoved(guid); |
498 | Notebook *notebook = m_notebooksHash.take(guid); |
499 | m_notebooks.removeAll(notebook); |
500 | + |
501 | + QSettings settings(m_cacheFile, QSettings::IniFormat); |
502 | + settings.beginGroup("notebooks"); |
503 | + settings.remove(notebook->guid()); |
504 | + settings.endGroup(); |
505 | + |
506 | + notebook->deleteInfoFile(); |
507 | notebook->deleteLater(); |
508 | } |
509 | |
510 | @@ -1712,12 +1783,18 @@ |
511 | |
512 | void NotesStore::expungeTag(const QString &guid) |
513 | { |
514 | +#ifdef NO_EXPUNGE_TAGS |
515 | + // This snipped can be used if the app is compiled with a restricted api key |
516 | + // that can't expunge tags on Evernote. Compile with |
517 | + // cmake -DNO_EXPUNGE_TAGS=1 |
518 | + |
519 | if (m_username != "@local") { |
520 | qCWarning(dcNotesStore) << "This account is managed by Evernote. Cannot delete tags."; |
521 | m_errorQueue.append(gettext("This account is managed by Evernote. Please use the Evernote website to delete tags.")); |
522 | emit errorChanged(); |
523 | return; |
524 | } |
525 | +#endif |
526 | |
527 | Tag *tag = m_tagsHash.value(guid); |
528 | if (!tag) { |
529 | @@ -1730,23 +1807,38 @@ |
530 | Note *note = m_notesHash.value(noteGuid); |
531 | if (!note) { |
532 | qCWarning(dcNotesStore) << "Tag holds note" << noteGuid << "which hasn't been found in Notes Store"; |
533 | + Q_ASSERT(false); |
534 | continue; |
535 | } |
536 | untagNote(noteGuid, guid); |
537 | } |
538 | |
539 | - emit tagRemoved(guid); |
540 | - m_tagsHash.remove(guid); |
541 | - m_tags.removeAll(tag); |
542 | - |
543 | - QSettings cacheFile(m_cacheFile, QSettings::IniFormat); |
544 | - cacheFile.beginGroup("tags"); |
545 | - cacheFile.remove(guid); |
546 | - cacheFile.endGroup(); |
547 | - tag->syncToInfoFile(); |
548 | - |
549 | - tag->deleteInfoFile(); |
550 | - tag->deleteLater(); |
551 | + if (tag->lastSyncedSequenceNumber() == 0) { |
552 | + emit tagRemoved(guid); |
553 | + m_tagsHash.remove(guid); |
554 | + m_tags.removeAll(tag); |
555 | + |
556 | + QSettings cacheFile(m_cacheFile, QSettings::IniFormat); |
557 | + cacheFile.beginGroup("tags"); |
558 | + cacheFile.remove(guid); |
559 | + cacheFile.endGroup(); |
560 | + tag->syncToInfoFile(); |
561 | + |
562 | + tag->deleteInfoFile(); |
563 | + tag->deleteLater(); |
564 | + } else { |
565 | + qCDebug(dcNotesStore) << "Setting tag to deleted:" << tag->guid(); |
566 | + tag->setDeleted(true); |
567 | + tag->setUpdateSequenceNumber(tag->updateSequenceNumber()+1); |
568 | + emit tagChanged(tag->guid()); |
569 | + syncToCacheFile(tag); |
570 | + |
571 | + if (EvernoteConnection::instance()->isConnected()) { |
572 | + ExpungeTagJob *job = new ExpungeTagJob(guid, this); |
573 | + connect(job, &ExpungeTagJob::jobDone, this, &NotesStore::expungeTagJobDone); |
574 | + EvernoteConnection::instance()->enqueue(job); |
575 | + } |
576 | + } |
577 | } |
578 | |
579 | void NotesStore::resolveConflict(const QString ¬eGuid, NotesStore::ConflictResolveMode mode) |
580 | |
581 | === modified file 'src/libqtevernote/notesstore.h' |
582 | --- src/libqtevernote/notesstore.h 2015-03-15 20:00:21 +0000 |
583 | +++ src/libqtevernote/notesstore.h 2015-06-11 21:38:48 +0000 |
584 | @@ -197,6 +197,7 @@ |
585 | void fetchTagsJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const std::vector<evernote::edam::Tag> &results); |
586 | void createTagJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const QString &tmpGuid, const evernote::edam::Tag &result); |
587 | void saveTagJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const evernote::edam::Tag &result); |
588 | + void expungeTagJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const QString &guid); |
589 | |
590 | void syncToCacheFile(Note *note); |
591 | void deleteFromCacheFile(Note* note); |
592 | |
593 | === modified file 'src/libqtevernote/tag.cpp' |
594 | --- src/libqtevernote/tag.cpp 2015-03-04 20:30:55 +0000 |
595 | +++ src/libqtevernote/tag.cpp 2015-06-11 21:38:48 +0000 |
596 | @@ -29,12 +29,14 @@ |
597 | QObject(parent), |
598 | m_updateSequenceNumber(updateSequenceNumber), |
599 | m_guid(guid), |
600 | + m_deleted(false), |
601 | m_loading(false), |
602 | m_syncError(false) |
603 | { |
604 | setGuid(guid); |
605 | QSettings infoFile(m_infoFile, QSettings::IniFormat); |
606 | m_name = infoFile.value("name").toString(); |
607 | + m_deleted = infoFile.value("deleted").toBool(); |
608 | m_lastSyncedSequenceNumber = infoFile.value("lastSyncedSequenceNumber", 0).toUInt(); |
609 | m_synced = m_lastSyncedSequenceNumber == m_updateSequenceNumber; |
610 | |
611 | @@ -129,6 +131,7 @@ |
612 | { |
613 | Tag *tag = new Tag(m_guid, m_updateSequenceNumber); |
614 | tag->setName(m_name); |
615 | + tag->setDeleted(m_deleted); |
616 | return tag; |
617 | } |
618 | |
619 | @@ -178,6 +181,7 @@ |
620 | { |
621 | QSettings infoFile(m_infoFile, QSettings::IniFormat); |
622 | infoFile.setValue("name", m_name); |
623 | + infoFile.setValue("deleted", m_deleted); |
624 | infoFile.setValue("lastSyncedSequenceNumber", m_lastSyncedSequenceNumber); |
625 | } |
626 | |
627 | @@ -212,6 +216,11 @@ |
628 | return m_syncError; |
629 | } |
630 | |
631 | +bool Tag::deleted() const |
632 | +{ |
633 | + return m_deleted; |
634 | +} |
635 | + |
636 | void Tag::setSyncError(bool syncError) |
637 | { |
638 | if (m_syncError != syncError) { |
639 | @@ -220,6 +229,14 @@ |
640 | } |
641 | } |
642 | |
643 | +void Tag::setDeleted(bool deleted) |
644 | +{ |
645 | + if (m_deleted != deleted) { |
646 | + m_deleted = deleted; |
647 | + emit deletedChanged(); |
648 | + } |
649 | +} |
650 | + |
651 | |
652 | QString Tag::noteAt(int index) const |
653 | { |
654 | |
655 | === modified file 'src/libqtevernote/tag.h' |
656 | --- src/libqtevernote/tag.h 2015-03-06 00:42:42 +0000 |
657 | +++ src/libqtevernote/tag.h 2015-06-11 21:38:48 +0000 |
658 | @@ -38,6 +38,7 @@ |
659 | Q_PROPERTY(QString guid READ guid NOTIFY guidChanged) |
660 | Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) |
661 | Q_PROPERTY(int noteCount READ noteCount NOTIFY noteCountChanged) |
662 | + Q_PROPERTY(bool deleted READ deleted NOTIFY deletedChanged) |
663 | // Don't forget to update clone() if you add new properties |
664 | |
665 | Q_PROPERTY(bool loading READ loading NOTIFY loadingChanged) |
666 | @@ -65,6 +66,7 @@ |
667 | bool loading() const; |
668 | bool synced() const; |
669 | bool syncError() const; |
670 | + bool deleted() const; |
671 | |
672 | Tag *clone(); |
673 | |
674 | @@ -75,6 +77,7 @@ |
675 | void loadingChanged(); |
676 | void syncedChanged(); |
677 | void syncErrorChanged(); |
678 | + void deletedChanged(); |
679 | |
680 | private slots: |
681 | void noteAdded(const QString ¬eGuid, const QString ¬ebookGuid); |
682 | @@ -88,12 +91,14 @@ |
683 | void setLastSyncedSequenceNumber(qint32 lastSyncedSequenceNumber); |
684 | void setLoading(bool loading); |
685 | void setSyncError(bool syncError); |
686 | + void setDeleted(bool deleted); |
687 | |
688 | private: |
689 | qint32 m_updateSequenceNumber; |
690 | qint32 m_lastSyncedSequenceNumber; |
691 | QString m_guid; |
692 | QString m_name; |
693 | + bool m_deleted; |
694 | |
695 | QList<QString> m_notesList; |
696 | |
697 | |
698 | === modified file 'src/libqtevernote/tags.cpp' |
699 | --- src/libqtevernote/tags.cpp 2015-03-06 00:47:45 +0000 |
700 | +++ src/libqtevernote/tags.cpp 2015-06-11 21:38:48 +0000 |
701 | @@ -61,6 +61,8 @@ |
702 | return tag->synced(); |
703 | case RoleSyncError: |
704 | return tag->syncError(); |
705 | + case RoleDeleted: |
706 | + return tag->deleted(); |
707 | } |
708 | return QVariant(); |
709 | } |
710 | @@ -80,6 +82,7 @@ |
711 | roles.insert(RoleLoading, "loading"); |
712 | roles.insert(RoleSynced, "synced"); |
713 | roles.insert(RoleSyncError, "syncError"); |
714 | + roles.insert(RoleDeleted, "deleted"); |
715 | return roles; |
716 | } |
717 | |
718 | @@ -104,6 +107,7 @@ |
719 | connect(tag, &Tag::loadingChanged, this, &Tags::tagLoadingChanged); |
720 | connect(tag, &Tag::syncedChanged, this, &Tags::syncedChanged); |
721 | connect(tag, &Tag::syncErrorChanged, this, &Tags::syncErrorChanged); |
722 | + connect(tag, &Tag::deletedChanged, this, &Tags::deletedChanged); |
723 | |
724 | beginInsertRows(QModelIndex(), m_list.count(), m_list.count()); |
725 | m_list.append(guid); |
726 | @@ -128,6 +132,13 @@ |
727 | } |
728 | } |
729 | |
730 | +void Tags::deletedChanged() |
731 | +{ |
732 | + Tag *tag = static_cast<Tag*>(sender()); |
733 | + int idx = m_list.indexOf(tag->guid()); |
734 | + emit dataChanged(index(idx), index(idx), QVector<int>() << RoleDeleted); |
735 | +} |
736 | + |
737 | void Tags::nameChanged() |
738 | { |
739 | Tag *tag = static_cast<Tag*>(sender()); |
740 | |
741 | === modified file 'src/libqtevernote/tags.h' |
742 | --- src/libqtevernote/tags.h 2015-03-04 00:23:45 +0000 |
743 | +++ src/libqtevernote/tags.h 2015-06-11 21:38:48 +0000 |
744 | @@ -38,7 +38,8 @@ |
745 | RoleNoteCount, |
746 | RoleLoading, |
747 | RoleSynced, |
748 | - RoleSyncError |
749 | + RoleSyncError, |
750 | + RoleDeleted |
751 | }; |
752 | explicit Tags(QObject *parent = 0); |
753 | |
754 | @@ -62,6 +63,7 @@ |
755 | void tagAdded(const QString &guid); |
756 | void tagRemoved(const QString &guid); |
757 | void tagGuidChanged(const QString &oldGuid, const QString &newGuid); |
758 | + void deletedChanged(); |
759 | |
760 | void nameChanged(); |
761 | void noteCountChanged(); |
PASSED: Continuous integration, rev:451 91.189. 93.70:8080/ job/reminders- app-ci/ 753/ 91.189. 93.70:8080/ job/generic- mediumtests- utopic/ 2908 91.189. 93.70:8080/ job/generic- mediumtests- utopic/ 2908/artifact/ work/output/ *zip*/output. zip 91.189. 93.70:8080/ job/reminders- app-utopic- amd64-ci/ 355 91.189. 93.70:8080/ job/reminders- app-vivid- amd64-ci/ 175
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: 91.189. 93.70:8080/ job/reminders- app-ci/ 753/rebuild
http://