Merge lp:~mzanetti/reminders-app/delete-tags-and-notebooks into lp:reminders-app

Proposed by Michael Zanetti
Status: Merged
Approved by: Riccardo Padovani
Approved revision: 369
Merged at revision: 369
Proposed branch: lp:~mzanetti/reminders-app/delete-tags-and-notebooks
Merge into: lp:reminders-app
Diff against target: 1122 lines (+400/-146)
17 files modified
src/app/qml/components/NotebooksDelegate.qml (+46/-37)
src/app/qml/components/StatusBar.qml (+4/-2)
src/app/qml/components/TagsDelegate.qml (+21/-27)
src/app/qml/reminders.qml (+13/-1)
src/app/qml/ui/NotebooksPage.qml (+50/-1)
src/app/qml/ui/TagsPage.qml (+45/-10)
src/libqtevernote/jobs/savenotebookjob.cpp (+2/-0)
src/libqtevernote/notebook.cpp (+21/-0)
src/libqtevernote/notebook.h (+7/-0)
src/libqtevernote/notebooks.cpp (+11/-6)
src/libqtevernote/notebooks.h (+3/-3)
src/libqtevernote/notesstore.cpp (+164/-42)
src/libqtevernote/notesstore.h (+6/-8)
src/libqtevernote/tag.cpp (+6/-0)
src/libqtevernote/tag.h (+1/-0)
src/libqtevernote/tags.cpp (+0/-6)
src/libqtevernote/tags.h (+0/-3)
To merge this branch: bzr merge lp:~mzanetti/reminders-app/delete-tags-and-notebooks
Reviewer Review Type Date Requested Status
Riccardo Padovani Approve
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Review via email: mp+251677@code.launchpad.net

Commit message

implement support for deleting notebooks and tags

both features can only be used with offline mode because the evernote api
doesn't allow 3rd Party applications to execute those methods. However,
this required using ListItemWithAction for notebooks and tags and with
that some polishing of those delegates. Also makes better use of the
error label.

To post a comment you must log in.
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Riccardo Padovani (rpadovani) wrote :

Tested both locally and with online account, works like charm!

Code looks good to me.

Good job!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/app/qml/components/NotebooksDelegate.qml'
2--- src/app/qml/components/NotebooksDelegate.qml 2014-12-16 23:01:22 +0000
3+++ src/app/qml/components/NotebooksDelegate.qml 2015-03-04 00:26:40 +0000
4@@ -22,12 +22,38 @@
5 import Ubuntu.Components.ListItems 1.0
6 import Evernote 0.1
7
8-Empty {
9+ListItemWithActions {
10 id: root
11- height: units.gu(10)
12
13 property string notebookColor: preferences.colorForNotebook(model.guid)
14
15+ signal deleteNotebook();
16+ signal setAsDefault();
17+ signal renameNotebook();
18+
19+ leftSideAction: Action {
20+ iconName: "delete"
21+ text: i18n.tr("Delete")
22+ onTriggered: {
23+ root.deleteNotebook();
24+ }
25+ }
26+
27+ rightSideActions: [
28+ Action {
29+ iconName: model.isDefaultNotebook ? "starred" : "non-starred"
30+ onTriggered: {
31+ root.setAsDefault();
32+ }
33+ },
34+ Action {
35+ iconName: "edit"
36+ onTriggered: {
37+ root.renameNotebook();
38+ }
39+ }
40+ ]
41+
42 Rectangle {
43 anchors.fill: parent
44 color: "#f9f9f9"
45@@ -61,34 +87,6 @@
46 color: root.notebookColor
47 fontSize: "large"
48 Layout.fillWidth: true
49-
50- MouseArea {
51- onPressAndHold: {
52- notebookTitleLabel.visible = false;
53- notebookTitleTextField.forceActiveFocus();
54- }
55- anchors.fill: parent
56- propagateComposedEvents: true
57- }
58- }
59-
60- TextField {
61- id: notebookTitleTextField
62- text: model.name
63- color: root.notebookColor
64- visible: !notebookTitleLabel.visible
65- Layout.fillWidth: true
66-
67- InverseMouseArea {
68- onClicked: {
69- if (notebookTitleTextField.text) {
70- notebooks.notebook(index).name = notebookTitleTextField.text;
71- NotesStore.saveNotebook(notebooks.notebook(index).guid);
72- notebookTitleLabel.visible = true;
73- }
74- }
75- anchors.fill: parent
76- }
77 }
78
79 Label {
80@@ -99,14 +97,25 @@
81 Layout.fillWidth: true
82 }
83
84- Label {
85- objectName: 'notebookPublishedLabel'
86+ Row {
87 Layout.fillHeight: true
88- text: model.published ? i18n.tr("Shared") : i18n.tr("Private")
89- color: model.published ? "black" : "#b3b3b3"
90- fontSize: "x-small"
91- verticalAlignment: Text.AlignVCenter
92- font.bold: model.published
93+ spacing: units.gu(1)
94+ Icon {
95+ height: parent.height
96+ width: height
97+ name: "starred"
98+ visible: model.isDefaultNotebook
99+ }
100+
101+ Label {
102+ objectName: 'notebookPublishedLabel'
103+ anchors.verticalCenter: parent.verticalCenter
104+ text: model.published ? i18n.tr("Shared") : i18n.tr("Private")
105+ color: model.published ? "black" : "#b3b3b3"
106+ fontSize: "x-small"
107+ verticalAlignment: Text.AlignVCenter
108+ font.bold: model.published
109+ }
110 }
111 }
112
113
114=== modified file 'src/app/qml/components/StatusBar.qml'
115--- src/app/qml/components/StatusBar.qml 2014-12-08 10:25:48 +0000
116+++ src/app/qml/components/StatusBar.qml 2015-03-04 00:26:40 +0000
117@@ -21,20 +21,22 @@
118 anchors { left: parent.left; top: parent.top; right: parent.right }
119 spacing: units.gu(1)
120
121- RowLayout {
122+ Row {
123 anchors { left: parent.left; right: parent.right; margins: units.gu(1) }
124 spacing: units.gu(1)
125+ height: label.height
126
127 Icon {
128 id: icon
129 height: units.gu(3)
130 width: height
131 color: UbuntuColors.red
132+ anchors.verticalCenter: parent.verticalCenter
133 }
134
135 Label {
136 id: label
137- Layout.fillWidth: true
138+ width: parent.width - x
139 wrapMode: Text.WordWrap
140 }
141 }
142
143=== modified file 'src/app/qml/components/TagsDelegate.qml'
144--- src/app/qml/components/TagsDelegate.qml 2014-12-14 21:52:26 +0000
145+++ src/app/qml/components/TagsDelegate.qml 2015-03-04 00:26:40 +0000
146@@ -22,10 +22,30 @@
147 import Ubuntu.Components.ListItems 1.0
148 import Evernote 0.1
149
150-Empty {
151+ListItemWithActions {
152 id: root
153 height: units.gu(10)
154
155+ signal deleteTag();
156+ signal renameTag();
157+
158+ leftSideAction: Action {
159+ iconName: "delete"
160+ text: i18n.tr("Delete")
161+ onTriggered: {
162+ root.deleteTag()
163+ }
164+ }
165+
166+ rightSideActions: [
167+ Action {
168+ iconName: "edit"
169+ onTriggered: {
170+ root.renameTag();
171+ }
172+ }
173+ ]
174+
175 Rectangle {
176 anchors.fill: parent
177 color: "#f9f9f9"
178@@ -58,32 +78,6 @@
179 text: model.name
180 fontSize: "large"
181 Layout.fillWidth: true
182-
183- MouseArea {
184- onPressAndHold: {
185- tagTitleLabel.visible = false;
186- tagTitleTextField.forceActiveFocus();
187- }
188- anchors.fill: parent
189- propagateComposedEvents: true
190- }
191- }
192-
193- TextField {
194- id: tagTitleTextField
195- text: model.name
196- visible: !tagTitleLabel.visible
197-
198- InverseMouseArea {
199- onClicked: {
200- if (tagTitleTextField.text) {
201- tags.tag(index).name = tagTitleTextField.text;
202- NotesStore.saveTag(tags.tag(index).guid);
203- tagTitleLabel.visible = true;
204- }
205- }
206- anchors.fill: parent
207- }
208 }
209 }
210
211
212=== modified file 'src/app/qml/reminders.qml'
213--- src/app/qml/reminders.qml 2015-03-01 22:32:41 +0000
214+++ src/app/qml/reminders.qml 2015-03-04 00:26:40 +0000
215@@ -422,9 +422,21 @@
216 anchors { left: parent.left; right: parent.right; top: parent.top; topMargin: units.gu(9) }
217 color: root.backgroundColor
218 shown: text
219- text: EvernoteConnection.error || NotesStore.error || NotesStore.notebooksError || NotesStore.tagsError
220+ text: EvernoteConnection.error || NotesStore.error
221 iconName: "sync-error"
222
223+ Timer {
224+ interval: 5000
225+ repeat: true
226+ running: NotesStore.error
227+ onTriggered: NotesStore.clearError();
228+ }
229+
230+ MouseArea {
231+ anchors.fill: parent
232+ onClicked: NotesStore.clearError();
233+ }
234+
235 }
236
237 PageStack {
238
239=== modified file 'src/app/qml/ui/NotebooksPage.qml'
240--- src/app/qml/ui/NotebooksPage.qml 2015-03-01 22:32:41 +0000
241+++ src/app/qml/ui/NotebooksPage.qml 2015-03-04 00:26:40 +0000
242@@ -19,6 +19,7 @@
243 import QtQuick 2.3
244 import Ubuntu.Components 1.1
245 import Ubuntu.Components.ListItems 1.0
246+import Ubuntu.Components.Popups 1.0
247 import Evernote 0.1
248 import "../components"
249
250@@ -116,10 +117,30 @@
251 }
252
253 delegate: NotebooksDelegate {
254- onClicked: {
255+ width: parent.width
256+ height: units.gu(10)
257+ triggerActionOnMouseRelease: true
258+
259+ onItemClicked: {
260 print("selected notebook:", model.guid)
261 root.openNotebook(model.guid)
262 }
263+
264+ onDeleteNotebook: {
265+ NotesStore.expungeNotebook(model.guid)
266+ }
267+
268+ onSetAsDefault: {
269+ NotesStore.setDefaultNotebook(model.guid)
270+ }
271+
272+ onRenameNotebook: {
273+ var popup = PopupUtils.open(renameNotebookDialogComponent, root, {name: model.name})
274+ popup.accepted.connect(function(newName) {
275+ notebooks.notebook(index).name = newName;
276+ NotesStore.saveNotebook(model.guid);
277+ })
278+ }
279 }
280
281 BouncingProgressBar {
282@@ -170,4 +191,32 @@
283 height: Qt.inputMethod.keyboardRectangle.height
284 }
285 }
286+
287+ Component {
288+ id: renameNotebookDialogComponent
289+ Dialog {
290+ id: renameNotebookDialog
291+ title: i18n.tr("Rename notebook")
292+ text: i18n.tr("Enter a new name for notebook %1").arg(name)
293+
294+ property string name
295+
296+ signal accepted(string newName)
297+
298+ TextField {
299+ id: nameTextField
300+ text: renameNotebookDialog.name
301+ placeholderText: i18n.tr("Name cannot be empty")
302+ }
303+
304+ Button {
305+ text: i18n.tr("OK")
306+ enabled: nameTextField.text
307+ onClicked: {
308+ renameNotebookDialog.accepted(nameTextField.text)
309+ PopupUtils.close(renameNotebookDialog)
310+ }
311+ }
312+ }
313+ }
314 }
315
316=== modified file 'src/app/qml/ui/TagsPage.qml'
317--- src/app/qml/ui/TagsPage.qml 2015-03-01 22:32:41 +0000
318+++ src/app/qml/ui/TagsPage.qml 2015-03-04 00:26:40 +0000
319@@ -19,6 +19,7 @@
320 import QtQuick 2.3
321 import Ubuntu.Components 1.1
322 import Ubuntu.Components.ListItems 1.0
323+import Ubuntu.Components.Popups 1.0
324 import Evernote 0.1
325 import "../components"
326
327@@ -80,10 +81,25 @@
328 }
329
330 delegate: TagsDelegate {
331- onClicked: {
332+ width: parent.width
333+ height: units.gu(10)
334+ triggerActionOnMouseRelease: true
335+
336+ onItemClicked: {
337 print("selected tag:", model.guid)
338 root.openTaggedNotes(model.guid)
339 }
340+ onDeleteTag: {
341+ NotesStore.expungeTag(model.guid);
342+ }
343+
344+ onRenameTag: {
345+ var popup = PopupUtils.open(renameTagDialogComponent, root, {name: model.name})
346+ popup.accepted.connect(function(newName) {
347+ tags.tag(index).name = newName;
348+ NotesStore.saveTag(model.guid);
349+ })
350+ }
351 }
352
353 ActivityIndicator {
354@@ -92,15 +108,6 @@
355 visible: running
356 }
357
358- Label {
359- anchors.centerIn: parent
360- width: parent.width - units.gu(4)
361- wrapMode: Text.WordWrap
362- horizontalAlignment: Text.AlignHCenter
363- visible: !tags.loading && tags.error
364- text: tags.error
365- }
366-
367 Scrollbar {
368 flickableItem: parent
369 }
370@@ -121,4 +128,32 @@
371 horizontalAlignment: Text.AlignHCenter
372 text: i18n.tr("No tags available. You can tag notes while viewing them.")
373 }
374+
375+ Component {
376+ id: renameTagDialogComponent
377+ Dialog {
378+ id: renameTagDialog
379+ title: i18n.tr("Rename tag")
380+ text: i18n.tr("Enter a new name for tag %1").arg(name)
381+
382+ property string name
383+
384+ signal accepted(string newName)
385+
386+ TextField {
387+ id: nameTextField
388+ text: renameTagDialog.name
389+ placeholderText: i18n.tr("Name cannot be empty")
390+ }
391+
392+ Button {
393+ text: i18n.tr("OK")
394+ enabled: nameTextField.text
395+ onClicked: {
396+ renameTagDialog.accepted(nameTextField.text)
397+ PopupUtils.close(renameTagDialog)
398+ }
399+ }
400+ }
401+ }
402 }
403
404=== modified file 'src/libqtevernote/jobs/savenotebookjob.cpp'
405--- src/libqtevernote/jobs/savenotebookjob.cpp 2014-12-13 03:55:52 +0000
406+++ src/libqtevernote/jobs/savenotebookjob.cpp 2015-03-04 00:26:40 +0000
407@@ -56,6 +56,8 @@
408 m_resultNotebook.__isset.name = true;
409 m_resultNotebook.updateSequenceNum = m_notebook->updateSequenceNumber();
410 m_resultNotebook.__isset.updateSequenceNum = true;
411+ m_resultNotebook.defaultNotebook = m_notebook->isDefaultNotebook();
412+ m_resultNotebook.__isset.defaultNotebook = true;
413
414 client()->updateNotebook(token().toStdString(), m_resultNotebook);
415 }
416
417=== modified file 'src/libqtevernote/notebook.cpp'
418--- src/libqtevernote/notebook.cpp 2015-02-24 22:21:04 +0000
419+++ src/libqtevernote/notebook.cpp 2015-03-04 00:26:40 +0000
420@@ -32,6 +32,7 @@
421 m_updateSequenceNumber(updateSequenceNumber),
422 m_guid(guid),
423 m_published(false),
424+ m_isDefaultNotebook(false),
425 m_loading(false),
426 m_syncError(false)
427 {
428@@ -41,6 +42,7 @@
429 m_published = infoFile.value("published").toBool();
430 m_lastUpdated = infoFile.value("lastUpdated").toDateTime();
431 m_lastSyncedSequenceNumber = infoFile.value("lastSyncedSequenceNumber", 0).toUInt();
432+ m_isDefaultNotebook = infoFile.value("isDefaultNotebook", false).toBool();
433 m_synced = m_lastSyncedSequenceNumber == m_updateSequenceNumber;
434
435 foreach (Note *note, NotesStore::instance()->notes()) {
436@@ -77,6 +79,11 @@
437 return m_notesList.count();
438 }
439
440+QString Notebook::noteAt(int index) const
441+{
442+ return m_notesList.at(index);
443+}
444+
445 bool Notebook::published() const
446 {
447 return m_published;
448@@ -129,6 +136,19 @@
449 return QString(gettext("on %1 %2")).arg(QLocale::system().standaloneMonthName(updateDate.month())).arg(updateDate.year());
450 }
451
452+bool Notebook::isDefaultNotebook() const
453+{
454+ return m_isDefaultNotebook;
455+}
456+
457+void Notebook::setIsDefaultNotebook(bool isDefaultNotebook)
458+{
459+ if (m_isDefaultNotebook != isDefaultNotebook) {
460+ m_isDefaultNotebook = isDefaultNotebook;
461+ emit isDefaultNotebookChanged();
462+ }
463+}
464+
465 Notebook *Notebook::clone()
466 {
467 Notebook *notebook = new Notebook(m_guid, m_updateSequenceNumber);
468@@ -212,6 +232,7 @@
469 infoFile.setValue("published", m_published);
470 infoFile.value("lastUpdated", m_lastUpdated);
471 infoFile.setValue("lastSyncedSequenceNumber", m_lastSyncedSequenceNumber);
472+ infoFile.setValue("isDefaultNotebook", m_isDefaultNotebook);
473 }
474
475 void Notebook::deleteInfoFile()
476
477=== modified file 'src/libqtevernote/notebook.h'
478--- src/libqtevernote/notebook.h 2014-12-13 00:41:41 +0000
479+++ src/libqtevernote/notebook.h 2015-03-04 00:26:40 +0000
480@@ -36,6 +36,7 @@
481 Q_PROPERTY(bool published READ published NOTIFY publishedChanged)
482 Q_PROPERTY(QDateTime lastUpdated READ lastUpdated NOTIFY lastUpdatedChanged)
483 Q_PROPERTY(QString lastUpdatedString READ lastUpdatedString NOTIFY lastUpdatedChanged)
484+ Q_PROPERTY(bool isDefaultNotebook READ isDefaultNotebook WRITE setIsDefaultNotebook NOTIFY isDefaultNotebookChanged)
485 // Don't forget to update clone() if you add new properties
486
487 Q_PROPERTY(bool loading READ loading NOTIFY loadingChanged)
488@@ -51,6 +52,7 @@
489 void setName(const QString &name);
490
491 int noteCount() const;
492+ QString noteAt(int index) const;
493
494 bool published() const;
495 void setPublished(bool published);
496@@ -60,6 +62,9 @@
497
498 QString lastUpdatedString() const;
499
500+ bool isDefaultNotebook() const;
501+ void setIsDefaultNotebook(bool isDefaultNotebook);
502+
503 quint32 updateSequenceNumber() const;
504 quint32 lastSyncedSequenceNumber() const;
505
506@@ -81,6 +86,7 @@
507 void loadingChanged();
508 void syncedChanged();
509 void syncErrorChanged();
510+ void isDefaultNotebookChanged();
511
512 private slots:
513 void noteAdded(const QString &noteGuid, const QString &notebookGuid);
514@@ -106,6 +112,7 @@
515 QString m_name;
516 bool m_published;
517 QDateTime m_lastUpdated;
518+ bool m_isDefaultNotebook;
519 QList<QString> m_notesList;
520
521 QString m_infoFile;
522
523=== modified file 'src/libqtevernote/notebooks.cpp'
524--- src/libqtevernote/notebooks.cpp 2014-12-13 03:55:52 +0000
525+++ src/libqtevernote/notebooks.cpp 2015-03-04 00:26:40 +0000
526@@ -32,7 +32,6 @@
527 }
528
529 connect(NotesStore::instance(), &NotesStore::notebooksLoadingChanged, this, &Notebooks::loadingChanged);
530- connect(NotesStore::instance(), &NotesStore::notebooksErrorChanged, this, &Notebooks::errorChanged);
531 connect(NotesStore::instance(), &NotesStore::notebookAdded, this, &Notebooks::notebookAdded);
532 connect(NotesStore::instance(), &NotesStore::notebookRemoved, this, &Notebooks::notebookRemoved);
533 connect(NotesStore::instance(), &NotesStore::notebookGuidChanged, this, &Notebooks::notebookGuidChanged);
534@@ -43,11 +42,6 @@
535 return NotesStore::instance()->notebooksLoading();
536 }
537
538-QString Notebooks::error() const
539-{
540- return NotesStore::instance()->notebooksError();
541-}
542-
543 int Notebooks::count() const
544 {
545 return rowCount();
546@@ -76,6 +70,8 @@
547 return notebook->synced();
548 case RoleSyncError:
549 return notebook->syncError();
550+ case RoleIsDefaultNotebook:
551+ return notebook->isDefaultNotebook();
552 }
553 return QVariant();
554 }
555@@ -99,6 +95,7 @@
556 roles.insert(RoleLoading, "loading");
557 roles.insert(RoleSynced, "synced");
558 roles.insert(RoleSyncError, "syncError");
559+ roles.insert(RoleIsDefaultNotebook, "isDefaultNotebook");
560 return roles;
561 }
562
563@@ -125,6 +122,7 @@
564 connect(notebook, &Notebook::syncedChanged, this, &Notebooks::syncedChanged);
565 connect(notebook, &Notebook::loadingChanged, this, &Notebooks::notebookLoadingChanged);
566 connect(notebook, &Notebook::syncErrorChanged, this, &Notebooks::syncErrorChanged);
567+ connect(notebook, &Notebook::isDefaultNotebookChanged, this, &Notebooks::isDefaultNotebookChanged);
568
569 beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
570 m_list.append(guid);
571@@ -147,6 +145,13 @@
572 emit dataChanged(index(idx), index(idx));
573 }
574
575+void Notebooks::isDefaultNotebookChanged()
576+{
577+ Notebook *notebook = static_cast<Notebook*>(sender());
578+ QModelIndex idx = index(m_list.indexOf((notebook->guid())));
579+ emit dataChanged(idx, idx, QVector<int>() << RoleIsDefaultNotebook);
580+}
581+
582 void Notebooks::nameChanged()
583 {
584 Notebook *notebook = static_cast<Notebook*>(sender());
585
586=== modified file 'src/libqtevernote/notebooks.h'
587--- src/libqtevernote/notebooks.h 2014-12-13 03:55:52 +0000
588+++ src/libqtevernote/notebooks.h 2015-03-04 00:26:40 +0000
589@@ -29,7 +29,6 @@
590 {
591 Q_OBJECT
592 Q_PROPERTY(bool loading READ loading NOTIFY loadingChanged)
593- Q_PROPERTY(QString error READ error NOTIFY errorChanged)
594 Q_PROPERTY(int count READ count NOTIFY countChanged)
595
596 public:
597@@ -42,7 +41,8 @@
598 RoleLastUpdatedString,
599 RoleLoading,
600 RoleSynced,
601- RoleSyncError
602+ RoleSyncError,
603+ RoleIsDefaultNotebook
604 };
605 explicit Notebooks(QObject *parent = 0);
606
607@@ -61,7 +61,6 @@
608
609 signals:
610 void loadingChanged();
611- void errorChanged();
612 void countChanged();
613
614 private slots:
615@@ -76,6 +75,7 @@
616 void syncedChanged();
617 void notebookLoadingChanged();
618 void syncErrorChanged();
619+ void isDefaultNotebookChanged();
620
621 private:
622 QList<QString> m_list;
623
624=== modified file 'src/libqtevernote/notesstore.cpp'
625--- src/libqtevernote/notesstore.cpp 2015-02-28 03:59:56 +0000
626+++ src/libqtevernote/notesstore.cpp 2015-03-04 00:26:40 +0000
627@@ -143,17 +143,7 @@
628
629 QString NotesStore::error() const
630 {
631- return m_error;
632-}
633-
634-QString NotesStore::notebooksError() const
635-{
636- return m_notebooksError;
637-}
638-
639-QString NotesStore::tagsError() const
640-{
641- return m_tagsError;
642+ return m_errorQueue.count() > 0 ? m_errorQueue.first() : QString();
643 }
644
645 int NotesStore::count() const
646@@ -284,6 +274,9 @@
647 {
648 Notebook *notebook = new Notebook(QUuid::createUuid().toString().remove(QRegExp("[\{\}]*")), 1, this);
649 notebook->setName(name);
650+ if (m_notebooks.isEmpty()) {
651+ notebook->setIsDefaultNotebook(true);
652+ }
653
654 m_notebooks.append(notebook);
655 m_notebooksHash.insert(notebook->guid(), notebook);
656@@ -359,6 +352,27 @@
657 emit notebookChanged(notebook->guid());
658 }
659
660+void NotesStore::setDefaultNotebook(const QString &guid)
661+{
662+ Notebook *notebook = m_notebooksHash.value(guid);
663+ if (!notebook) {
664+ qWarning() << "[NotesStore] Notebook guid not found:" << guid;
665+ return;
666+ }
667+
668+ qDebug() << "[NotesStore] Setting default notebook:" << guid;
669+ foreach (Notebook *tmp, m_notebooks) {
670+ if (tmp->isDefaultNotebook()) {
671+ tmp->setIsDefaultNotebook(false);
672+ saveNotebook(tmp->guid());
673+ break;
674+ }
675+ }
676+ notebook->setIsDefaultNotebook(true);
677+ saveNotebook(guid);
678+ emit defaultNotebookChanged(guid);
679+}
680+
681 void NotesStore::saveTag(const QString &guid)
682 {
683 Tag *tag = m_tagsHash.value(guid);
684@@ -381,9 +395,66 @@
685
686 void NotesStore::expungeNotebook(const QString &guid)
687 {
688- ExpungeNotebookJob *job = new ExpungeNotebookJob(guid);
689- connect(job, &ExpungeNotebookJob::jobDone, this, &NotesStore::expungeNotebookJobDone);
690- EvernoteConnection::instance()->enqueue(job);
691+ if (m_username != "@local") {
692+ qWarning() << "[NotesStore] Account managed by Evernote. Cannot delete notebooks.";
693+ m_errorQueue.append(QString(gettext("This account is managed by Evernote. Use the Evernote website to delete notebooks.")));
694+ emit errorChanged();
695+ return;
696+ }
697+
698+ Notebook* notebook = m_notebooksHash.value(guid);
699+ if (!notebook) {
700+ qWarning() << "[NotesStore] Cannot delete notebook. Notebook not found for guid:" << guid;
701+ return;
702+ }
703+
704+ if (notebook->isDefaultNotebook()) {
705+ qWarning() << "[NotesStore] Cannot delete the default notebook.";
706+ m_errorQueue.append(QString(gettext("Cannot delete the default notebook. Set another notebook to be the default first.")));
707+ emit errorChanged();
708+ return;
709+ }
710+
711+ if (notebook->noteCount() > 0) {
712+ QString defaultNotebook;
713+ foreach (const Notebook *notebook, m_notebooks) {
714+ if (notebook->isDefaultNotebook()) {
715+ defaultNotebook = notebook->guid();
716+ break;
717+ }
718+ }
719+ if (defaultNotebook.isEmpty()) {
720+ qWarning() << "[NotesStore] No default notebook set. Can't delete notebooks.";
721+ return;
722+ }
723+
724+ while (notebook->noteCount() > 0) {
725+ QString noteGuid = notebook->noteAt(0);
726+ Note *note = m_notesHash.value(noteGuid);
727+ if (!note) {
728+ qWarning() << "[NotesStore] Notebook holds a noteGuid which cannot be found in notes store";
729+ Q_ASSERT(false);
730+ continue;
731+ }
732+ qDebug() << "[NotesStore] Moving note" << noteGuid << "to default Notebook";
733+ note->setNotebookGuid(defaultNotebook);
734+ saveNote(note->guid());
735+ emit noteChanged(note->guid(), defaultNotebook);
736+ syncToCacheFile(note);
737+ }
738+ }
739+
740+ m_notebooks.removeAll(notebook);
741+ m_notebooksHash.remove(notebook->guid());
742+ emit notebookRemoved(notebook->guid());
743+
744+ QSettings settings(m_cacheFile, QSettings::IniFormat);
745+ settings.beginGroup("notebooks");
746+ settings.remove(notebook->guid());
747+ settings.endGroup();
748+
749+ notebook->deleteInfoFile();
750+ notebook->deleteLater();
751 }
752
753 QList<Tag *> NotesStore::tags() const
754@@ -548,11 +619,7 @@
755 {
756 switch (errorCode) {
757 case EvernoteConnection::ErrorCodeNoError:
758- // All is well, reset error code.
759- if (!m_error.isEmpty()) {
760- m_error.clear();
761- emit errorChanged();
762- }
763+ // All is well...
764 break;
765 case EvernoteConnection::ErrorCodeUserException:
766 qWarning() << "FetchNotesJobDone: EDAMUserException:" << errorMessage;
767@@ -571,8 +638,6 @@
768 return; // silently discarding...
769 default:
770 qWarning() << "FetchNotesJobDone: Failed to fetch notes list:" << errorMessage << errorCode;
771- m_error = QString(gettext("Error refreshing notes: %1")).arg(errorMessage);
772- emit errorChanged();
773 m_loading = false;
774 emit loadingChanged();
775 return;
776@@ -875,11 +940,7 @@
777
778 switch (errorCode) {
779 case EvernoteConnection::ErrorCodeNoError:
780- // All is well, reset error code.
781- if (!m_notebooksError.isEmpty()) {
782- m_notebooksError.clear();
783- emit notebooksErrorChanged();
784- }
785+ // All is well...
786 break;
787 case EvernoteConnection::ErrorCodeUserException:
788 qWarning() << "FetchNotebooksJobDone: EDAMUserException:" << errorMessage;
789@@ -890,19 +951,19 @@
790 return; // silently discarding
791 default:
792 qWarning() << "FetchNotebooksJobDone: Failed to fetch notes list:" << errorMessage << errorCode;
793- m_notebooksError = tr("Error refreshing notebooks: %1").arg(errorMessage);
794- emit notebooksErrorChanged();
795- return;
796+ return; // silently discarding
797 }
798
799 QList<Notebook*> unhandledNotebooks = m_notebooks;
800
801+ qDebug() << "[NotesStore] Have" << results.size() << "from Evernote.";
802 for (unsigned int i = 0; i < results.size(); ++i) {
803 evernote::edam::Notebook result = results.at(i);
804 Notebook *notebook = m_notebooksHash.value(QString::fromStdString(result.guid));
805 unhandledNotebooks.removeAll(notebook);
806 bool newNotebook = notebook == 0;
807 if (newNotebook) {
808+ qDebug() << "[NotesStore] Found new notebook on Evernote:" << QString::fromStdString(result.guid);
809 notebook = new Notebook(QString::fromStdString(result.guid), 0, this);
810 updateFromEDAM(result, notebook);
811 m_notebooksHash.insert(notebook->guid(), notebook);
812@@ -911,20 +972,25 @@
813 syncToCacheFile(notebook);
814 } else if (notebook->synced()) {
815 if (notebook->updateSequenceNumber() < result.updateSequenceNum) {
816+ qDebug() << "[NotesStore] Notebook on Evernote is newer than local copy. Updating:" << notebook->guid();
817 updateFromEDAM(result, notebook);
818 emit notebookChanged(notebook->guid());
819 syncToCacheFile(notebook);
820+ } else {
821+ qDebug() << "[NotesStore] Notebook is in sync:" << notebook->guid();
822 }
823 } else {
824 // Local notebook changed. See if we can push our changes
825 if (result.updateSequenceNum == notebook->lastSyncedSequenceNumber()) {
826+ qDebug() << "[NotesStore] Local Notebook changed. Uploading changes to Evernote:" << notebook->guid();
827 SaveNotebookJob *job = new SaveNotebookJob(notebook);
828 connect(job, &SaveNotebookJob::jobDone, this, &NotesStore::saveNotebookJobDone);
829 EvernoteConnection::instance()->enqueue(job);
830 notebook->setLoading(true);
831 emit notebookChanged(notebook->guid());
832 } else {
833- qWarning() << "CONFLICT in notebook:" << notebook->name();
834+ qWarning() << "[NotesStore] Sync conflict in notebook:" << notebook->name();
835+ qWarning() << "[NotesStore] Resolving of sync conflicts is not implemented yet.";
836 notebook->setSyncError(true);
837 emit notebookChanged(notebook->guid());
838 }
839@@ -933,18 +999,20 @@
840
841 foreach (Notebook *notebook, unhandledNotebooks) {
842 if (notebook->lastSyncedSequenceNumber() == 0) {
843+ qDebug() << "[NotesStore] Have a local notebook that doesn't exist on Evernote. Creating on server:" << notebook->guid();
844 notebook->setLoading(true);
845 CreateNotebookJob *job = new CreateNotebookJob(notebook);
846 connect(job, &CreateNotebookJob::jobDone, this, &NotesStore::createNotebookJobDone);
847 EvernoteConnection::instance()->enqueue(job);
848 emit notebookChanged(notebook->guid());
849 } else {
850+ qDebug() << "[NotesStore] Notebook has been deleted on the server. Deleting local copy:" << notebook->guid();
851 m_notebooks.removeAll(notebook);
852 m_notebooksHash.remove(notebook->guid());
853 emit notebookRemoved(notebook->guid());
854
855 QSettings settings(m_cacheFile, QSettings::IniFormat);
856- settings.beginGroup("notenooks");
857+ settings.beginGroup("notebooks");
858 settings.remove(notebook->guid());
859 settings.endGroup();
860
861@@ -967,6 +1035,14 @@
862 EvernoteConnection::instance()->enqueue(job);
863 }
864
865+void NotesStore::clearError()
866+{
867+ if (m_errorQueue.count() > 0) {
868+ m_errorQueue.takeFirst();
869+ emit errorChanged();
870+ }
871+}
872+
873 void NotesStore::fetchTagsJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const std::vector<evernote::edam::Tag> &results)
874 {
875 m_tagsLoading = false;
876@@ -974,11 +1050,7 @@
877
878 switch (errorCode) {
879 case EvernoteConnection::ErrorCodeNoError:
880- // All is well, reset error code.
881- if (!m_tagsError.isEmpty()) {
882- m_tagsError.clear();
883- emit tagsErrorChanged();
884- }
885+ // All is well...
886 break;
887 case EvernoteConnection::ErrorCodeUserException:
888 qWarning() << "FetchTagsJobDone: EDAMUserException:" << errorMessage;
889@@ -989,9 +1061,7 @@
890 return; // silently discarding
891 default:
892 qWarning() << "FetchTagsJobDone: Failed to fetch notes list:" << errorMessage << errorCode;
893- m_tagsError = tr("Error refreshing tags: %1").arg(errorMessage);
894- emit tagsErrorChanged();
895- return;
896+ return; // silently discarding
897 }
898
899 QHash<QString, Tag*> unhandledTags = m_tagsHash;
900@@ -1067,10 +1137,18 @@
901 connect(note, &Note::reminderDoneChanged, this, &NotesStore::emitDataChanged);
902
903 note->setTitle(title);
904- if (notebookGuid.isEmpty() && m_notebooks.count() > 0) {
905- note->setNotebookGuid(m_notebooks.first()->guid());
906- } else {
907+
908+ if (!notebookGuid.isEmpty()) {
909 note->setNotebookGuid(notebookGuid);
910+ } else if (m_notebooks.count() > 0){
911+ QString generatedNotebook = m_notebooks.first()->guid();
912+ foreach (Notebook *notebook, m_notebooks) {
913+ if (notebook->isDefaultNotebook()) {
914+ generatedNotebook = notebook->guid();
915+ break;
916+ }
917+ }
918+ note->setNotebookGuid(generatedNotebook);
919 }
920 note->setEnmlContent(content.enml());
921 note->setCreated(QDateTime::currentDateTime());
922@@ -1534,5 +1612,49 @@
923 if (evNotebook.__isset.published && evNotebook.published != notebook->published()) {
924 notebook->setPublished(evNotebook.published);
925 }
926+ qDebug() << "readong from evernote:" << evNotebook.__isset.defaultNotebook << evNotebook.defaultNotebook << notebook->name();
927+ if (evNotebook.__isset.defaultNotebook && evNotebook.defaultNotebook != notebook->isDefaultNotebook()) {
928+ notebook->setIsDefaultNotebook(evNotebook.defaultNotebook);
929+ }
930 notebook->setLastSyncedSequenceNumber(evNotebook.updateSequenceNum);
931 }
932+
933+
934+void NotesStore::expungeTag(const QString &guid)
935+{
936+ if (m_username != "@local") {
937+ qWarning() << "This account is managed by Evernote. Cannot delete tags.";
938+ m_errorQueue.append(gettext("This account is managed by Evernote. Please use the Evernote website to delete tags."));
939+ emit errorChanged();
940+ return;
941+ }
942+
943+ Tag *tag = m_tagsHash.value(guid);
944+ if (!tag) {
945+ qWarning() << "[NotesStore] No tag with guid" << guid;
946+ return;
947+ }
948+
949+ while (tag->noteCount() > 0) {
950+ QString noteGuid = tag->noteAt(0);
951+ Note *note = m_notesHash.value(noteGuid);
952+ if (!note) {
953+ qWarning() << "[NotesStore] Tag holds note" << noteGuid << "which hasn't been found in Notes Store";
954+ continue;
955+ }
956+ untagNote(noteGuid, guid);
957+ }
958+
959+ emit tagRemoved(guid);
960+ m_tagsHash.remove(guid);
961+ m_tags.removeAll(tag);
962+
963+ QSettings cacheFile(m_cacheFile, QSettings::IniFormat);
964+ cacheFile.beginGroup("tags");
965+ cacheFile.remove(guid);
966+ cacheFile.endGroup();
967+ tag->syncToInfoFile();
968+
969+ tag->deleteInfoFile();
970+ tag->deleteLater();
971+}
972
973=== modified file 'src/libqtevernote/notesstore.h'
974--- src/libqtevernote/notesstore.h 2015-02-26 22:47:10 +0000
975+++ src/libqtevernote/notesstore.h 2015-03-04 00:26:40 +0000
976@@ -59,7 +59,6 @@
977 Q_PROPERTY(bool loading READ loading NOTIFY loadingChanged)
978 Q_PROPERTY(bool notebooksLoading READ notebooksLoading NOTIFY notebooksLoadingChanged)
979 Q_PROPERTY(QString error READ error NOTIFY errorChanged)
980- Q_PROPERTY(QString notebooksError READ notebooksError NOTIFY notebooksErrorChanged)
981 Q_PROPERTY(int count READ count NOTIFY countChanged)
982
983 public:
984@@ -105,8 +104,6 @@
985 bool tagsLoading() const;
986
987 QString error() const;
988- QString notebooksError() const;
989- QString tagsError() const;
990
991 int count() const;
992
993@@ -129,6 +126,7 @@
994 Q_INVOKABLE Notebook* notebook(const QString &guid);
995 Q_INVOKABLE void createNotebook(const QString &name);
996 Q_INVOKABLE void saveNotebook(const QString &guid);
997+ Q_INVOKABLE void setDefaultNotebook(const QString &guid);
998 Q_INVOKABLE void expungeNotebook(const QString &guid);
999
1000 QList<Tag*> tags() const;
1001@@ -137,6 +135,7 @@
1002 Q_INVOKABLE void saveTag(const QString &guid);
1003 Q_INVOKABLE void tagNote(const QString &noteGuid, const QString &tagGuid);
1004 Q_INVOKABLE void untagNote(const QString &noteGuid, const QString &tagGuid);
1005+ Q_INVOKABLE void expungeTag(const QString &guid);
1006
1007 public slots:
1008 void refreshNotes(const QString &filterNotebookGuid = QString(), int startIndex = 0);
1009@@ -146,14 +145,14 @@
1010 void refreshNotebooks();
1011 void refreshTags();
1012
1013+ void clearError();
1014+
1015 signals:
1016 void usernameChanged();
1017 void loadingChanged();
1018 void notebooksLoadingChanged();
1019 void tagsLoadingChanged();
1020 void errorChanged();
1021- void notebooksErrorChanged();
1022- void tagsErrorChanged();
1023 void countChanged();
1024
1025 void noteCreated(const QString &guid, const QString &notebookGuid);
1026@@ -167,6 +166,7 @@
1027 void notebookChanged(const QString &guid);
1028 void notebookRemoved(const QString &guid);
1029 void notebookGuidChanged(const QString &oldGuid, const QString &newGuid);
1030+ void defaultNotebookChanged(const QString &guid);
1031
1032 void tagAdded(const QString &guid);
1033 void tagChanged(const QString &guid);
1034@@ -213,9 +213,7 @@
1035 bool m_notebooksLoading;
1036 bool m_tagsLoading;
1037
1038- QString m_error;
1039- QString m_notebooksError;
1040- QString m_tagsError;
1041+ QStringList m_errorQueue;
1042
1043 QList<Note*> m_notes;
1044 QList<Notebook*> m_notebooks;
1045
1046=== modified file 'src/libqtevernote/tag.cpp'
1047--- src/libqtevernote/tag.cpp 2015-02-24 22:21:04 +0000
1048+++ src/libqtevernote/tag.cpp 2015-03-04 00:26:40 +0000
1049@@ -219,3 +219,9 @@
1050 emit syncErrorChanged();
1051 }
1052 }
1053+
1054+
1055+QString Tag::noteAt(int index) const
1056+{
1057+ return m_notesList.at(index);
1058+}
1059
1060=== modified file 'src/libqtevernote/tag.h'
1061--- src/libqtevernote/tag.h 2014-12-13 03:55:52 +0000
1062+++ src/libqtevernote/tag.h 2015-03-04 00:26:40 +0000
1063@@ -61,6 +61,7 @@
1064 void setName(const QString &guid);
1065
1066 int noteCount() const;
1067+ QString noteAt(int index) const;
1068
1069 bool loading() const;
1070 bool synced() const;
1071
1072=== modified file 'src/libqtevernote/tags.cpp'
1073--- src/libqtevernote/tags.cpp 2014-12-13 03:55:52 +0000
1074+++ src/libqtevernote/tags.cpp 2015-03-04 00:26:40 +0000
1075@@ -32,7 +32,6 @@
1076 }
1077
1078 connect(NotesStore::instance(), &NotesStore::tagsLoadingChanged, this, &Tags::loadingChanged);
1079- connect(NotesStore::instance(), &NotesStore::tagsErrorChanged, this, &Tags::errorChanged);
1080 connect(NotesStore::instance(), &NotesStore::tagAdded, this, &Tags::tagAdded);
1081 connect(NotesStore::instance(), &NotesStore::tagRemoved, this, &Tags::tagRemoved);
1082 connect(NotesStore::instance(), &NotesStore::tagGuidChanged, this, &Tags::tagGuidChanged);
1083@@ -43,11 +42,6 @@
1084 return NotesStore::instance()->tagsLoading();
1085 }
1086
1087-QString Tags::error() const
1088-{
1089- return NotesStore::instance()->tagsError();
1090-}
1091-
1092 int Tags::count() const
1093 {
1094 return rowCount();
1095
1096=== modified file 'src/libqtevernote/tags.h'
1097--- src/libqtevernote/tags.h 2014-12-13 03:55:52 +0000
1098+++ src/libqtevernote/tags.h 2015-03-04 00:26:40 +0000
1099@@ -29,7 +29,6 @@
1100 {
1101 Q_OBJECT
1102 Q_PROPERTY(bool loading READ loading NOTIFY loadingChanged)
1103- Q_PROPERTY(QString error READ error NOTIFY errorChanged)
1104 Q_PROPERTY(int count READ count NOTIFY countChanged)
1105
1106 public:
1107@@ -44,7 +43,6 @@
1108 explicit Tags(QObject *parent = 0);
1109
1110 bool loading() const;
1111- QString error() const;
1112 int count() const;
1113
1114 QVariant data(const QModelIndex &index, int role) const;
1115@@ -58,7 +56,6 @@
1116
1117 signals:
1118 void loadingChanged();
1119- void errorChanged();
1120 void countChanged();
1121
1122 private slots:

Subscribers

People subscribed via source and target branches