Merge lp:~mzanetti/reminders-app/notesdelegate into lp:reminders-app

Proposed by Michael Zanetti
Status: Superseded
Proposed branch: lp:~mzanetti/reminders-app/notesdelegate
Merge into: lp:reminders-app
Diff against target: 3403 lines (+1845/-702)
49 files modified
src/app/app.pro (+4/-1)
src/app/qml/components/NotesDelegate.qml (+56/-0)
src/app/qml/components/ToolbarSpacer.qml (+45/-0)
src/app/qml/reminders-app.qml (+8/-1)
src/app/qml/ui/AccountSelectorPage.qml (+1/-1)
src/app/qml/ui/NotePage.qml (+2/-0)
src/app/qml/ui/NotebooksPage.qml (+9/-0)
src/app/qml/ui/NotesPage.qml (+21/-7)
src/app/qml/ui/RemindersPage.qml (+9/-10)
src/app/qml/ui/SearchNotesPage.qml (+80/-0)
src/plugin/Evernote/Evernote.pro (+14/-2)
src/plugin/Evernote/evernoteconnection.cpp (+190/-0)
src/plugin/Evernote/evernoteconnection.h (+101/-0)
src/plugin/Evernote/evernoteplugin.cpp (+14/-2)
src/plugin/Evernote/jobs/createnotebookjob.cpp (+41/-0)
src/plugin/Evernote/jobs/createnotebookjob.h (+46/-0)
src/plugin/Evernote/jobs/createnotejob.cpp (+26/-32)
src/plugin/Evernote/jobs/createnotejob.h (+13/-8)
src/plugin/Evernote/jobs/deletenotejob.cpp (+9/-10)
src/plugin/Evernote/jobs/deletenotejob.h (+7/-5)
src/plugin/Evernote/jobs/evernotejob.cpp (+50/-17)
src/plugin/Evernote/jobs/evernotejob.h (+22/-8)
src/plugin/Evernote/jobs/expungenotebookjob.cpp (+39/-0)
src/plugin/Evernote/jobs/expungenotebookjob.h (+43/-0)
src/plugin/Evernote/jobs/fetchnotebooksjob.cpp (+13/-17)
src/plugin/Evernote/jobs/fetchnotebooksjob.h (+10/-5)
src/plugin/Evernote/jobs/fetchnotejob.cpp (+7/-17)
src/plugin/Evernote/jobs/fetchnotejob.h (+10/-4)
src/plugin/Evernote/jobs/fetchnotesjob.cpp (+27/-18)
src/plugin/Evernote/jobs/fetchnotesjob.h (+10/-6)
src/plugin/Evernote/jobs/fetchusernamejob.cpp (+38/-0)
src/plugin/Evernote/jobs/fetchusernamejob.h (+43/-0)
src/plugin/Evernote/jobs/notesstorejob.cpp (+39/-0)
src/plugin/Evernote/jobs/notesstorejob.h (+44/-0)
src/plugin/Evernote/jobs/savenotejob.cpp (+36/-33)
src/plugin/Evernote/jobs/savenotejob.h (+9/-5)
src/plugin/Evernote/jobs/userstorejob.cpp (+39/-0)
src/plugin/Evernote/jobs/userstorejob.h (+46/-0)
src/plugin/Evernote/note.cpp (+115/-11)
src/plugin/Evernote/note.h (+55/-4)
src/plugin/Evernote/notebooks.cpp (+0/-1)
src/plugin/Evernote/notes.cpp (+58/-80)
src/plugin/Evernote/notes.h (+17/-25)
src/plugin/Evernote/notesstore.cpp (+245/-231)
src/plugin/Evernote/notesstore.h (+53/-41)
src/plugin/Evernote/userstore.cpp (+38/-95)
src/plugin/Evernote/userstore.h (+19/-5)
src/plugin/Evernote/utils/html2enmlconverter.cpp (+22/-0)
src/plugin/Evernote/utils/html2enmlconverter.h (+2/-0)
To merge this branch: bzr merge lp:~mzanetti/reminders-app/notesdelegate
Reviewer Review Type Date Requested Status
Ubuntu Phone Apps Jenkins Bot continuous-integration Needs Fixing
Ubuntu Notes app developers Pending
Review via email: mp+199011@code.launchpad.net

This proposal has been superseded by a proposal from 2013-12-14.

Commit message

Added a NotesDelegate to roughly reflect design wireframe

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: Needs Fixing (continuous-integration)
25. By Michael Zanetti

don't automatically fetch notes content to avoid hitting the rate limit

26. By Michael Zanetti

merge prerequisite branch

27. By Michael Zanetti

added missing file

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/app/app.pro'
2--- src/app/app.pro 2013-11-22 21:35:34 +0000
3+++ src/app/app.pro 2013-12-14 00:07:45 +0000
4@@ -10,7 +10,10 @@
5 qml/ui/RemindersPage.qml \
6 qml/ui/NotesPage.qml \
7 qml/ui/AccountSelectorPage.qml \
8- qml/ui/NotePage.qml
9+ qml/ui/NotePage.qml \
10+ qml/ui/SearchNotesPage.qml \
11+ qml/components/ToolbarSpacer.qml \
12+ qml/components/NotesDelegate.qml \
13
14 # Copy qml to build dir for running with qtcreator
15 qmlfolder.source = src/app/qml
16
17=== added directory 'src/app/qml/components'
18=== added file 'src/app/qml/components/NotesDelegate.qml'
19--- src/app/qml/components/NotesDelegate.qml 1970-01-01 00:00:00 +0000
20+++ src/app/qml/components/NotesDelegate.qml 2013-12-14 00:07:45 +0000
21@@ -0,0 +1,56 @@
22+/*
23+ * Copyright: 2013 Canonical, Ltd
24+ *
25+ * This file is part of reminders-app
26+ *
27+ * reminders-app is free software: you can redistribute it and/or modify
28+ * it under the terms of the GNU General Public License as published by
29+ * the Free Software Foundation; version 3.
30+ *
31+ * reminders-app is distributed in the hope that it will be useful,
32+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
33+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34+ * GNU General Public License for more details.
35+ *
36+ * You should have received a copy of the GNU General Public License
37+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
38+ */
39+
40+import QtQuick 2.0
41+import Ubuntu.Components 0.1
42+import Ubuntu.Components.ListItems 0.1
43+
44+Empty {
45+ id: root
46+ height: units.gu(9)
47+
48+ property string title
49+ property date creationDate
50+ property string content
51+
52+ Column {
53+ id: contentColumn
54+ spacing: units.gu(1)
55+ anchors {
56+ top: parent.top
57+ topMargin: units.gu(1)
58+ left: parent.left
59+ leftMargin: units.gu(2)
60+ right: parent.right
61+ rightMargin: units.gu(2)
62+ }
63+ Label {
64+ anchors { left: parent.left; right: parent.right }
65+ text: root.title
66+ font.bold: true
67+ elide: Text.ElideRight
68+ }
69+ Label {
70+ anchors { left: parent.left; right: parent.right }
71+ text: "<font color=\"#dd4814\">"+ Qt.formatDate(root.creationDate) + "</font> " + root.content
72+ wrapMode: Text.WordWrap
73+ textFormat: Text.StyledText
74+ maximumLineCount: 2
75+ }
76+ }
77+}
78
79=== added file 'src/app/qml/components/ToolbarSpacer.qml'
80--- src/app/qml/components/ToolbarSpacer.qml 1970-01-01 00:00:00 +0000
81+++ src/app/qml/components/ToolbarSpacer.qml 2013-12-14 00:07:45 +0000
82@@ -0,0 +1,45 @@
83+/*
84+ * Copyright: 2013 Canonical, Ltd
85+ *
86+ * This file is part of reminders-app
87+ *
88+ * reminders-app is free software: you can redistribute it and/or modify
89+ * it under the terms of the GNU General Public License as published by
90+ * the Free Software Foundation; version 3.
91+ *
92+ * reminders-app is distributed in the hope that it will be useful,
93+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
94+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
95+ * GNU General Public License for more details.
96+ *
97+ * You should have received a copy of the GNU General Public License
98+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
99+ */
100+
101+import QtQuick 2.0
102+import Ubuntu.Components 0.1
103+import Ubuntu.Components.Popups 0.1
104+
105+Item {
106+ id: spacerItem
107+ objectName: "__ToolBarItems.SpacerItem"
108+ height: parent.height
109+ width: {
110+ var othersWidth = 0;
111+
112+ // Hack: the autogenerated back button
113+ if (pageStack != null && pageStack.depth > 1) {
114+ othersWidth = units.gu(6)
115+ }
116+
117+ for (var i = 0; i < parent.children.length; ++i) {
118+ var otherItem = parent.children[i];
119+ if (otherItem.objectName !== "__ToolBarItems.SpacerItem") {
120+ if (otherItem.visible) {
121+ othersWidth += otherItem.width + parent.spacing;
122+ }
123+ }
124+ }
125+ return parent.parent.width - othersWidth - units.gu(4);
126+ }
127+}
128
129=== modified file 'src/app/qml/reminders-app.qml'
130--- src/app/qml/reminders-app.qml 2013-11-26 17:18:33 +0000
131+++ src/app/qml/reminders-app.qml 2013-12-14 00:07:45 +0000
132@@ -47,11 +47,18 @@
133
134 Component.onCompleted: {
135 pagestack.push(rootTabs)
136- if (NotesStore.token.length === 0) {
137+ if (EvernoteConnection.token.length === 0) {
138 pagestack.push(Qt.resolvedUrl("ui/AccountSelectorPage.qml"));
139 }
140 }
141
142+ Connections {
143+ target: UserStore
144+ onUsernameChanged: {
145+ print("Logged in as user:", UserStore.username)
146+ }
147+ }
148+
149 PageStack {
150 id: pagestack
151
152
153=== modified file 'src/app/qml/ui/AccountSelectorPage.qml'
154--- src/app/qml/ui/AccountSelectorPage.qml 2013-11-26 17:18:33 +0000
155+++ src/app/qml/ui/AccountSelectorPage.qml 2013-12-14 00:07:45 +0000
156@@ -51,7 +51,7 @@
157 // Print the access token on the console
158 onAuthenticated: {
159 console.log("Access token is " + reply.AccessToken)
160- NotesStore.token = reply.AccessToken;
161+ EvernoteConnection.token = reply.AccessToken;
162 pagestack.pop();
163 }
164 onAuthenticationError: { console.log("Authentication failed, code " + error.code) }
165
166=== modified file 'src/app/qml/ui/NotePage.qml'
167--- src/app/qml/ui/NotePage.qml 2013-11-26 17:18:33 +0000
168+++ src/app/qml/ui/NotePage.qml 2013-12-14 00:07:45 +0000
169@@ -24,6 +24,8 @@
170 title: note.title
171 property var note
172
173+ Component.onCompleted: NotesStore.refreshNoteContent(note.guid)
174+
175 Column {
176 anchors.fill: parent
177 spacing: units.gu(1)
178
179=== modified file 'src/app/qml/ui/NotebooksPage.qml'
180--- src/app/qml/ui/NotebooksPage.qml 2013-11-26 17:18:33 +0000
181+++ src/app/qml/ui/NotebooksPage.qml 2013-12-14 00:07:45 +0000
182@@ -30,6 +30,15 @@
183 }
184 }
185
186+ tools: ToolbarItems {
187+ ToolbarButton {
188+ text: "add notebook"
189+ onTriggered: {
190+ NotesStore.createNotebook("new notebook");
191+ }
192+ }
193+ }
194+
195 Notebooks {
196 id: notebooks
197 }
198
199=== modified file 'src/app/qml/ui/NotesPage.qml'
200--- src/app/qml/ui/NotesPage.qml 2013-11-26 17:18:33 +0000
201+++ src/app/qml/ui/NotesPage.qml 2013-12-14 00:07:45 +0000
202@@ -20,6 +20,7 @@
203 import Ubuntu.Components 0.1
204 import Ubuntu.Components.ListItems 0.1
205 import Evernote 0.1
206+import "../components"
207
208 Page {
209 id: notesPage
210@@ -28,14 +29,23 @@
211
212 onActiveChanged: {
213 if (active) {
214- print("refreshing notes")
215- notes.refresh();
216+ NotesStore.refreshNotes();
217 }
218 }
219
220 // Just for testing
221 tools: ToolbarItems {
222 ToolbarButton {
223+ text: "search"
224+ iconName: "search"
225+ onTriggered: {
226+ pagestack.push(Qt.resolvedUrl("SearchNotesPage.qml"))
227+ }
228+ }
229+
230+ ToolbarSpacer { }
231+
232+ ToolbarButton {
233 text: "add note"
234 enabled: notes.filterNotebookGuid.length > 0
235 onTriggered: {
236@@ -52,18 +62,22 @@
237 }
238
239 ListView {
240- anchors.fill: parent
241+ anchors { left: parent.left; right: parent.right }
242+ height: parent.height - y
243 model: notes
244+ clip: true
245
246- delegate: Standard {
247- text: title
248+ delegate: NotesDelegate {
249+ title: model.title
250+ creationDate: model.created
251+ content: NotesStore.note(model.guid).plaintextContent
252
253 onClicked: {
254- pageStack.push(Qt.resolvedUrl("NotePage.qml"), {note: notes.note(guid)})
255+ pageStack.push(Qt.resolvedUrl("NotePage.qml"), {note: NotesStore.note(guid)})
256 }
257
258 onPressAndHold: {
259- notes.note(guid).remove();
260+ NotesStore.deleteNote(guid);
261 }
262 }
263 }
264
265=== modified file 'src/app/qml/ui/RemindersPage.qml'
266--- src/app/qml/ui/RemindersPage.qml 2013-11-26 17:18:33 +0000
267+++ src/app/qml/ui/RemindersPage.qml 2013-12-14 00:07:45 +0000
268@@ -19,28 +19,27 @@
269 import QtQuick 2.0
270 import Ubuntu.Components 0.1
271 import Ubuntu.Components.ListItems 0.1
272-//import "../components"
273+import Evernote 0.1
274
275 Page {
276 id: remindersPage
277
278- Label {
279- id: developmentWarning
280- anchors.centerIn: parent
281- text: i18n.tr("This page is still in development")
282+ Notes {
283+ id: notes
284+ onlyReminders: true
285 }
286
287 ListView {
288
289- width: parent.width; height: parent.height
290+ anchors.fill: parent
291
292 delegate: Subtitled {
293- text: '<b>Name:</b> ' + model.name
294- subText: '<b>Date:</b> ' + model.date
295+ text: '<b>Name:</b> ' + model.title
296+ subText: '<b>Date:</b> ' + Qt.formatDateTime(model.created) +
297+ (model.reminderDone ? " - <b>Done:</b> " + Qt.formatDate(model.reminderDoneTime) : "")
298 }
299
300-// model: RemindersModel {}
301-
302+ model: notes
303 }
304
305 }
306
307=== added file 'src/app/qml/ui/SearchNotesPage.qml'
308--- src/app/qml/ui/SearchNotesPage.qml 1970-01-01 00:00:00 +0000
309+++ src/app/qml/ui/SearchNotesPage.qml 2013-12-14 00:07:45 +0000
310@@ -0,0 +1,80 @@
311+/*
312+ * Copyright: 2013 Canonical, Ltd
313+ *
314+ * This file is part of reminders-app
315+ *
316+ * reminders-app is free software: you can redistribute it and/or modify
317+ * it under the terms of the GNU General Public License as published by
318+ * the Free Software Foundation; version 3.
319+ *
320+ * reminders-app is distributed in the hope that it will be useful,
321+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
322+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
323+ * GNU General Public License for more details.
324+ *
325+ * You should have received a copy of the GNU General Public License
326+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
327+ */
328+
329+import QtQuick 2.0
330+import Ubuntu.Components 0.1
331+import Ubuntu.Components.ListItems 0.1
332+import Evernote 0.1
333+import "../components"
334+
335+Page {
336+ Column {
337+ anchors { fill: parent; topMargin: units.gu(2); bottomMargin: units.gu(2) }
338+ spacing: units.gu(2)
339+
340+ Row {
341+ anchors { left: parent.left; right: parent.right; margins: units.gu(2) }
342+ spacing: units.gu(1)
343+
344+ TextField {
345+ id: searchField
346+ width: parent.width - searchButton.width - parent.spacing
347+ anchors.verticalCenter: parent.verticalCenter
348+
349+ primaryItem: Icon {
350+ height: searchField.height - units.gu(1)
351+ width: height
352+ name: "search"
353+ }
354+
355+ onAccepted: {
356+ NotesStore.findNotes(searchField.text + "*")
357+ }
358+ }
359+ Button {
360+ id: searchButton
361+ height: searchField.height
362+ text: "search"
363+ onClicked: {
364+ NotesStore.findNotes(searchField.text + "*")
365+ }
366+ }
367+ }
368+
369+ ListView {
370+ anchors { left: parent.left; right: parent.right }
371+ height: parent.height - y
372+ clip: true
373+
374+ model: Notes {
375+ onlySearchResults: true
376+ }
377+
378+ delegate: NotesDelegate {
379+ title: model.title
380+ creationDate: model.created
381+ content: NotesStore.note(model.guid).plaintextContent
382+
383+ onClicked: {
384+ pageStack.push(Qt.resolvedUrl("NotePage.qml"), {note: NotesStore.note(guid)})
385+ }
386+ }
387+ }
388+
389+ }
390+}
391
392=== modified file 'src/plugin/Evernote/Evernote.pro'
393--- src/plugin/Evernote/Evernote.pro 2013-11-27 17:33:36 +0000
394+++ src/plugin/Evernote/Evernote.pro 2013-12-14 00:07:45 +0000
395@@ -23,7 +23,13 @@
396 jobs/evernotejob.cpp \
397 jobs/savenotejob.cpp \
398 jobs/deletenotejob.cpp \
399- utils/html2enmlconverter.cpp
400+ utils/html2enmlconverter.cpp \
401+ evernoteconnection.cpp \
402+ jobs/userstorejob.cpp \
403+ jobs/notesstorejob.cpp \
404+ jobs/fetchusernamejob.cpp \
405+ jobs/createnotebookjob.cpp \
406+ jobs/expungenotebookjob.cpp
407
408 HEADERS += evernoteplugin.h \
409 notesstore.h \
410@@ -39,7 +45,13 @@
411 jobs/evernotejob.h \
412 jobs/savenotejob.h \
413 jobs/deletenotejob.h \
414- utils/html2enmlconverter.h
415+ utils/html2enmlconverter.h \
416+ evernoteconnection.h \
417+ jobs/userstorejob.h \
418+ jobs/notesstorejob.h \
419+ jobs/fetchusernamejob.h \
420+ jobs/createnotebookjob.h \
421+ jobs/expungenotebookjob.h
422
423 message(building in $$OUT_PWD)
424 LIBS += -L$$OUT_PWD/../../../3rdParty/evernote-sdk-cpp/ -L$$OUT_PWD/../../../3rdParty/libthrift/ -levernote-sdk-cpp -llibthrift -lssl -lcrypto
425
426=== added file 'src/plugin/Evernote/evernoteconnection.cpp'
427--- src/plugin/Evernote/evernoteconnection.cpp 1970-01-01 00:00:00 +0000
428+++ src/plugin/Evernote/evernoteconnection.cpp 2013-12-14 00:07:45 +0000
429@@ -0,0 +1,190 @@
430+/*
431+ * Copyright: 2013 Canonical, Ltd
432+ *
433+ * This file is part of reminders-app
434+ *
435+ * reminders-app is free software: you can redistribute it and/or modify
436+ * it under the terms of the GNU General Public License as published by
437+ * the Free Software Foundation; version 3.
438+ *
439+ * reminders-app is distributed in the hope that it will be useful,
440+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
441+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
442+ * GNU General Public License for more details.
443+ *
444+ * You should have received a copy of the GNU General Public License
445+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
446+ *
447+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
448+ */
449+
450+#include "evernoteconnection.h"
451+#include "jobs/evernotejob.h"
452+
453+// Thrift
454+#include <arpa/inet.h> // seems thrift forgot this one
455+#include <protocol/TBinaryProtocol.h>
456+#include <transport/THttpClient.h>
457+#include <transport/TSSLSocket.h>
458+#include <Thrift.h>
459+
460+// Evernote SDK
461+#include <NoteStore.h>
462+#include <NoteStore_constants.h>
463+#include <UserStore.h>
464+#include <UserStore_constants.h>
465+#include <Errors_types.h>
466+
467+#include <QDebug>
468+
469+using namespace apache::thrift;
470+using namespace apache::thrift::protocol;
471+using namespace apache::thrift::transport;
472+
473+EvernoteConnection* EvernoteConnection::s_instance = 0;
474+
475+// FIXME: need to populate this string from the system
476+// The structure should be:
477+// application/version; platform/version; [ device/version ]
478+// E.g. "Evernote Windows/3.0.1; Windows/XP SP3"
479+QString EDAM_CLIENT_NAME = QStringLiteral("Reminders/0.1; Ubuntu/13.10");
480+QString EVERNOTE_HOST = QStringLiteral("sandbox.evernote.com");
481+QString EDAM_USER_STORE_PATH = QStringLiteral("/edam/user");
482+QString EDAM_NOTE_STORE_PATH = QStringLiteral("/edam/note");
483+
484+EvernoteConnection::EvernoteConnection(QObject *parent) :
485+ QObject(parent),
486+ m_currentJob(0),
487+ m_useSSL(true)
488+{
489+ setupUserStore();
490+ setupNotesStore();
491+}
492+
493+bool EvernoteConnection::setupUserStore()
494+{
495+ bool versionOK = false;
496+ try {
497+ boost::shared_ptr<TSocket> socket;
498+
499+ if (m_useSSL) {
500+ boost::shared_ptr<TSSLSocketFactory> sslSocketFactory(new TSSLSocketFactory());
501+ socket = sslSocketFactory->createSocket(EVERNOTE_HOST.toStdString(), 443);
502+ qDebug() << "created UserStore SSL socket";
503+ } else {
504+ // Create a non-secure socket
505+ socket = boost::shared_ptr<TSocket> (new TSocket(EVERNOTE_HOST.toStdString(), 80));
506+ qDebug() << "created insecure UserStore socket";
507+ }
508+
509+ boost::shared_ptr<TBufferedTransport> bufferedTransport(new TBufferedTransport(socket));
510+ m_userStoreHttpClient = boost::shared_ptr<THttpClient>(new THttpClient(bufferedTransport,
511+ EVERNOTE_HOST.toStdString(),
512+ EDAM_USER_STORE_PATH.toStdString()));
513+ m_userStoreHttpClient->open();
514+ boost::shared_ptr<TProtocol> iprot(new TBinaryProtocol(m_userStoreHttpClient));
515+ m_userstoreClient = new evernote::edam::UserStoreClient(iprot);
516+ evernote::edam::UserStoreConstants constants;
517+ versionOK = m_userstoreClient->checkVersion(EDAM_CLIENT_NAME.toStdString(),
518+ constants.EDAM_VERSION_MAJOR,
519+ constants.EDAM_VERSION_MINOR);
520+ qDebug() << "UserStoreClient created. Version check:" << versionOK;
521+
522+ } catch (const TTransportException & e) {
523+ qWarning() << "Failed to create Transport for UserStore:" << e.what();
524+ } catch (const TException & e) {
525+ qWarning() << "Generic Thrift exception in UserStore setup:" << e.what();
526+ }
527+ return versionOK;
528+}
529+
530+bool EvernoteConnection::setupNotesStore()
531+{
532+ try {
533+ boost::shared_ptr<TSocket> socket;
534+
535+ if (m_useSSL) {
536+ boost::shared_ptr<TSSLSocketFactory> sslSocketFactory(new TSSLSocketFactory());
537+ socket = sslSocketFactory->createSocket(EVERNOTE_HOST.toStdString(), 443);
538+ qDebug() << "created NotesStore SSL socket";
539+ } else {
540+ // Create a non-secure socket
541+ socket = boost::shared_ptr<TSocket> (new TSocket(EVERNOTE_HOST.toStdString(), 80));
542+ qDebug() << "created insecure NotesStore socket";
543+ }
544+
545+ // setup UserStore
546+ boost::shared_ptr<TBufferedTransport> bufferedTransport(new TBufferedTransport(socket));
547+ m_notesStoreHttpClient = boost::shared_ptr<THttpClient>(new THttpClient(bufferedTransport,
548+ EVERNOTE_HOST.toStdString(),
549+ EDAM_NOTE_STORE_PATH.toStdString()));
550+ m_notesStoreHttpClient->open();
551+ boost::shared_ptr<TProtocol> iprot(new TBinaryProtocol(m_notesStoreHttpClient));
552+
553+ // setup notesstore
554+ m_notesStoreClient = new evernote::edam::NoteStoreClient(iprot);
555+
556+ qDebug() << "NoteStore client created.";
557+
558+ } catch (const TTransportException & e) {
559+ qWarning() << "Failed to create Transport for NotesStore:" << e.what();
560+ return false;
561+ } catch (const TException & e) {
562+ qWarning() << "Generic Thrift exception in NotesStore setup:" << e.what();
563+ return false;
564+ }
565+ return true;
566+}
567+
568+EvernoteConnection *EvernoteConnection::instance()
569+{
570+ if (!s_instance) {
571+ s_instance = new EvernoteConnection();
572+ }
573+ return s_instance;
574+}
575+
576+EvernoteConnection::~EvernoteConnection()
577+{
578+ delete m_notesStoreClient;
579+}
580+
581+QString EvernoteConnection::token() const
582+{
583+ return m_token;
584+}
585+
586+void EvernoteConnection::setToken(const QString &token)
587+{
588+ if (token != m_token) {
589+ m_token = token;
590+ emit tokenChanged();
591+ }
592+}
593+
594+void EvernoteConnection::enqueue(EvernoteJob *job)
595+{
596+ connect(job, &EvernoteJob::finished, this, &EvernoteConnection::startNextJob);
597+
598+ m_jobQueue.append(job);
599+ startJobQueue();
600+}
601+
602+void EvernoteConnection::startJobQueue()
603+{
604+ if (m_jobQueue.isEmpty()) {
605+ return;
606+ }
607+
608+ if (m_currentJob) {
609+ return;
610+ }
611+ m_currentJob = m_jobQueue.takeFirst();
612+ m_currentJob->start();
613+}
614+
615+void EvernoteConnection::startNextJob()
616+{
617+ m_currentJob = 0;
618+ startJobQueue();
619+}
620
621=== added file 'src/plugin/Evernote/evernoteconnection.h'
622--- src/plugin/Evernote/evernoteconnection.h 1970-01-01 00:00:00 +0000
623+++ src/plugin/Evernote/evernoteconnection.h 2013-12-14 00:07:45 +0000
624@@ -0,0 +1,101 @@
625+/*
626+ * Copyright: 2013 Canonical, Ltd
627+ *
628+ * This file is part of reminders-app
629+ *
630+ * reminders-app is free software: you can redistribute it and/or modify
631+ * it under the terms of the GNU General Public License as published by
632+ * the Free Software Foundation; version 3.
633+ *
634+ * reminders-app is distributed in the hope that it will be useful,
635+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
636+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
637+ * GNU General Public License for more details.
638+ *
639+ * You should have received a copy of the GNU General Public License
640+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
641+ *
642+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
643+ */
644+
645+#ifndef EVERNOTECONNECTION_H
646+#define EVERNOTECONNECTION_H
647+
648+#include <boost/shared_ptr.hpp>
649+
650+// Thrift
651+#include <transport/THttpClient.h>
652+
653+#include <QObject>
654+
655+namespace evernote {
656+namespace edam {
657+class NoteStoreClient;
658+class UserStoreClient;
659+}
660+}
661+
662+using namespace apache::thrift::transport;
663+
664+class EvernoteJob;
665+
666+class EvernoteConnection : public QObject
667+{
668+ Q_OBJECT
669+ Q_PROPERTY(QString token READ token WRITE setToken NOTIFY tokenChanged)
670+
671+ friend class NotesStoreJob;
672+ friend class UserStoreJob;
673+
674+public:
675+ enum ErrorCode {
676+ ErrorCodeNoError,
677+ ErrorCodeUserException,
678+ ErrorCodeSystemException,
679+ ErrorCodeNotFoundExcpetion,
680+ ErrorCodeConnectionLost
681+ };
682+
683+ static EvernoteConnection* instance();
684+ ~EvernoteConnection();
685+
686+ QString token() const;
687+ void setToken(const QString &token);
688+
689+ void enqueue(EvernoteJob *job);
690+
691+signals:
692+ void tokenChanged();
693+
694+private slots:
695+ void startJobQueue();
696+ void startNextJob();
697+
698+private:
699+ explicit EvernoteConnection(QObject *parent = 0);
700+ static EvernoteConnection *s_instance;
701+
702+ bool setupUserStore();
703+ bool setupNotesStore();
704+
705+ bool m_useSSL;
706+
707+ QString m_token;
708+
709+ // There must be only one job running at a time
710+ // Do not start jobs other than with startJobQueue()
711+ QList<EvernoteJob*> m_jobQueue;
712+ EvernoteJob *m_currentJob;
713+
714+ // Those 4 are accessed from the job thread.
715+ // Make sure to not access them while any jobs are running
716+ // or we need to mutex them.
717+ evernote::edam::NoteStoreClient *m_notesStoreClient;
718+ boost::shared_ptr<THttpClient> m_notesStoreHttpClient;
719+
720+ evernote::edam::UserStoreClient *m_userstoreClient;
721+ boost::shared_ptr<THttpClient> m_userStoreHttpClient;
722+
723+};
724+
725+#endif // EVERNOTECONNECTION_H
726
727=== modified file 'src/plugin/Evernote/evernoteplugin.cpp'
728--- src/plugin/Evernote/evernoteplugin.cpp 2013-11-26 17:18:33 +0000
729+++ src/plugin/Evernote/evernoteplugin.cpp 2013-12-14 00:07:45 +0000
730@@ -20,6 +20,7 @@
731
732 #include "evernoteplugin.h"
733
734+#include "evernoteconnection.h"
735 #include "userstore.h"
736 #include "notesstore.h"
737 #include "notes.h"
738@@ -28,16 +29,27 @@
739
740 #include <QtQml>
741
742+static QObject* userStoreProvider(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)
743+{
744+ return UserStore::instance();
745+}
746+
747 static QObject* notesStoreProvider(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)
748 {
749 return NotesStore::instance();
750 }
751
752+static QObject* connectionProvider(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)
753+{
754+ return EvernoteConnection::instance();
755+}
756+
757 void FitBitPlugin::registerTypes(const char *uri)
758 {
759- qmlRegisterType<UserStore>("Evernote", 0, 1, "UserStore");
760-
761+ qmlRegisterSingletonType<UserStore>("Evernote", 0, 1, "UserStore", userStoreProvider);
762 qmlRegisterSingletonType<NotesStore>("Evernote", 0, 1, "NotesStore", notesStoreProvider);
763+ qmlRegisterSingletonType<EvernoteConnection>("Evernote", 0, 1, "EvernoteConnection", connectionProvider);
764+
765 qmlRegisterType<Notes>("Evernote", 0, 1, "Notes");
766 qmlRegisterType<Notebooks>("Evernote", 0, 1, "Notebooks");
767 qmlRegisterUncreatableType<Note>("Evernote", 0, 1, "Note", "Cannot create Notes in QML. Use NotesStore.createNote() instead.");
768
769=== added file 'src/plugin/Evernote/jobs/createnotebookjob.cpp'
770--- src/plugin/Evernote/jobs/createnotebookjob.cpp 1970-01-01 00:00:00 +0000
771+++ src/plugin/Evernote/jobs/createnotebookjob.cpp 2013-12-14 00:07:45 +0000
772@@ -0,0 +1,41 @@
773+/*
774+ * Copyright: 2013 Canonical, Ltd
775+ *
776+ * This file is part of reminders-app
777+ *
778+ * reminders-app is free software: you can redistribute it and/or modify
779+ * it under the terms of the GNU General Public License as published by
780+ * the Free Software Foundation; version 3.
781+ *
782+ * reminders-app is distributed in the hope that it will be useful,
783+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
784+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
785+ * GNU General Public License for more details.
786+ *
787+ * You should have received a copy of the GNU General Public License
788+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
789+ *
790+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
791+ */
792+
793+#include "createnotebookjob.h"
794+
795+#include <QDebug>
796+
797+CreateNotebookJob::CreateNotebookJob(const QString &name, QObject *parent) :
798+ NotesStoreJob(parent),
799+ m_name(name)
800+{
801+}
802+
803+void CreateNotebookJob::startJob()
804+{
805+ m_result.name = m_name.toStdString();
806+ m_result.__isset.name = true;
807+ client()->createNotebook(m_result, token().toStdString(), m_result);
808+}
809+
810+void CreateNotebookJob::emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage)
811+{
812+ emit jobDone(errorCode, errorMessage, m_result);
813+}
814
815=== added file 'src/plugin/Evernote/jobs/createnotebookjob.h'
816--- src/plugin/Evernote/jobs/createnotebookjob.h 1970-01-01 00:00:00 +0000
817+++ src/plugin/Evernote/jobs/createnotebookjob.h 2013-12-14 00:07:45 +0000
818@@ -0,0 +1,46 @@
819+/*
820+ * Copyright: 2013 Canonical, Ltd
821+ *
822+ * This file is part of reminders-app
823+ *
824+ * reminders-app is free software: you can redistribute it and/or modify
825+ * it under the terms of the GNU General Public License as published by
826+ * the Free Software Foundation; version 3.
827+ *
828+ * reminders-app is distributed in the hope that it will be useful,
829+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
830+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
831+ * GNU General Public License for more details.
832+ *
833+ * You should have received a copy of the GNU General Public License
834+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
835+ *
836+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
837+ */
838+
839+#ifndef CREATENOTEBOOKJOB_H
840+#define CREATENOTEBOOKJOB_H
841+
842+#include "notesstorejob.h"
843+
844+class CreateNotebookJob : public NotesStoreJob
845+{
846+ Q_OBJECT
847+public:
848+ explicit CreateNotebookJob(const QString &name, QObject *parent = 0);
849+
850+ virtual void startJob() override;
851+
852+signals:
853+ void jobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const evernote::edam::Notebook &result);
854+
855+private slots:
856+ void emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage);
857+
858+private:
859+ QString m_name;
860+
861+ evernote::edam::Notebook m_result;
862+};
863+
864+#endif // CREATENOTEBOOKJOB_H
865
866=== modified file 'src/plugin/Evernote/jobs/createnotejob.cpp'
867--- src/plugin/Evernote/jobs/createnotejob.cpp 2013-11-26 17:18:33 +0000
868+++ src/plugin/Evernote/jobs/createnotejob.cpp 2013-12-14 00:07:45 +0000
869@@ -22,36 +22,30 @@
870
871 #include <QDebug>
872
873-CreateNoteJob::CreateNoteJob(Note *note, QObject *parent) :
874- EvernoteJob(parent),
875- m_note(note)
876-{
877-}
878-
879-void CreateNoteJob::run()
880-{
881- NotesStore::ErrorCode errorCode = NotesStore::ErrorCodeNoError;
882-
883- try {
884- evernote::edam::Note input;
885- input.title = m_note->title().toStdString();
886- input.__isset.title = true;
887- input.notebookGuid = m_note->notebookGuid().toStdString();
888- input.__isset.notebookGuid = true;
889- input.content = m_note->content().toStdString();
890- input.__isset.content = true;
891- input.contentLength = m_note->content().length();
892- input.__isset.contentLength = true;
893-
894- evernote::edam::Note result;
895- client()->createNote(result, token().toStdString(), input);
896-
897- m_note->setGuid(QString::fromStdString(result.guid));
898-
899- } catch(evernote::edam::EDAMUserException e) {
900- errorCode = NotesStore::ErrorCodeUserException;
901- } catch(evernote::edam::EDAMSystemException) {
902- errorCode = NotesStore::ErrorCodeSystemException;
903- }
904- emit resultReady(errorCode, m_note);
905+CreateNoteJob::CreateNoteJob(const QString &title, const QString &notebookGuid, const QString &content, QObject *parent) :
906+ NotesStoreJob(parent),
907+ m_title(title),
908+ m_notebookGuid(notebookGuid),
909+ m_content(content)
910+{
911+}
912+
913+void CreateNoteJob::startJob()
914+{
915+ evernote::edam::Note input;
916+ input.title = m_title.toStdString();
917+ input.__isset.title = true;
918+ input.notebookGuid = m_notebookGuid.toStdString();
919+ input.__isset.notebookGuid = true;
920+ input.content = m_content.toStdString();
921+ input.__isset.content = true;
922+ input.contentLength = m_content.length();
923+ input.__isset.contentLength = true;
924+
925+ client()->createNote(m_resultNote, token().toStdString(), input);
926+}
927+
928+void CreateNoteJob::emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage)
929+{
930+ emit jobDone(errorCode, errorMessage, m_resultNote);
931 }
932
933=== modified file 'src/plugin/Evernote/jobs/createnotejob.h'
934--- src/plugin/Evernote/jobs/createnotejob.h 2013-11-25 00:49:48 +0000
935+++ src/plugin/Evernote/jobs/createnotejob.h 2013-12-14 00:07:45 +0000
936@@ -1,22 +1,27 @@
937 #ifndef CREATENOTEJOB_H
938 #define CREATENOTEJOB_H
939
940-#include "evernotejob.h"
941-#include "note.h"
942+#include "notesstorejob.h"
943
944-class CreateNoteJob : public EvernoteJob
945+class CreateNoteJob : public NotesStoreJob
946 {
947 Q_OBJECT
948 public:
949- explicit CreateNoteJob(Note *note, QObject *parent = 0);
950-
951- void run();
952+ explicit CreateNoteJob(const QString &title, const QString &notebookGuid, const QString &content, QObject *parent = 0);
953
954 signals:
955- void resultReady(NotesStore::ErrorCode errorCode, Note *note);
956+ void jobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, evernote::edam::Note note);
957+
958+protected:
959+ void startJob();
960+ void emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage);
961
962 private:
963- Note *m_note;
964+ QString m_title;
965+ QString m_notebookGuid;
966+ QString m_content;
967+
968+ evernote::edam::Note m_resultNote;
969 };
970
971 #endif // CREATENOTEJOB_H
972
973=== modified file 'src/plugin/Evernote/jobs/deletenotejob.cpp'
974--- src/plugin/Evernote/jobs/deletenotejob.cpp 2013-11-26 17:18:33 +0000
975+++ src/plugin/Evernote/jobs/deletenotejob.cpp 2013-12-14 00:07:45 +0000
976@@ -21,18 +21,17 @@
977 #include "deletenotejob.h"
978
979 DeleteNoteJob::DeleteNoteJob(const QString &guid, QObject *parent):
980- EvernoteJob(parent),
981+ NotesStoreJob(parent),
982 m_guid(guid)
983 {
984 }
985
986-void DeleteNoteJob::run()
987-{
988- NotesStore::ErrorCode errorCode = NotesStore::ErrorCodeNoError;
989- try {
990- client()->deleteNote(token().toStdString(), m_guid.toStdString());
991- } catch(...) {
992- catchTransportException();
993- }
994- emit resultReady(errorCode, m_guid);
995+void DeleteNoteJob::startJob()
996+{
997+ client()->deleteNote(token().toStdString(), m_guid.toStdString());
998+}
999+
1000+void DeleteNoteJob::emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage)
1001+{
1002+ emit jobDone(errorCode, errorMessage, m_guid);
1003 }
1004
1005=== modified file 'src/plugin/Evernote/jobs/deletenotejob.h'
1006--- src/plugin/Evernote/jobs/deletenotejob.h 2013-11-25 00:49:48 +0000
1007+++ src/plugin/Evernote/jobs/deletenotejob.h 2013-12-14 00:07:45 +0000
1008@@ -1,18 +1,20 @@
1009 #ifndef DELETENOTEJOB_H
1010 #define DELETENOTEJOB_H
1011
1012-#include "evernotejob.h"
1013+#include "notesstorejob.h"
1014
1015-class DeleteNoteJob : public EvernoteJob
1016+class DeleteNoteJob : public NotesStoreJob
1017 {
1018 Q_OBJECT
1019 public:
1020 DeleteNoteJob(const QString &guid, QObject *parent = 0);
1021
1022- void run();
1023-
1024 signals:
1025- void resultReady(NotesStore::ErrorCode errorCode, const QString &guid);
1026+ void jobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const QString &guid);
1027+
1028+protected:
1029+ void startJob();
1030+ void emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage);
1031
1032 private:
1033 QString m_guid;
1034
1035=== modified file 'src/plugin/Evernote/jobs/evernotejob.cpp'
1036--- src/plugin/Evernote/jobs/evernotejob.cpp 2013-11-26 17:18:33 +0000
1037+++ src/plugin/Evernote/jobs/evernotejob.cpp 2013-12-14 00:07:45 +0000
1038@@ -19,6 +19,7 @@
1039 */
1040
1041 #include "evernotejob.h"
1042+#include "evernoteconnection.h"
1043
1044 // Thrift
1045 #include <arpa/inet.h> // seems thrift forgot this one
1046@@ -35,35 +36,67 @@
1047
1048 EvernoteJob::EvernoteJob(QObject *parent) :
1049 QThread(parent),
1050- m_token(NotesStore::instance()->token())
1051+ m_token(EvernoteConnection::instance()->token())
1052 {
1053 connect(this, &EvernoteJob::finished, this, &EvernoteJob::deleteLater);
1054 }
1055
1056 EvernoteJob::~EvernoteJob()
1057 {
1058-
1059 }
1060
1061-evernote::edam::NoteStoreClient *EvernoteJob::client()
1062+void EvernoteJob::run()
1063 {
1064- return NotesStore::instance()->m_client;
1065+ if (m_token.isEmpty()) {
1066+ qWarning() << "No token set. Cannot execute job. (" << this->metaObject()->className() << ")";
1067+ emitJobDone(EvernoteConnection::ErrorCodeUserException, QStringLiteral("No token set."));
1068+ return;
1069+ }
1070+
1071+ try {
1072+ startJob();
1073+ } catch (const TTransportException & e) {
1074+
1075+ // The connection broke down. libthrift + evernote servers seem to be quite flaky
1076+ // so lets try to start the job once more.
1077+ qWarning() << "Got a transport exception:" << e.what() << ". Trying to reestablish connection...";
1078+ try {
1079+ resetConnection();
1080+ startJob();
1081+ } catch (const TTransportException &e) {
1082+ // Giving up... the connection seems to be down for real.
1083+ qWarning() << "Cannot reestablish connection:" << e.what();
1084+ emitJobDone(EvernoteConnection::ErrorCodeConnectionLost, e.what());
1085+ } catch (const TApplicationException &e) {
1086+ qWarning() << "Cannot reestablish connection:" << e.what();
1087+ emitJobDone(EvernoteConnection::ErrorCodeConnectionLost, e.what());
1088+ } catch (const evernote::edam::EDAMUserException &e) {
1089+ qWarning() << "EDAMUserException" << e.what();
1090+ emitJobDone(EvernoteConnection::ErrorCodeUserException, e.what());
1091+ } catch (const evernote::edam::EDAMSystemException &e) {
1092+ qWarning() << "EDAMSystemException" << e.what();
1093+ emitJobDone(EvernoteConnection::ErrorCodeSystemException, e.what());
1094+ } catch (const evernote::edam::EDAMNotFoundException &e) {
1095+ qWarning() << "EDAMNotFoundException" << e.what();
1096+ emitJobDone(EvernoteConnection::ErrorCodeNotFoundExcpetion, e.what());
1097+ }
1098+
1099+
1100+ } catch (const evernote::edam::EDAMUserException &e) {
1101+ qWarning() << "EDAMUserException" << e.what();
1102+ emitJobDone(EvernoteConnection::ErrorCodeUserException, e.what());
1103+ } catch (const evernote::edam::EDAMSystemException &e) {
1104+ qWarning() << "EDAMSystemException" << e.what();
1105+ emitJobDone(EvernoteConnection::ErrorCodeSystemException, e.what());
1106+ } catch (const evernote::edam::EDAMNotFoundException &e) {
1107+ qWarning() << "EDAMNotFoundException" << e.what();
1108+ emitJobDone(EvernoteConnection::ErrorCodeNotFoundExcpetion, e.what());
1109+ }
1110+
1111+ emitJobDone(EvernoteConnection::ErrorCodeNoError, QString());
1112 }
1113
1114 QString EvernoteJob::token()
1115 {
1116 return m_token;
1117 }
1118-
1119-void EvernoteJob::catchTransportException()
1120-{
1121- try {
1122- // this function is meant to be called from a catch block
1123- // rethrow the exception to catch it again
1124- throw;
1125- } catch (const TTransportException & e) {
1126- qDebug() << e.what();
1127- } catch (const TException & e) {
1128- qDebug() << e.what();
1129- }
1130-}
1131
1132=== modified file 'src/plugin/Evernote/jobs/evernotejob.h'
1133--- src/plugin/Evernote/jobs/evernotejob.h 2013-11-25 00:49:48 +0000
1134+++ src/plugin/Evernote/jobs/evernotejob.h 2013-12-14 00:07:45 +0000
1135@@ -3,13 +3,21 @@
1136
1137 #include "notesstore.h"
1138
1139-// Evernote SDK
1140-#include <NoteStore.h>
1141-#include <NoteStore_constants.h>
1142-#include <Errors_types.h>
1143-
1144 #include <QThread>
1145
1146+/* How to create a new Job type:
1147+ * - Subclass EvernoteJob
1148+ * - Implement startJob() in which you do the call to evernote.
1149+ * - No need to catch exceptions, EvernoteJob will deal with those.
1150+ * - Define a jobDone() signal with the result parameters you need.
1151+ * - Keep the convention of jobDone(EvernoteConnection::ErrorCode errorCode, const QString &message [, ...])
1152+ * - Emit jobDone() in your implementation of emitJobDone().
1153+ * - NOTE: emitJobDone() might be called with an error even before startJob() is triggered.
1154+ *
1155+ * Jobs can be enqueue()d in NotesStore.
1156+ * They will destroy themselves when finished.
1157+ * The jobqueue will take care about starting them.
1158+ */
1159 class EvernoteJob : public QThread
1160 {
1161 Q_OBJECT
1162@@ -17,12 +25,18 @@
1163 explicit EvernoteJob(QObject *parent = 0);
1164 virtual ~EvernoteJob();
1165
1166+ void run() final;
1167+
1168+signals:
1169+ void connectionLost(const QString &errorMessage);
1170+
1171 protected:
1172- evernote::edam::NoteStoreClient* client();
1173+ virtual void resetConnection() = 0;
1174+ virtual void startJob() = 0;
1175+ virtual void emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage) = 0;
1176+
1177 QString token();
1178
1179- void catchTransportException();
1180-
1181 private:
1182 QString m_token;
1183 };
1184
1185=== added file 'src/plugin/Evernote/jobs/expungenotebookjob.cpp'
1186--- src/plugin/Evernote/jobs/expungenotebookjob.cpp 1970-01-01 00:00:00 +0000
1187+++ src/plugin/Evernote/jobs/expungenotebookjob.cpp 2013-12-14 00:07:45 +0000
1188@@ -0,0 +1,39 @@
1189+/*
1190+ * Copyright: 2013 Canonical, Ltd
1191+ *
1192+ * This file is part of reminders-app
1193+ *
1194+ * reminders-app is free software: you can redistribute it and/or modify
1195+ * it under the terms of the GNU General Public License as published by
1196+ * the Free Software Foundation; version 3.
1197+ *
1198+ * reminders-app is distributed in the hope that it will be useful,
1199+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1200+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1201+ * GNU General Public License for more details.
1202+ *
1203+ * You should have received a copy of the GNU General Public License
1204+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1205+ *
1206+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
1207+ */
1208+
1209+#include "expungenotebookjob.h"
1210+
1211+#include <QDebug>
1212+
1213+ExpungeNotebookJob::ExpungeNotebookJob(const QString &guid, QObject *parent) :
1214+ NotesStoreJob(parent),
1215+ m_guid(guid)
1216+{
1217+}
1218+
1219+void ExpungeNotebookJob::startJob()
1220+{
1221+ client()->expungeNotebook(token().toStdString(), m_guid.toStdString());
1222+}
1223+
1224+void ExpungeNotebookJob::emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage)
1225+{
1226+ emit jobDone(errorCode, errorMessage, m_guid);
1227+}
1228
1229=== added file 'src/plugin/Evernote/jobs/expungenotebookjob.h'
1230--- src/plugin/Evernote/jobs/expungenotebookjob.h 1970-01-01 00:00:00 +0000
1231+++ src/plugin/Evernote/jobs/expungenotebookjob.h 2013-12-14 00:07:45 +0000
1232@@ -0,0 +1,43 @@
1233+/*
1234+ * Copyright: 2013 Canonical, Ltd
1235+ *
1236+ * This file is part of reminders-app
1237+ *
1238+ * reminders-app is free software: you can redistribute it and/or modify
1239+ * it under the terms of the GNU General Public License as published by
1240+ * the Free Software Foundation; version 3.
1241+ *
1242+ * reminders-app is distributed in the hope that it will be useful,
1243+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1244+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1245+ * GNU General Public License for more details.
1246+ *
1247+ * You should have received a copy of the GNU General Public License
1248+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1249+ *
1250+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
1251+ */
1252+
1253+#ifndef DELETENOTEBOOKJOB_H
1254+#define DELETENOTEBOOKJOB_H
1255+
1256+#include "notesstorejob.h"
1257+
1258+class ExpungeNotebookJob : public NotesStoreJob
1259+{
1260+ Q_OBJECT
1261+public:
1262+ explicit ExpungeNotebookJob(const QString &guid, QObject *parent = 0);
1263+
1264+signals:
1265+ void jobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const QString &guid);
1266+
1267+private slots:
1268+ void startJob();
1269+ void emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage);
1270+
1271+private:
1272+ QString m_guid;
1273+};
1274+
1275+#endif // DELETENOTEBOOKJOB_H
1276
1277=== modified file 'src/plugin/Evernote/jobs/fetchnotebooksjob.cpp'
1278--- src/plugin/Evernote/jobs/fetchnotebooksjob.cpp 2013-11-26 17:18:33 +0000
1279+++ src/plugin/Evernote/jobs/fetchnotebooksjob.cpp 2013-12-14 00:07:45 +0000
1280@@ -23,21 +23,17 @@
1281 #include <QDebug>
1282
1283 FetchNotebooksJob::FetchNotebooksJob(QObject *parent) :
1284- EvernoteJob(parent)
1285-{
1286-}
1287-
1288-
1289-void FetchNotebooksJob::run()
1290-{
1291- NotesStore::ErrorCode errorCode = NotesStore::ErrorCodeNoError;
1292- std::vector<evernote::edam::Notebook> results;
1293- try {
1294- client()->listNotebooks(results, token().toStdString());
1295- } catch(evernote::edam::EDAMUserException) {
1296- errorCode = NotesStore::ErrorCodeUserException;
1297- } catch(evernote::edam::EDAMSystemException) {
1298- errorCode = NotesStore::ErrorCodeSystemException;
1299- }
1300- emit resultReady(errorCode, results);
1301+ NotesStoreJob(parent)
1302+{
1303+}
1304+
1305+
1306+void FetchNotebooksJob::startJob()
1307+{
1308+ client()->listNotebooks(m_results, token().toStdString());
1309+}
1310+
1311+void FetchNotebooksJob::emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage)
1312+{
1313+ emit jobDone(errorCode, errorMessage, m_results);
1314 }
1315
1316=== modified file 'src/plugin/Evernote/jobs/fetchnotebooksjob.h'
1317--- src/plugin/Evernote/jobs/fetchnotebooksjob.h 2013-11-25 00:49:48 +0000
1318+++ src/plugin/Evernote/jobs/fetchnotebooksjob.h 2013-12-14 00:07:45 +0000
1319@@ -1,18 +1,23 @@
1320 #ifndef FETCHNOTEBOOKSJOB_H
1321 #define FETCHNOTEBOOKSJOB_H
1322
1323-#include "evernotejob.h"
1324+#include "notesstorejob.h"
1325
1326-class FetchNotebooksJob : public EvernoteJob
1327+class FetchNotebooksJob : public NotesStoreJob
1328 {
1329 Q_OBJECT
1330 public:
1331 explicit FetchNotebooksJob(QObject *parent = 0);
1332
1333- void run();
1334-
1335 signals:
1336- void resultReady(NotesStore::ErrorCode errorCode, const std::vector<evernote::edam::Notebook> &results);
1337+ void jobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const std::vector<evernote::edam::Notebook> &results);
1338+
1339+protected:
1340+ void startJob();
1341+ void emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage);
1342+
1343+private:
1344+ std::vector<evernote::edam::Notebook> m_results;
1345 };
1346
1347 #endif // FETCHNOTEBOOKSJOB_H
1348
1349=== modified file 'src/plugin/Evernote/jobs/fetchnotejob.cpp'
1350--- src/plugin/Evernote/jobs/fetchnotejob.cpp 2013-11-26 17:18:33 +0000
1351+++ src/plugin/Evernote/jobs/fetchnotejob.cpp 2013-12-14 00:07:45 +0000
1352@@ -21,27 +21,17 @@
1353 #include "fetchnotejob.h"
1354
1355 FetchNoteJob::FetchNoteJob(const QString &guid, QObject *parent) :
1356- EvernoteJob(parent),
1357+ NotesStoreJob(parent),
1358 m_guid(guid)
1359 {
1360 }
1361
1362-void FetchNoteJob::run()
1363+void FetchNoteJob::startJob()
1364 {
1365- NotesStore::ErrorCode errorCode = NotesStore::ErrorCodeNoError;
1366- evernote::edam::Note result;
1367- try {
1368- client()->getNote(result, token().toStdString(), m_guid.toStdString(), true, true, false, false);
1369- } catch (evernote::edam::EDAMUserException) {
1370- errorCode = NotesStore::ErrorCodeUserException;
1371- } catch (evernote::edam::EDAMSystemException) {
1372- errorCode = NotesStore::ErrorCodeSystemException;
1373- } catch (evernote::edam::EDAMNotFoundException) {
1374- errorCode = NotesStore::ErrorCodeNotFoundExcpetion;
1375- } catch (...) {
1376- catchTransportException();
1377- errorCode = NotesStore::ErrorCodeConnectionLost;
1378- }
1379+ client()->getNote(m_result, token().toStdString(), m_guid.toStdString(), true, false, false, false);
1380+}
1381
1382- emit resultReady(errorCode, result);
1383+void FetchNoteJob::emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage)
1384+{
1385+ emit resultReady(errorCode, errorMessage, m_result);
1386 }
1387
1388=== modified file 'src/plugin/Evernote/jobs/fetchnotejob.h'
1389--- src/plugin/Evernote/jobs/fetchnotejob.h 2013-11-25 00:49:48 +0000
1390+++ src/plugin/Evernote/jobs/fetchnotejob.h 2013-12-14 00:07:45 +0000
1391@@ -1,22 +1,28 @@
1392 #ifndef FETCHNOTEJOB_H
1393 #define FETCHNOTEJOB_H
1394
1395-#include "evernotejob.h"
1396+#include "notesstorejob.h"
1397
1398-class FetchNoteJob : public EvernoteJob
1399+class FetchNoteJob : public NotesStoreJob
1400 {
1401 Q_OBJECT
1402 public:
1403 explicit FetchNoteJob(const QString &guid, QObject *parent = 0);
1404
1405- void run();
1406 signals:
1407- void resultReady(NotesStore::ErrorCode error, const evernote::edam::Note &note);
1408+ void resultReady(EvernoteConnection::ErrorCode error, const QString &errorMessage, const evernote::edam::Note &note);
1409+
1410+protected:
1411+ void startJob();
1412+ void emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage);
1413
1414 private:
1415 evernote::edam::NoteStoreClient *m_client;
1416 QString m_token;
1417 QString m_guid;
1418+
1419+ evernote::edam::Note m_result;
1420+
1421 };
1422
1423 #endif // FETCHNOTEJOB_H
1424
1425=== modified file 'src/plugin/Evernote/jobs/fetchnotesjob.cpp'
1426--- src/plugin/Evernote/jobs/fetchnotesjob.cpp 2013-11-26 17:18:33 +0000
1427+++ src/plugin/Evernote/jobs/fetchnotesjob.cpp 2013-12-14 00:07:45 +0000
1428@@ -22,43 +22,52 @@
1429
1430 #include "notesstore.h"
1431
1432+// evernote sdk
1433+#include "Limits_constants.h"
1434+
1435 #include <QDebug>
1436
1437-FetchNotesJob::FetchNotesJob( const QString &filterNotebookGuid, QObject *parent) :
1438- EvernoteJob(parent),
1439- m_filterNotebookGuid(filterNotebookGuid)
1440+FetchNotesJob::FetchNotesJob(const QString &filterNotebookGuid, const QString &searchWords, QObject *parent) :
1441+ NotesStoreJob(parent),
1442+ m_filterNotebookGuid(filterNotebookGuid),
1443+ m_searchWords(searchWords)
1444 {
1445 }
1446
1447-void FetchNotesJob::run()
1448+void FetchNotesJob::startJob()
1449 {
1450 // TODO: fix start/end (use smaller chunks and continue fetching if there are more notes available)
1451 int32_t start = 0;
1452- int32_t end = 10000;
1453+ evernote::limits::LimitsConstants limits;
1454+ int32_t end = limits.EDAM_USER_NOTES_MAX;
1455
1456 // Prepare filter
1457 evernote::edam::NoteFilter filter;
1458 filter.notebookGuid = m_filterNotebookGuid.toStdString();
1459 filter.__isset.notebookGuid = !m_filterNotebookGuid.isEmpty();
1460
1461+ filter.words = m_searchWords.toStdString();
1462+ filter.__isset.words = !m_searchWords.isEmpty();
1463+
1464 // Prepare ResultSpec
1465 evernote::edam::NotesMetadataResultSpec resultSpec;
1466+
1467 resultSpec.includeNotebookGuid = true;
1468 resultSpec.__isset.includeNotebookGuid = true;
1469+
1470+ resultSpec.includeCreated = true;
1471+ resultSpec.__isset.includeCreated = true;
1472+
1473 resultSpec.includeTitle = true;
1474 resultSpec.__isset.includeTitle = true;
1475
1476- NotesStore::ErrorCode errorCode = NotesStore::ErrorCodeNoError;
1477- evernote::edam::NotesMetadataList results;
1478-
1479- try {
1480- client()->findNotesMetadata(results, token().toStdString(), filter, start, end, resultSpec);
1481- } catch(evernote::edam::EDAMUserException) {
1482- errorCode = NotesStore::ErrorCodeUserException;
1483- } catch(evernote::edam::EDAMSystemException) {
1484- errorCode = NotesStore::ErrorCodeSystemException;
1485- } catch(evernote::edam::EDAMNotFoundException) {
1486- errorCode = NotesStore::ErrorCodeNotFoundExcpetion;
1487- }
1488- emit resultReady(errorCode, results);
1489+ resultSpec.includeAttributes = true;
1490+ resultSpec.__isset.includeAttributes = true;
1491+
1492+ client()->findNotesMetadata(m_results, token().toStdString(), filter, start, end, resultSpec);
1493+}
1494+
1495+void FetchNotesJob::emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage)
1496+{
1497+ emit jobDone(errorCode, errorMessage, m_results);
1498 }
1499
1500=== modified file 'src/plugin/Evernote/jobs/fetchnotesjob.h'
1501--- src/plugin/Evernote/jobs/fetchnotesjob.h 2013-11-25 00:49:48 +0000
1502+++ src/plugin/Evernote/jobs/fetchnotesjob.h 2013-12-14 00:07:45 +0000
1503@@ -1,21 +1,25 @@
1504 #ifndef FETCHNOTESJOB_H
1505 #define FETCHNOTESJOB_H
1506
1507-#include "evernotejob.h"
1508+#include "notesstorejob.h"
1509
1510-class FetchNotesJob : public EvernoteJob
1511+class FetchNotesJob : public NotesStoreJob
1512 {
1513 Q_OBJECT
1514 public:
1515- explicit FetchNotesJob(const QString &filterNotebookGuid, QObject *parent = 0);
1516-
1517- void run();
1518+ explicit FetchNotesJob(const QString &filterNotebookGuid = QString(), const QString &searchWords = QString(), QObject *parent = 0);
1519
1520 signals:
1521- void resultReady(NotesStore::ErrorCode errorCode, const evernote::edam::NotesMetadataList &results);
1522+ void jobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const evernote::edam::NotesMetadataList &results);
1523+
1524+protected:
1525+ void startJob();
1526+ void emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage);
1527
1528 private:
1529 QString m_filterNotebookGuid;
1530+ QString m_searchWords;
1531+ evernote::edam::NotesMetadataList m_results;
1532 };
1533
1534 #endif // FETCHNOTESJOB_H
1535
1536=== added file 'src/plugin/Evernote/jobs/fetchusernamejob.cpp'
1537--- src/plugin/Evernote/jobs/fetchusernamejob.cpp 1970-01-01 00:00:00 +0000
1538+++ src/plugin/Evernote/jobs/fetchusernamejob.cpp 2013-12-14 00:07:45 +0000
1539@@ -0,0 +1,38 @@
1540+/*
1541+ * Copyright: 2013 Canonical, Ltd
1542+ *
1543+ * This file is part of reminders-app
1544+ *
1545+ * reminders-app is free software: you can redistribute it and/or modify
1546+ * it under the terms of the GNU General Public License as published by
1547+ * the Free Software Foundation; version 3.
1548+ *
1549+ * reminders-app is distributed in the hope that it will be useful,
1550+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1551+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1552+ * GNU General Public License for more details.
1553+ *
1554+ * You should have received a copy of the GNU General Public License
1555+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1556+ *
1557+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
1558+ */
1559+
1560+#include "fetchusernamejob.h"
1561+
1562+FetchUsernameJob::FetchUsernameJob(QObject *parent) :
1563+ UserStoreJob(parent)
1564+{
1565+}
1566+
1567+void FetchUsernameJob::startJob()
1568+{
1569+ evernote::edam::User user;
1570+ client()->getUser(user, token().toStdString());
1571+ m_result = QString::fromStdString(user.username);
1572+}
1573+
1574+void FetchUsernameJob::emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage)
1575+{
1576+ emit jobDone(errorCode, errorMessage, m_result);
1577+}
1578
1579=== added file 'src/plugin/Evernote/jobs/fetchusernamejob.h'
1580--- src/plugin/Evernote/jobs/fetchusernamejob.h 1970-01-01 00:00:00 +0000
1581+++ src/plugin/Evernote/jobs/fetchusernamejob.h 2013-12-14 00:07:45 +0000
1582@@ -0,0 +1,43 @@
1583+/*
1584+ * Copyright: 2013 Canonical, Ltd
1585+ *
1586+ * This file is part of reminders-app
1587+ *
1588+ * reminders-app is free software: you can redistribute it and/or modify
1589+ * it under the terms of the GNU General Public License as published by
1590+ * the Free Software Foundation; version 3.
1591+ *
1592+ * reminders-app is distributed in the hope that it will be useful,
1593+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1594+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1595+ * GNU General Public License for more details.
1596+ *
1597+ * You should have received a copy of the GNU General Public License
1598+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1599+ *
1600+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
1601+ */
1602+
1603+#ifndef FETCHUSERNAMEJOB_H
1604+#define FETCHUSERNAMEJOB_H
1605+
1606+#include "userstorejob.h"
1607+
1608+class FetchUsernameJob : public UserStoreJob
1609+{
1610+ Q_OBJECT
1611+public:
1612+ explicit FetchUsernameJob(QObject *parent = 0);
1613+
1614+signals:
1615+ void jobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const QString &result);
1616+
1617+protected:
1618+ void startJob();
1619+ void emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage);
1620+
1621+private:
1622+ QString m_result;
1623+};
1624+
1625+#endif // FETCHUSERNAMEJOB_H
1626
1627=== added file 'src/plugin/Evernote/jobs/notesstorejob.cpp'
1628--- src/plugin/Evernote/jobs/notesstorejob.cpp 1970-01-01 00:00:00 +0000
1629+++ src/plugin/Evernote/jobs/notesstorejob.cpp 2013-12-14 00:07:45 +0000
1630@@ -0,0 +1,39 @@
1631+/*
1632+ * Copyright: 2013 Canonical, Ltd
1633+ *
1634+ * This file is part of reminders-app
1635+ *
1636+ * reminders-app is free software: you can redistribute it and/or modify
1637+ * it under the terms of the GNU General Public License as published by
1638+ * the Free Software Foundation; version 3.
1639+ *
1640+ * reminders-app is distributed in the hope that it will be useful,
1641+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1642+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1643+ * GNU General Public License for more details.
1644+ *
1645+ * You should have received a copy of the GNU General Public License
1646+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1647+ *
1648+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
1649+ */
1650+
1651+#include "notesstorejob.h"
1652+
1653+#include "evernoteconnection.h"
1654+
1655+NotesStoreJob::NotesStoreJob(QObject *parent) :
1656+ EvernoteJob(parent)
1657+{
1658+}
1659+
1660+void NotesStoreJob::resetConnection()
1661+{
1662+ EvernoteConnection::instance()->m_notesStoreHttpClient->close();
1663+ EvernoteConnection::instance()->m_notesStoreHttpClient->open();
1664+}
1665+
1666+evernote::edam::NoteStoreClient *NotesStoreJob::client() const
1667+{
1668+ return EvernoteConnection::instance()->m_notesStoreClient;
1669+}
1670
1671=== added file 'src/plugin/Evernote/jobs/notesstorejob.h'
1672--- src/plugin/Evernote/jobs/notesstorejob.h 1970-01-01 00:00:00 +0000
1673+++ src/plugin/Evernote/jobs/notesstorejob.h 2013-12-14 00:07:45 +0000
1674@@ -0,0 +1,44 @@
1675+/*
1676+ * Copyright: 2013 Canonical, Ltd
1677+ *
1678+ * This file is part of reminders-app
1679+ *
1680+ * reminders-app is free software: you can redistribute it and/or modify
1681+ * it under the terms of the GNU General Public License as published by
1682+ * the Free Software Foundation; version 3.
1683+ *
1684+ * reminders-app is distributed in the hope that it will be useful,
1685+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1686+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1687+ * GNU General Public License for more details.
1688+ *
1689+ * You should have received a copy of the GNU General Public License
1690+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1691+ *
1692+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
1693+ */
1694+
1695+#ifndef NOTESSTOREJOB_H
1696+#define NOTESSTOREJOB_H
1697+
1698+#include "evernotejob.h"
1699+
1700+// Evernote SDK
1701+#include <NoteStore.h>
1702+#include <NoteStore_constants.h>
1703+#include <Errors_types.h>
1704+
1705+class NotesStoreJob : public EvernoteJob
1706+{
1707+ Q_OBJECT
1708+public:
1709+ explicit NotesStoreJob(QObject *parent = 0);
1710+
1711+protected:
1712+ void resetConnection() final;
1713+
1714+ evernote::edam::NoteStoreClient *client() const;
1715+
1716+};
1717+
1718+#endif // NOTESSTOREJOB_H
1719
1720=== modified file 'src/plugin/Evernote/jobs/savenotejob.cpp'
1721--- src/plugin/Evernote/jobs/savenotejob.cpp 2013-11-26 17:18:33 +0000
1722+++ src/plugin/Evernote/jobs/savenotejob.cpp 2013-12-14 00:07:45 +0000
1723@@ -24,37 +24,40 @@
1724 #include <QDebug>
1725
1726 SaveNoteJob::SaveNoteJob(Note *note, QObject *parent) :
1727- EvernoteJob(parent),
1728- m_note(note)
1729-{
1730-}
1731-
1732-void SaveNoteJob::run()
1733-{
1734- NotesStore::ErrorCode errorCode = NotesStore::ErrorCodeNoError;
1735- try {
1736- evernote::edam::Note note;
1737- note.guid = m_note->guid().toStdString();
1738- note.__isset.guid = true;
1739- note.title = m_note->title().toStdString();
1740- note.__isset.title = true;
1741- note.notebookGuid = m_note->notebookGuid().toStdString();
1742- note.__isset.notebookGuid = true;
1743- note.content = m_note->content().toStdString();
1744- note.__isset.content = true;
1745- note.contentLength = m_note->content().length();
1746-
1747- client()->updateNote(note, token().toStdString(), note);
1748-
1749- } catch (evernote::edam::EDAMUserException e) {
1750- errorCode = NotesStore::ErrorCodeUserException;
1751- qDebug() << QString::fromStdString(e.parameter);
1752- } catch (evernote::edam::EDAMSystemException) {
1753- errorCode = NotesStore::ErrorCodeSystemException;
1754- } catch (...) {
1755- catchTransportException();
1756- errorCode = NotesStore::ErrorCodeConnectionLost;
1757- }
1758-
1759- emit resultReady(errorCode, m_note);
1760+ NotesStoreJob(parent)
1761+{
1762+ // Need to clone it. As startJob() will run in another thread we can't access the real note from there.
1763+ m_note = note->clone();
1764+
1765+ // Make sure we delete the clone when done
1766+ m_note->setParent(this);
1767+}
1768+
1769+void SaveNoteJob::startJob()
1770+{
1771+ evernote::edam::Note note;
1772+ note.guid = m_note->guid().toStdString();
1773+ note.__isset.guid = true;
1774+ note.title = m_note->title().toStdString();
1775+ note.__isset.title = true;
1776+ note.notebookGuid = m_note->notebookGuid().toStdString();
1777+ note.__isset.notebookGuid = true;
1778+ note.content = m_note->content().toStdString();
1779+ note.__isset.content = true;
1780+ note.contentLength = m_note->content().length();
1781+
1782+ note.__isset.attributes = true;
1783+ note.attributes.reminderOrder = m_note->reminderOrder();
1784+ note.attributes.__isset.reminderOrder = true;
1785+ note.attributes.reminderTime = m_note->reminderTime().toMSecsSinceEpoch();
1786+ note.attributes.__isset.reminderTime = true;
1787+ note.attributes.reminderDoneTime = m_note->reminderDoneTime().toMSecsSinceEpoch();
1788+ note.attributes.__isset.reminderDoneTime = true;
1789+
1790+ client()->updateNote(m_resultNote, token().toStdString(), note);
1791+}
1792+
1793+void SaveNoteJob::emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage)
1794+{
1795+ emit jobDone(errorCode, errorMessage, m_resultNote);
1796 }
1797
1798=== modified file 'src/plugin/Evernote/jobs/savenotejob.h'
1799--- src/plugin/Evernote/jobs/savenotejob.h 2013-11-25 00:49:48 +0000
1800+++ src/plugin/Evernote/jobs/savenotejob.h 2013-12-14 00:07:45 +0000
1801@@ -1,20 +1,24 @@
1802 #ifndef SAVENOTEJOB_H
1803 #define SAVENOTEJOB_H
1804
1805-#include "evernotejob.h"
1806+#include "notesstorejob.h"
1807
1808-class SaveNoteJob : public EvernoteJob
1809+class SaveNoteJob : public NotesStoreJob
1810 {
1811 Q_OBJECT
1812 public:
1813 explicit SaveNoteJob(Note *note, QObject *parent = 0);
1814
1815- void run();
1816 signals:
1817- void resultReady(NotesStore::ErrorCode errorCode, Note *note);
1818+ void jobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const evernote::edam::Note &note);
1819+
1820+protected:
1821+ void startJob();
1822+ void emitJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage);
1823
1824 private:
1825- Note *m_note;
1826+ Note* m_note;
1827+ evernote::edam::Note m_resultNote;
1828 };
1829
1830 #endif // SAVENOTEJOB_H
1831
1832=== added file 'src/plugin/Evernote/jobs/userstorejob.cpp'
1833--- src/plugin/Evernote/jobs/userstorejob.cpp 1970-01-01 00:00:00 +0000
1834+++ src/plugin/Evernote/jobs/userstorejob.cpp 2013-12-14 00:07:45 +0000
1835@@ -0,0 +1,39 @@
1836+/*
1837+ * Copyright: 2013 Canonical, Ltd
1838+ *
1839+ * This file is part of reminders-app
1840+ *
1841+ * reminders-app is free software: you can redistribute it and/or modify
1842+ * it under the terms of the GNU General Public License as published by
1843+ * the Free Software Foundation; version 3.
1844+ *
1845+ * reminders-app is distributed in the hope that it will be useful,
1846+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1847+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1848+ * GNU General Public License for more details.
1849+ *
1850+ * You should have received a copy of the GNU General Public License
1851+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1852+ *
1853+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
1854+ */
1855+
1856+#include "userstorejob.h"
1857+
1858+#include "evernoteconnection.h"
1859+
1860+UserStoreJob::UserStoreJob(QObject *parent) :
1861+ EvernoteJob(parent)
1862+{
1863+}
1864+
1865+void UserStoreJob::resetConnection()
1866+{
1867+ EvernoteConnection::instance()->m_userStoreHttpClient->close();
1868+ EvernoteConnection::instance()->m_userStoreHttpClient->open();
1869+}
1870+
1871+evernote::edam::UserStoreClient *UserStoreJob::client() const
1872+{
1873+ return EvernoteConnection::instance()->m_userstoreClient;
1874+}
1875
1876=== added file 'src/plugin/Evernote/jobs/userstorejob.h'
1877--- src/plugin/Evernote/jobs/userstorejob.h 1970-01-01 00:00:00 +0000
1878+++ src/plugin/Evernote/jobs/userstorejob.h 2013-12-14 00:07:45 +0000
1879@@ -0,0 +1,46 @@
1880+/*
1881+ * Copyright: 2013 Canonical, Ltd
1882+ *
1883+ * This file is part of reminders-app
1884+ *
1885+ * reminders-app is free software: you can redistribute it and/or modify
1886+ * it under the terms of the GNU General Public License as published by
1887+ * the Free Software Foundation; version 3.
1888+ *
1889+ * reminders-app is distributed in the hope that it will be useful,
1890+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1891+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1892+ * GNU General Public License for more details.
1893+ *
1894+ * You should have received a copy of the GNU General Public License
1895+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1896+ *
1897+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
1898+ */
1899+
1900+#ifndef USERSTOREJOB_H
1901+#define USERSTOREJOB_H
1902+
1903+#include "evernotejob.h"
1904+
1905+// Evernote SDK
1906+#include <UserStore.h>
1907+#include <UserStore_constants.h>
1908+#include <Errors_types.h>
1909+
1910+class UserStoreJob : public EvernoteJob
1911+{
1912+ Q_OBJECT
1913+public:
1914+ explicit UserStoreJob(QObject *parent = 0);
1915+
1916+protected:
1917+ void resetConnection() final;
1918+
1919+ evernote::edam::UserStoreClient* client() const;
1920+
1921+public slots:
1922+
1923+};
1924+
1925+#endif // USERSTOREJOB_H
1926
1927=== modified file 'src/plugin/Evernote/note.cpp'
1928--- src/plugin/Evernote/note.cpp 2013-11-26 17:18:33 +0000
1929+++ src/plugin/Evernote/note.cpp 2013-12-14 00:07:45 +0000
1930@@ -21,10 +21,16 @@
1931 #include "note.h"
1932
1933 #include "notesstore.h"
1934-
1935-Note::Note(const QString &guid, QObject *parent) :
1936+#include "utils/html2enmlconverter.h"
1937+
1938+#include <QDateTime>
1939+#include <QDebug>
1940+
1941+Note::Note(const QString &guid, const QDateTime &created, QObject *parent) :
1942 QObject(parent),
1943- m_guid(guid)
1944+ m_guid(guid),
1945+ m_created(created),
1946+ m_isSearchResult(false)
1947 {
1948 }
1949
1950@@ -33,14 +39,6 @@
1951 return m_guid;
1952 }
1953
1954-void Note::setGuid(const QString &guid)
1955-{
1956- if (m_guid == guid) {
1957- m_guid = guid;
1958- emit guidChanged();
1959- }
1960-}
1961-
1962 QString Note::notebookGuid() const
1963 {
1964 return m_notebookGuid;
1965@@ -54,6 +52,11 @@
1966 }
1967 }
1968
1969+QDateTime Note::created() const
1970+{
1971+ return m_created;
1972+}
1973+
1974 QString Note::title() const
1975 {
1976 return m_title;
1977@@ -76,10 +79,111 @@
1978 {
1979 if (m_content != content) {
1980 m_content = content;
1981+ m_plaintextContent = Html2EnmlConverter::enml2plaintext(content);
1982+ qDebug() << "plaintext content is" << m_plaintextContent;
1983 emit contentChanged();
1984 }
1985 }
1986
1987+QString Note::plaintextContent() const
1988+{
1989+ return m_plaintextContent;
1990+}
1991+
1992+bool Note::reminder() const
1993+{
1994+ return m_reminderOrder > 0;
1995+}
1996+
1997+void Note::setReminder(bool reminder)
1998+{
1999+ if (reminder && m_reminderOrder == 0) {
2000+ m_reminderOrder = QDateTime::currentMSecsSinceEpoch();
2001+ emit reminderChanged();
2002+ } else if (!reminder && m_reminderOrder > 0) {
2003+ m_reminderOrder = 0;
2004+ emit reminderChanged();
2005+ }
2006+}
2007+
2008+qint64 Note::reminderOrder() const
2009+{
2010+ return m_reminderOrder;
2011+}
2012+
2013+void Note::setReminderOrder(qint64 reminderOrder)
2014+{
2015+ if (m_reminderOrder != reminderOrder) {
2016+ m_reminderOrder = reminderOrder;
2017+ emit reminderChanged();
2018+ }
2019+}
2020+
2021+QDateTime Note::reminderTime() const
2022+{
2023+ return m_reminderTime;
2024+}
2025+
2026+void Note::setReminderTime(const QDateTime &reminderTime)
2027+{
2028+ if (m_reminderTime != reminderTime) {
2029+ m_reminderTime = reminderTime;
2030+ emit reminderTimeChanged();
2031+ }
2032+}
2033+
2034+bool Note::reminderDone() const
2035+{
2036+ return !m_reminderDoneTime.isNull();
2037+}
2038+
2039+void Note::setReminderDone(bool reminderDone)
2040+{
2041+ if (reminderDone && m_reminderDoneTime.isNull()) {
2042+ m_reminderDoneTime = QDateTime::currentDateTime();
2043+ emit reminderDoneChanged();
2044+ }
2045+}
2046+
2047+QDateTime Note::reminderDoneTime() const
2048+{
2049+ return m_reminderDoneTime;
2050+}
2051+
2052+void Note::setReminderDoneTime(const QDateTime &reminderDoneTime)
2053+{
2054+ if (m_reminderDoneTime != reminderDoneTime) {
2055+ m_reminderDoneTime = reminderDoneTime;
2056+ emit reminderDoneChanged();
2057+ }
2058+}
2059+
2060+bool Note::isSearchResult() const
2061+{
2062+ return m_isSearchResult;
2063+}
2064+
2065+void Note::setIsSearchResult(bool isSearchResult)
2066+{
2067+ if (m_isSearchResult != isSearchResult) {
2068+ m_isSearchResult = isSearchResult;
2069+ emit isSearchResultChanged();
2070+ }
2071+}
2072+
2073+Note *Note::clone()
2074+{
2075+ Note *note = new Note(m_guid, m_created);
2076+ note->setNotebookGuid(m_notebookGuid);
2077+ note->setTitle(m_title);
2078+ note->setContent(m_content);
2079+ note->setReminderOrder(m_reminderOrder);
2080+ note->setReminderTime(m_reminderTime);
2081+ note->setReminderDoneTime(m_reminderDoneTime);
2082+ note->setIsSearchResult(m_isSearchResult);
2083+ return note;
2084+}
2085+
2086 void Note::save()
2087 {
2088 NotesStore::instance()->saveNote(m_guid);
2089
2090=== modified file 'src/plugin/Evernote/note.h'
2091--- src/plugin/Evernote/note.h 2013-11-25 00:49:48 +0000
2092+++ src/plugin/Evernote/note.h 2013-12-14 00:07:45 +0000
2093@@ -2,45 +2,96 @@
2094 #define NOTE_H
2095
2096 #include <QObject>
2097+#include <QDateTime>
2098+#include <QStringList>
2099
2100 class Note : public QObject
2101 {
2102 Q_OBJECT
2103
2104- Q_PROPERTY(QString guid READ guid NOTIFY guidChanged)
2105+ // Don't forget to update clone() if you add properties!
2106+ Q_PROPERTY(QString guid READ guid CONSTANT)
2107 Q_PROPERTY(QString notebookGuid READ notebookGuid WRITE setNotebookGuid NOTIFY notebookGuidChanged)
2108+ Q_PROPERTY(QDateTime created READ created CONSTANT)
2109 Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
2110 Q_PROPERTY(QString content READ content WRITE setContent NOTIFY contentChanged)
2111+ Q_PROPERTY(QString plaintextContent READ plaintextContent NOTIFY contentChanged)
2112+ Q_PROPERTY(bool reminder READ reminder WRITE setReminder NOTIFY reminderChanged)
2113+ Q_PROPERTY(QDateTime reminderTime READ reminderTime WRITE setReminderTime NOTIFY reminderTimeChanged)
2114+ Q_PROPERTY(bool reminderDone READ reminderDone WRITE setReminderDone NOTIFY reminderDoneChanged)
2115+ Q_PROPERTY(QDateTime reminderDoneTime READ reminderDoneTime WRITE setReminderDoneTime NOTIFY reminderDoneChanged)
2116+ Q_PROPERTY(bool isSearchResult READ isSearchResult NOTIFY isSearchResultChanged)
2117+ // Don't forget to update clone() if you add properties!
2118+
2119 public:
2120- explicit Note(const QString &guid = QString(), QObject *parent = 0);
2121+ explicit Note(const QString &guid, const QDateTime &created, QObject *parent = 0);
2122
2123 QString guid() const;
2124- void setGuid(const QString &guid);
2125
2126 QString notebookGuid() const;
2127 void setNotebookGuid(const QString &notebookGuid);
2128
2129+ QDateTime created() const;
2130+
2131 QString title() const;
2132 void setTitle(const QString &title);
2133
2134 QString content() const;
2135 void setContent(const QString &content);
2136
2137+ QString plaintextContent() const;
2138+ void setPlaintextContent(const QString &plaintextContent);
2139+
2140+ // This is the QML representation as we don't want to deal with timestamps there.
2141+ // setting it to false will reset the reminderOrder to 0, setting it to true will
2142+ // create a new timestamp for it.
2143+ bool reminder() const;
2144+ void setReminder(bool reminder);
2145+
2146+ qint64 reminderOrder() const;
2147+ void setReminderOrder(qint64 reminderOrder);
2148+
2149+ QDateTime reminderTime() const;
2150+ void setReminderTime(const QDateTime &reminderTime);
2151+
2152+ // This is the QML representation as we don't want to deal with timestamps there.
2153+ // setting it to false will reset reminderDoneTime to 0, setting it to true will
2154+ // create a new timestamp for it.
2155+ bool reminderDone() const;
2156+ void setReminderDone(bool reminderDone);
2157+
2158+ QDateTime reminderDoneTime() const;
2159+ void setReminderDoneTime(const QDateTime &reminderDoneTime);
2160+
2161+ bool isSearchResult() const;
2162+ void setIsSearchResult(bool isSearchResult);
2163+
2164+ Note* clone();
2165+
2166 public slots:
2167 void save();
2168 void remove();
2169
2170 signals:
2171- void guidChanged();
2172 void titleChanged();
2173 void notebookGuidChanged();
2174 void contentChanged();
2175+ void reminderChanged();
2176+ void reminderTimeChanged();
2177+ void reminderDoneChanged();
2178+ void isSearchResultChanged();
2179
2180 private:
2181 QString m_guid;
2182 QString m_notebookGuid;
2183+ QDateTime m_created;
2184 QString m_title;
2185 QString m_content;
2186+ QString m_plaintextContent;
2187+ qint64 m_reminderOrder;
2188+ QDateTime m_reminderTime;
2189+ QDateTime m_reminderDoneTime;
2190+ bool m_isSearchResult;
2191 };
2192
2193 #endif // NOTE_H
2194
2195=== modified file 'src/plugin/Evernote/notebooks.cpp'
2196--- src/plugin/Evernote/notebooks.cpp 2013-11-26 17:18:33 +0000
2197+++ src/plugin/Evernote/notebooks.cpp 2013-12-14 00:07:45 +0000
2198@@ -35,7 +35,6 @@
2199
2200 QVariant Notebooks::data(const QModelIndex &index, int role) const
2201 {
2202-
2203 Notebook *notebook = NotesStore::instance()->notebook(m_list.at(index.row()));
2204 switch(role) {
2205 case RoleGuid:
2206
2207=== modified file 'src/plugin/Evernote/notes.cpp'
2208--- src/plugin/Evernote/notes.cpp 2013-11-26 17:18:33 +0000
2209+++ src/plugin/Evernote/notes.cpp 2013-12-14 00:07:45 +0000
2210@@ -24,37 +24,12 @@
2211 #include <QDebug>
2212
2213 Notes::Notes(QObject *parent) :
2214- QAbstractListModel(parent)
2215-{
2216- connect(NotesStore::instance(), &NotesStore::noteAdded, this, &Notes::noteAdded);
2217- connect(NotesStore::instance(), &NotesStore::noteRemoved, this, &Notes::noteRemoved);
2218- connect(NotesStore::instance(), &NotesStore::noteChanged, this, &Notes::noteChanged);
2219-}
2220-
2221-QVariant Notes::data(const QModelIndex &index, int role) const
2222-{
2223- Note *note = NotesStore::instance()->note(m_list.at(index.row()));
2224- switch(role) {
2225- case RoleGuid:
2226- return note->guid();
2227- case RoleTitle:
2228- return note->title();
2229- }
2230-
2231- return QVariant();
2232-}
2233-
2234-int Notes::rowCount(const QModelIndex &parent) const
2235-{
2236- return m_list.count();
2237-}
2238-
2239-QHash<int, QByteArray> Notes::roleNames() const
2240-{
2241- QHash<int, QByteArray> roles;
2242- roles.insert(RoleGuid, "guid");
2243- roles.insert(RoleTitle, "title");
2244- return roles;
2245+ QSortFilterProxyModel(parent),
2246+ m_onlyReminders(false)
2247+{
2248+ setSourceModel(NotesStore::instance());
2249+ setSortRole(NotesStore::RoleCreated);
2250+ sort(0, Qt::DescendingOrder);
2251 }
2252
2253 QString Notes::filterNotebookGuid() const
2254@@ -67,53 +42,56 @@
2255 if (m_filterNotebookGuid != notebookGuid) {
2256 m_filterNotebookGuid = notebookGuid;
2257 emit filterNotebookGuidChanged();
2258- }
2259-}
2260-
2261-Note* Notes::note(const QString &guid)
2262-{
2263- NotesStore::instance()->refreshNoteContent(guid);
2264- return NotesStore::instance()->note(guid);
2265-}
2266-
2267-void Notes::componentComplete()
2268-{
2269- foreach (Note *note, NotesStore::instance()->notes()) {
2270- if (m_filterNotebookGuid.isEmpty() || note->notebookGuid() == m_filterNotebookGuid) {
2271- m_list.append(note->guid());
2272- }
2273- }
2274- beginInsertRows(QModelIndex(), 0, m_list.count() - 1);
2275- endInsertRows();
2276- refresh();
2277-}
2278-
2279-void Notes::refresh()
2280-{
2281- NotesStore::instance()->refreshNotes(m_filterNotebookGuid);
2282-}
2283-
2284-void Notes::noteAdded(const QString &guid)
2285-{
2286- beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
2287- m_list.append(guid);
2288- endInsertRows();
2289-}
2290-
2291-void Notes::noteChanged(const QString &guid)
2292-{
2293- int row = m_list.indexOf(guid);
2294- if (row >= 0) {
2295- emit dataChanged(index(row), index(row));
2296- }
2297-}
2298-
2299-void Notes::noteRemoved(const QString &guid)
2300-{
2301- int index = m_list.indexOf(guid);
2302- if (index >= 0) {
2303- beginRemoveRows(QModelIndex(), index, index);
2304- m_list.removeAt(index);
2305- endRemoveRows();
2306- }
2307+ invalidateFilter();
2308+ }
2309+}
2310+
2311+bool Notes::onlyReminders() const
2312+{
2313+ return m_onlyReminders;
2314+}
2315+
2316+void Notes::setOnlyReminders(bool onlyReminders)
2317+{
2318+ if (m_onlyReminders != onlyReminders) {
2319+ m_onlyReminders = onlyReminders;
2320+ emit onlyRemindersChanged();
2321+ invalidateFilter();
2322+ }
2323+}
2324+
2325+bool Notes::onlySearchResults() const
2326+{
2327+ return m_onlySearchResults;
2328+}
2329+
2330+void Notes::setOnlySearchResults(bool onlySearchResults)
2331+{
2332+ if (m_onlySearchResults != onlySearchResults) {
2333+ m_onlySearchResults = onlySearchResults;
2334+ emit onlySearchResultsChanged();
2335+ invalidateFilter();
2336+ }
2337+}
2338+
2339+bool Notes::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
2340+{
2341+ QModelIndex sourceIndex = sourceModel()->index(sourceRow, 0, sourceParent);
2342+ if (!m_filterNotebookGuid.isEmpty()) {
2343+ if (sourceModel()->data(sourceIndex, NotesStore::RoleNotebookGuid).toString() != m_filterNotebookGuid) {
2344+ return false;
2345+ }
2346+ }
2347+ if (m_onlyReminders) {
2348+ if (!sourceModel()->data(sourceIndex, NotesStore::RoleReminder).toBool()) {
2349+ return false;
2350+ }
2351+ }
2352+ if (m_onlySearchResults) {
2353+ Note *note = NotesStore::instance()->note(sourceModel()->data(sourceIndex, NotesStore::RoleGuid).toString());
2354+ if (!note->isSearchResult()) {
2355+ return false;
2356+ }
2357+ }
2358+ return true;
2359 }
2360
2361=== modified file 'src/plugin/Evernote/notes.h'
2362--- src/plugin/Evernote/notes.h 2013-11-25 00:49:48 +0000
2363+++ src/plugin/Evernote/notes.h 2013-12-14 00:07:45 +0000
2364@@ -3,47 +3,39 @@
2365
2366 #include "notesstore.h"
2367
2368-#include <QAbstractListModel>
2369-#include <QQmlParserStatus>
2370+#include <QSortFilterProxyModel>
2371
2372-class Notes : public QAbstractListModel, public QQmlParserStatus
2373+class Notes : public QSortFilterProxyModel
2374 {
2375 Q_OBJECT
2376 Q_PROPERTY(QString filterNotebookGuid READ filterNotebookGuid WRITE setFilterNotebookGuid NOTIFY filterNotebookGuidChanged)
2377+ Q_PROPERTY(bool onlyReminders READ onlyReminders WRITE setOnlyReminders NOTIFY onlyRemindersChanged)
2378+ Q_PROPERTY(bool onlySearchResults READ onlySearchResults WRITE setOnlySearchResults NOTIFY onlySearchResultsChanged)
2379+
2380 public:
2381- enum Roles {
2382- RoleGuid,
2383- RoleTitle
2384- };
2385 explicit Notes(QObject *parent = 0);
2386
2387- QVariant data(const QModelIndex &index, int role) const;
2388- int rowCount(const QModelIndex &parent) const;
2389- QHash<int, QByteArray> roleNames() const;
2390-
2391 QString filterNotebookGuid() const;
2392 void setFilterNotebookGuid(const QString &notebookGuid);
2393
2394- Q_INVOKABLE Note* note(const QString &guid);
2395-
2396- void classBegin() {}
2397- void componentComplete();
2398-
2399-public slots:
2400- void refresh();
2401-
2402-private slots:
2403- void noteAdded(const QString &guid);
2404- void noteChanged(const QString &guid);
2405- void noteRemoved(const QString &guid);
2406+ bool onlyReminders() const;
2407+ void setOnlyReminders(bool onlyReminders);
2408+
2409+ bool onlySearchResults() const;
2410+ void setOnlySearchResults(bool onlySearchResults);
2411+
2412+protected:
2413+ bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
2414
2415 signals:
2416 void filterNotebookGuidChanged();
2417+ void onlyRemindersChanged();
2418+ void onlySearchResultsChanged();
2419
2420 private:
2421- QList<QString> m_list;
2422 QString m_filterNotebookGuid;
2423-
2424+ bool m_onlyReminders;
2425+ bool m_onlySearchResults;
2426 };
2427
2428 #endif // NOTES_H
2429
2430=== modified file 'src/plugin/Evernote/notesstore.cpp'
2431--- src/plugin/Evernote/notesstore.cpp 2013-11-27 17:33:36 +0000
2432+++ src/plugin/Evernote/notesstore.cpp 2013-12-14 00:07:45 +0000
2433@@ -19,6 +19,7 @@
2434 */
2435
2436 #include "notesstore.h"
2437+#include "evernoteconnection.h"
2438 #include "notebooks.h"
2439 #include "notebook.h"
2440 #include "note.h"
2441@@ -30,73 +31,24 @@
2442 #include "jobs/createnotejob.h"
2443 #include "jobs/savenotejob.h"
2444 #include "jobs/deletenotejob.h"
2445-
2446-// Thrift
2447-#include <arpa/inet.h> // seems thrift forgot this one
2448-#include <protocol/TBinaryProtocol.h>
2449-#include <transport/THttpClient.h>
2450-#include <transport/TSSLSocket.h>
2451-#include <Thrift.h>
2452+#include "jobs/createnotebookjob.h"
2453+#include "jobs/expungenotebookjob.h"
2454
2455 #include <QDebug>
2456
2457-using namespace apache::thrift;
2458-using namespace apache::thrift::protocol;
2459-using namespace apache::thrift::transport;
2460-
2461 NotesStore* NotesStore::s_instance = 0;
2462
2463 NotesStore::NotesStore(QObject *parent) :
2464- QObject(parent),
2465- m_currentJob(0)
2466+ QAbstractListModel(parent)
2467 {
2468- try {
2469- // FIXME: need to populate this string from the system
2470- // The structure should be:
2471- // application/version; platform/version; [ device/version ]
2472- // E.g. "Evernote Windows/3.0.1; Windows/XP SP3"
2473- QString EDAM_CLIENT_NAME = QStringLiteral("Reminders/0.1; Ubuntu/13.10");
2474- QString EVERNOTE_HOST = QStringLiteral("sandbox.evernote.com");
2475- QString EDAM_USER_STORE_PATH = QStringLiteral("/edam/note");
2476- boost::shared_ptr<TSocket> socket;
2477- bool use_SSL = true;
2478-
2479- if (use_SSL) {
2480- // Create an SSL socket
2481- // FIXME: this fails with the following error:
2482- // Thrift: Fri Nov 15 12:47:31 2013 SSL_shutdown: error code: 0
2483- // SSL_get_verify_result(), unable to get local issuer certificate
2484- // Additionally, the UI blocks and does not load for about 2 minutes
2485- boost::shared_ptr<TSSLSocketFactory> sslSocketFactory(new TSSLSocketFactory());
2486- socket = sslSocketFactory->createSocket(EVERNOTE_HOST.toStdString(), 443);
2487- qDebug() << "created SSL socket";
2488- } else {
2489- // Create a non-secure socket
2490- socket = boost::shared_ptr<TSocket> (new TSocket(EVERNOTE_HOST.toStdString(), 80));
2491- qDebug() << "created insecure socket";
2492- }
2493-
2494- boost::shared_ptr<TBufferedTransport> bufferedTransport(new TBufferedTransport(socket));
2495- boost::shared_ptr<THttpClient> userStoreHttpClient (new THttpClient(bufferedTransport,
2496- EVERNOTE_HOST.toStdString(),
2497- EDAM_USER_STORE_PATH.toStdString()));
2498- userStoreHttpClient->open();
2499-
2500- boost::shared_ptr<TProtocol> iprot(new TBinaryProtocol(userStoreHttpClient));
2501- m_client = new evernote::edam::NoteStoreClient(iprot);
2502-
2503- qDebug() << "NoteStore client created.";
2504-
2505- } catch (const TTransportException & e) {
2506- qWarning() << "Failed to create Transport:" << e.what();
2507- } catch (const TException & e) {
2508- qWarning() << "Generic Thrift exception:" << e.what();
2509- }
2510-
2511- qRegisterMetaType<NotesStore::ErrorCode>("NotesStore::ErrorCode");
2512+ connect(EvernoteConnection::instance(), &EvernoteConnection::tokenChanged, this, &NotesStore::refreshNotebooks);
2513+ connect(EvernoteConnection::instance(), SIGNAL(tokenChanged()), this, SLOT(refreshNotes()));
2514+
2515+ qRegisterMetaType<EvernoteConnection::ErrorCode>("EvernoteConnection::ErrorCode");
2516 qRegisterMetaType<evernote::edam::NotesMetadataList>("evernote::edam::NotesMetadataList");
2517 qRegisterMetaType<evernote::edam::Note>("evernote::edam::Note");
2518 qRegisterMetaType<std::vector<evernote::edam::Notebook> >("std::vector<evernote::edam::Notebook>");
2519+ qRegisterMetaType<evernote::edam::Notebook>("evernote::edam::Notebook");
2520
2521 }
2522
2523@@ -108,255 +60,317 @@
2524 return s_instance;
2525 }
2526
2527-QString NotesStore::errorCodeToString(NotesStore::ErrorCode errorCode)
2528-{
2529- switch(errorCode) {
2530- case ErrorCodeNoError:
2531- return QStringLiteral("No error");
2532- case ErrorCodeUserException:
2533- return QStringLiteral("User exception");
2534- case ErrorCodeSystemException:
2535- return QStringLiteral("System exception");
2536- case ErrorCodeNotFoundExcpetion:
2537- return QStringLiteral("Not found");
2538+int NotesStore::rowCount(const QModelIndex &parent) const
2539+{
2540+ return m_notes.count();
2541+}
2542+
2543+QVariant NotesStore::data(const QModelIndex &index, int role) const
2544+{
2545+ switch (role) {
2546+ case RoleGuid:
2547+ return m_notes.at(index.row())->guid();
2548+ case RoleNotebookGuid:
2549+ return m_notes.at(index.row())->notebookGuid();
2550+ case RoleCreated:
2551+ return m_notes.at(index.row())->created();
2552+ case RoleTitle:
2553+ return m_notes.at(index.row())->title();
2554+ case RoleReminder:
2555+ return m_notes.at(index.row())->reminder();
2556+ case RoleReminderTime:
2557+ return m_notes.at(index.row())->reminderTime();
2558+ case RoleReminderDone:
2559+ return m_notes.at(index.row())->reminderDone();
2560+ case RoleReminderDoneTime:
2561+ return m_notes.at(index.row())->reminderDoneTime();
2562 }
2563- return QString();
2564+ return QVariant();
2565+}
2566+
2567+QHash<int, QByteArray> NotesStore::roleNames() const
2568+{
2569+ QHash<int, QByteArray> roles;
2570+ roles.insert(RoleGuid, "guid");
2571+ roles.insert(RoleNotebookGuid, "notebookGuid");
2572+ roles.insert(RoleCreated, "created");
2573+ roles.insert(RoleTitle, "title");
2574+ roles.insert(RoleReminder, "reminder");
2575+ roles.insert(RoleReminderTime, "reminderTime");
2576+ roles.insert(RoleReminderDone, "reminderDone");
2577+ roles.insert(RoleReminderDoneTime, "reminderDoneTime");
2578+ return roles;
2579 }
2580
2581 NotesStore::~NotesStore()
2582 {
2583- delete m_client;
2584-}
2585-
2586-QString NotesStore::token() const
2587-{
2588- return m_token;
2589-}
2590-
2591-void NotesStore::setToken(const QString &token)
2592-{
2593- if (token != m_token) {
2594- m_token = token;
2595- emit tokenChanged();
2596- refreshNotebooks();
2597- refreshNotes();
2598- }
2599 }
2600
2601 QList<Note*> NotesStore::notes() const
2602 {
2603- return m_notes.values();
2604+ return m_notes;
2605 }
2606
2607 Note *NotesStore::note(const QString &guid)
2608 {
2609- return m_notes.value(guid);
2610-}
2611-
2612-void NotesStore::saveNote(const QString &guid)
2613-{
2614- Note *note = m_notes.value(guid);
2615-
2616- QString enml = Html2EnmlConverter::html2enml(note->content());
2617- note->setContent(enml);
2618-
2619- SaveNoteJob *job = new SaveNoteJob(note, this);
2620- connect(job, &SaveNoteJob::resultReady, this, &NotesStore::saveNoteJobDone);
2621- m_jobQueue.append(job);
2622- startJobQueue();
2623-}
2624-
2625-void NotesStore::deleteNote(const QString &guid)
2626-{
2627- DeleteNoteJob *job = new DeleteNoteJob(guid, this);
2628- connect(job, &DeleteNoteJob::resultReady, this, &NotesStore::deleteNoteJobDone);
2629- m_jobQueue.append(job);
2630- startJobQueue();
2631+ return m_notesHash.value(guid);
2632 }
2633
2634 QList<Notebook *> NotesStore::notebooks() const
2635 {
2636- return m_notebooks.values();
2637+ return m_notebooks;
2638 }
2639
2640 Notebook *NotesStore::notebook(const QString &guid)
2641 {
2642- return m_notebooks.value(guid);
2643-}
2644-
2645-void NotesStore::startJobQueue()
2646-{
2647- if (m_jobQueue.isEmpty()) {
2648- return;
2649- }
2650-
2651- if (m_currentJob) {
2652- return;
2653- }
2654- m_currentJob = m_jobQueue.takeFirst();
2655- m_currentJob->start();
2656-}
2657-
2658-void NotesStore::startNextJob()
2659-{
2660- m_currentJob = 0;
2661- startJobQueue();
2662+ return m_notebooksHash.value(guid);
2663+}
2664+
2665+void NotesStore::createNotebook(const QString &name)
2666+{
2667+ CreateNotebookJob *job = new CreateNotebookJob(name);
2668+ connect(job, &CreateNotebookJob::jobDone, this, &NotesStore::createNotebookJobDone);
2669+ EvernoteConnection::instance()->enqueue(job);
2670+}
2671+
2672+void NotesStore::expungeNotebook(const QString &guid)
2673+{
2674+ ExpungeNotebookJob *job = new ExpungeNotebookJob(guid);
2675+ connect(job, &ExpungeNotebookJob::jobDone, this, &NotesStore::expungeNotebookJobDone);
2676+ EvernoteConnection::instance()->enqueue(job);
2677 }
2678
2679 void NotesStore::refreshNotes(const QString &filterNotebookGuid)
2680 {
2681- if (m_token.isEmpty()) {
2682- qWarning() << "No token set. Cannot fetch notes.";
2683- return;
2684- }
2685-
2686 FetchNotesJob *job = new FetchNotesJob(filterNotebookGuid);
2687- connect(job, &FetchNotesJob::resultReady, this, &NotesStore::fetchNotesJobDone);
2688-
2689- m_jobQueue.append(job);
2690- startJobQueue();
2691+ connect(job, &FetchNotesJob::jobDone, this, &NotesStore::fetchNotesJobDone);
2692+ EvernoteConnection::instance()->enqueue(job);
2693 }
2694
2695-void NotesStore::fetchNotesJobDone(ErrorCode errorCode, const evernote::edam::NotesMetadataList &results)
2696+void NotesStore::fetchNotesJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const evernote::edam::NotesMetadataList &results)
2697 {
2698- if (errorCode != ErrorCodeNoError) {
2699- qWarning() << "Failed to fetch notes list:" << errorCodeToString(errorCode);
2700- startNextJob();
2701+ if (errorCode != EvernoteConnection::ErrorCodeNoError) {
2702+ qWarning() << "Failed to fetch notes list:" << errorMessage;
2703 return;
2704 }
2705
2706 for (int i = 0; i < results.notes.size(); ++i) {
2707 evernote::edam::NoteMetadata result = results.notes.at(i);
2708- Note *note = m_notes.value(QString::fromStdString(result.guid));
2709- if (note) {
2710- note->setTitle(QString::fromStdString(result.title));
2711- note->setNotebookGuid(QString::fromStdString(result.notebookGuid));
2712+ Note *note = m_notesHash.value(QString::fromStdString(result.guid));
2713+ bool newNote = note == 0;
2714+ if (newNote) {
2715+ QString guid = QString::fromStdString(result.guid);
2716+ QDateTime created = QDateTime::fromMSecsSinceEpoch(result.created);
2717+ note = new Note(guid, created, this);
2718+ }
2719+
2720+ note->setTitle(QString::fromStdString(result.title));
2721+ note->setNotebookGuid(QString::fromStdString(result.notebookGuid));
2722+ note->setReminderOrder(result.attributes.reminderOrder);
2723+
2724+ if (!results.searchedWords.empty()) {
2725+ note->setIsSearchResult(true);
2726+ }
2727+
2728+ QDateTime reminderDoneTime;
2729+ if (result.attributes.reminderDoneTime > 0) {
2730+ reminderDoneTime = QDateTime::fromMSecsSinceEpoch(result.attributes.reminderDoneTime);
2731+ }
2732+ note->setReminderDoneTime(reminderDoneTime);
2733+
2734+ if (newNote) {
2735+ beginInsertRows(QModelIndex(), m_notes.count(), m_notes.count());
2736+ m_notesHash.insert(note->guid(), note);
2737+ m_notes.append(note);
2738+ endInsertRows();
2739+ emit noteAdded(note->guid());
2740+ } else {
2741+ QModelIndex noteIndex = index(m_notes.indexOf(note));
2742+ emit dataChanged(noteIndex, noteIndex);
2743 emit noteChanged(note->guid());
2744- } else {
2745- note = new Note(QString::fromStdString(result.guid), this);
2746- note->setNotebookGuid(QString::fromStdString(result.notebookGuid));
2747- note->setTitle(QString::fromStdString(result.title));
2748- m_notes.insert(note->guid(), note);
2749- emit noteAdded(note->guid());
2750 }
2751 }
2752-
2753- startNextJob();
2754 }
2755
2756 void NotesStore::refreshNoteContent(const QString &guid)
2757 {
2758- if (m_token.isEmpty()) {
2759- qWarning() << "No token set. Cannot fetch note.";
2760- return;
2761- }
2762-
2763 FetchNoteJob *job = new FetchNoteJob(guid, this);
2764 connect(job, &FetchNoteJob::resultReady, this, &NotesStore::fetchNoteJobDone);
2765- m_jobQueue.append(job);
2766-
2767- startJobQueue();
2768+ EvernoteConnection::instance()->enqueue(job);
2769 }
2770
2771-void NotesStore::fetchNoteJobDone(ErrorCode errorCode, const evernote::edam::Note &result)
2772+void NotesStore::fetchNoteJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const evernote::edam::Note &result)
2773 {
2774- if (errorCode != ErrorCodeNoError) {
2775- qWarning() << "Error fetching note:" << errorCode;
2776- startNextJob();
2777+ if (errorCode != EvernoteConnection::ErrorCodeNoError) {
2778+ qWarning() << "Error fetching note:" << errorMessage;
2779 return;
2780 }
2781
2782- Note *note = m_notes.value(QString::fromStdString(result.guid));
2783+ Note *note = m_notesHash.value(QString::fromStdString(result.guid));
2784 note->setNotebookGuid(QString::fromStdString(result.notebookGuid));
2785 note->setTitle(QString::fromStdString(result.title));
2786 note->setContent(QString::fromStdString(result.content));
2787+ note->setReminderOrder(result.attributes.reminderOrder);
2788+ QDateTime reminderDoneTime;
2789+ if (result.attributes.reminderDoneTime > 0) {
2790+ reminderDoneTime = QDateTime::fromMSecsSinceEpoch(result.attributes.reminderDoneTime);
2791+ }
2792+ note->setReminderDoneTime(reminderDoneTime);
2793 emit noteChanged(note->guid());
2794
2795- startNextJob();
2796+ QModelIndex noteIndex = index(m_notes.indexOf(note));
2797+ emit dataChanged(noteIndex, noteIndex);
2798 }
2799
2800 void NotesStore::refreshNotebooks()
2801 {
2802- if (m_token.isEmpty()) {
2803- qWarning() << "No token set. Cannot refresh notebooks.";
2804- return;
2805- }
2806-
2807 FetchNotebooksJob *job = new FetchNotebooksJob();
2808- connect(job, &FetchNotebooksJob::resultReady, this, &NotesStore::fetchNotebooksJobDone);
2809-
2810- m_jobQueue.append(job);
2811- startJobQueue();
2812+ connect(job, &FetchNotebooksJob::jobDone, this, &NotesStore::fetchNotebooksJobDone);
2813+ EvernoteConnection::instance()->enqueue(job);
2814 }
2815
2816-void NotesStore::fetchNotebooksJobDone(ErrorCode errorCode, const std::vector<evernote::edam::Notebook> &results)
2817+void NotesStore::fetchNotebooksJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const std::vector<evernote::edam::Notebook> &results)
2818 {
2819- if (errorCode != ErrorCodeNoError) {
2820- qWarning() << "Error fetching notebooks:" << errorCodeToString(errorCode);
2821- startNextJob();
2822+ if (errorCode != EvernoteConnection::ErrorCodeNoError) {
2823+ qWarning() << "Error fetching notebooks:" << errorMessage;
2824 return;
2825 }
2826
2827 for (int i = 0; i < results.size(); ++i) {
2828 evernote::edam::Notebook result = results.at(i);
2829- Notebook *notebook = m_notebooks.value(QString::fromStdString(result.guid));
2830- if (notebook) {
2831- qDebug() << "got notebook update";
2832- notebook->setName(QString::fromStdString(result.name));
2833- emit notebookChanged(notebook->guid());
2834- } else {
2835+ Notebook *notebook = m_notebooksHash.value(QString::fromStdString(result.guid));
2836+ bool newNoteNotebook = notebook == 0;
2837+ if (newNoteNotebook) {
2838 notebook = new Notebook(QString::fromStdString(result.guid), this);
2839- notebook->setName(QString::fromStdString(result.name));
2840- m_notebooks.insert(notebook->guid(), notebook);
2841+ }
2842+ notebook->setName(QString::fromStdString(result.name));
2843+
2844+ if (newNoteNotebook) {
2845+ m_notebooksHash.insert(notebook->guid(), notebook);
2846+ m_notebooks.append(notebook);
2847 emit notebookAdded(notebook->guid());
2848- qDebug() << "got new notebook" << notebook->guid();
2849+ } else {
2850+ emit notebookChanged(notebook->guid());
2851 }
2852 }
2853-
2854- startNextJob();
2855 }
2856
2857 void NotesStore::createNote(const QString &title, const QString &notebookGuid, const QString &content)
2858 {
2859- Note *note = new Note();
2860- note->setTitle(title);
2861- note->setNotebookGuid(notebookGuid);
2862- note->setContent(content);
2863- CreateNoteJob *job = new CreateNoteJob(note);
2864- connect(job, &CreateNoteJob::resultReady, this, &NotesStore::createNoteJobDone);
2865-
2866- m_jobQueue.append(job);
2867- startJobQueue();
2868-}
2869-
2870-void NotesStore::createNoteJobDone(NotesStore::ErrorCode errorCode, Note *note)
2871-{
2872- if (errorCode != ErrorCodeNoError) {
2873- qWarning() << "Error creating note:" << errorCodeToString(errorCode);
2874- delete note;
2875- startNextJob();
2876- return;
2877- }
2878-
2879- m_notes.insert(note->guid(), note);
2880- noteAdded(note->guid());
2881- startNextJob();
2882-}
2883-
2884-void NotesStore::saveNoteJobDone(NotesStore::ErrorCode errorCode, Note *note)
2885-{
2886- startNextJob();
2887-}
2888-
2889-void NotesStore::deleteNoteJobDone(NotesStore::ErrorCode errorCode, const QString &guid)
2890-{
2891- if (errorCode != ErrorCodeNoError) {
2892- qWarning() << "Cannot delete note:" << errorCodeToString(errorCode);
2893- startNextJob();
2894+ CreateNoteJob *job = new CreateNoteJob(title, notebookGuid, content);
2895+ connect(job, &CreateNoteJob::jobDone, this, &NotesStore::createNoteJobDone);
2896+ EvernoteConnection::instance()->enqueue(job);
2897+}
2898+
2899+void NotesStore::createNoteJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const evernote::edam::Note &result)
2900+{
2901+ if (errorCode != EvernoteConnection::ErrorCodeNoError) {
2902+ qWarning() << "Error creating note:" << errorMessage;
2903+ return;
2904+ }
2905+
2906+ QString guid = QString::fromStdString(result.guid);
2907+ QDateTime created = QDateTime::fromMSecsSinceEpoch(result.created);
2908+ Note *note = new Note(guid, created, this);
2909+ note->setNotebookGuid(QString::fromStdString(result.notebookGuid));
2910+ note->setTitle(QString::fromStdString(result.title));
2911+ note->setContent(QString::fromStdString(result.content));
2912+
2913+ beginInsertRows(QModelIndex(), m_notes.count(), m_notes.count());
2914+ m_notesHash.insert(note->guid(), note);
2915+ m_notes.append(note);
2916+ endInsertRows();
2917+
2918+ emit noteAdded(note->guid());
2919+}
2920+
2921+void NotesStore::saveNote(const QString &guid)
2922+{
2923+ Note *note = m_notesHash.value(guid);
2924+
2925+ QString enml = Html2EnmlConverter::html2enml(note->content());
2926+ note->setContent(enml);
2927+
2928+ SaveNoteJob *job = new SaveNoteJob(note, this);
2929+ connect(job, &SaveNoteJob::jobDone, this, &NotesStore::saveNoteJobDone);
2930+ EvernoteConnection::instance()->enqueue(job);
2931+}
2932+
2933+void NotesStore::saveNoteJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const evernote::edam::Note &result)
2934+{
2935+ if (errorCode != EvernoteConnection::ErrorCodeNoError) {
2936+ qWarning() << "error saving note" << errorMessage;
2937+ return;
2938+ }
2939+
2940+ Note *note = m_notesHash.value(QString::fromStdString(result.guid));
2941+ if (note) {
2942+ note->setTitle(QString::fromStdString(result.title));
2943+ note->setNotebookGuid(QString::fromStdString(result.notebookGuid));
2944+
2945+ emit noteChanged(note->guid());
2946+
2947+ QModelIndex noteIndex = index(m_notes.indexOf(note));
2948+ emit dataChanged(noteIndex, noteIndex);
2949+ }
2950+}
2951+
2952+void NotesStore::deleteNote(const QString &guid)
2953+{
2954+ DeleteNoteJob *job = new DeleteNoteJob(guid, this);
2955+ connect(job, &DeleteNoteJob::jobDone, this, &NotesStore::deleteNoteJobDone);
2956+ EvernoteConnection::instance()->enqueue(job);
2957+}
2958+
2959+void NotesStore::findNotes(const QString &searchWords)
2960+{
2961+ foreach (Note *note, m_notes) {
2962+ note->setIsSearchResult(false);
2963+ }
2964+ emit dataChanged(index(0), index(m_notes.count()), QVector<int>() << RoleIsSearchResult);
2965+
2966+ FetchNotesJob *job = new FetchNotesJob(QString(), searchWords);
2967+ connect(job, &FetchNotesJob::jobDone, this, &NotesStore::fetchNotesJobDone);
2968+ EvernoteConnection::instance()->enqueue(job);
2969+}
2970+
2971+void NotesStore::deleteNoteJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const QString &guid)
2972+{
2973+ if (errorCode != EvernoteConnection::ErrorCodeNoError) {
2974+ qWarning() << "Cannot delete note:" << errorMessage;
2975 return;
2976 }
2977 emit noteRemoved(guid);
2978- m_notes.take(guid)->deleteLater();
2979- startNextJob();
2980-}
2981-
2982+
2983+ Note *note = m_notesHash.value(guid);
2984+ int noteIndex = m_notes.indexOf(note);
2985+ beginRemoveRows(QModelIndex(), noteIndex, noteIndex);
2986+ m_notes.takeAt(noteIndex);
2987+ m_notesHash.take(guid)->deleteLater();
2988+ endRemoveRows();
2989+}
2990+
2991+void NotesStore::createNotebookJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const evernote::edam::Notebook &result)
2992+{
2993+ if (errorCode != EvernoteConnection::ErrorCodeNoError) {
2994+ qWarning() << "Error creating notebook:" << errorMessage;
2995+ return;
2996+ }
2997+ Notebook *notebook = new Notebook(QString::fromStdString(result.guid));
2998+ notebook->setName(QString::fromStdString(result.name));
2999+ m_notebooks.append(notebook);
3000+ m_notebooksHash.insert(notebook->guid(), notebook);
3001+ emit notebookAdded(notebook->guid());
3002+}
3003+
3004+void NotesStore::expungeNotebookJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const QString &guid)
3005+{
3006+ if (errorCode != EvernoteConnection::ErrorCodeNoError) {
3007+ qWarning() << "Error expunging notebook:" << errorMessage;
3008+ return;
3009+ }
3010+ emit notebookRemoved(guid);
3011+ Notebook *notebook = m_notebooksHash.take(guid);
3012+ m_notebooks.removeAll(notebook);
3013+ notebook->deleteLater();
3014+}
3015
3016=== modified file 'src/plugin/Evernote/notesstore.h'
3017--- src/plugin/Evernote/notesstore.h 2013-11-25 00:49:48 +0000
3018+++ src/plugin/Evernote/notesstore.h 2013-12-14 00:07:45 +0000
3019@@ -1,53 +1,67 @@
3020 #ifndef NOTESSTORE_H
3021 #define NOTESSTORE_H
3022
3023+#include "evernoteconnection.h"
3024+
3025+// Thrift
3026+#include <arpa/inet.h> // seems thrift forgot this one
3027+#include <protocol/TBinaryProtocol.h>
3028+#include <transport/THttpClient.h>
3029+#include <transport/TSSLSocket.h>
3030+#include <Thrift.h>
3031+
3032 // Evernote SDK
3033 #include <NoteStore.h>
3034 #include <NoteStore_constants.h>
3035 #include <Errors_types.h>
3036
3037-#include <QObject>
3038+#include <QAbstractListModel>
3039 #include <QHash>
3040
3041-class EvernoteJob;
3042-
3043 class Notebook;
3044 class Note;
3045
3046-class NotesStore : public QObject
3047+using namespace apache::thrift::transport;
3048+
3049+class NotesStore : public QAbstractListModel
3050 {
3051 Q_OBJECT
3052- Q_PROPERTY(QString token READ token WRITE setToken NOTIFY tokenChanged)
3053-
3054- friend class EvernoteJob;
3055
3056 public:
3057- enum ErrorCode {
3058- ErrorCodeNoError,
3059- ErrorCodeUserException,
3060- ErrorCodeSystemException,
3061- ErrorCodeNotFoundExcpetion,
3062- ErrorCodeConnectionLost
3063+ enum Roles {
3064+ RoleGuid,
3065+ RoleNotebookGuid,
3066+ RoleCreated,
3067+ RoleTitle,
3068+ RoleReminder,
3069+ RoleReminderTime,
3070+ RoleReminderDone,
3071+ RoleReminderDoneTime,
3072+ RoleIsSearchResult
3073 };
3074
3075- Q_INVOKABLE void createNote(const QString &title, const QString &notebookGuid, const QString &content);
3076-
3077+ ~NotesStore();
3078 static NotesStore *instance();
3079- static QString errorCodeToString(ErrorCode errorCode);
3080-
3081- ~NotesStore();
3082-
3083- QString token() const;
3084- void setToken(const QString &token);
3085+
3086+ // reimplemented from QAbstractListModel
3087+ int rowCount(const QModelIndex &parent) const;
3088+ QVariant data(const QModelIndex &index, int role) const;
3089+ QHash<int, QByteArray> roleNames() const;
3090
3091 QList<Note*> notes() const;
3092- Note* note(const QString &guid);
3093- void saveNote(const QString &guid);
3094- void deleteNote(const QString &guid);
3095+
3096+ Q_INVOKABLE Note* note(const QString &guid);
3097+ Q_INVOKABLE void createNote(const QString &title, const QString &notebookGuid, const QString &content);
3098+ Q_INVOKABLE void saveNote(const QString &guid);
3099+ Q_INVOKABLE void deleteNote(const QString &guid);
3100+ Q_INVOKABLE void findNotes(const QString &searchWords);
3101
3102 QList<Notebook*> notebooks() const;
3103 Notebook* notebook(const QString &guid);
3104+ Q_INVOKABLE void createNotebook(const QString &name);
3105+ Q_INVOKABLE void expungeNotebook(const QString &guid);
3106
3107+public slots:
3108 void refreshNotes(const QString &filterNotebookGuid = QString());
3109 void refreshNoteContent(const QString &guid);
3110 void refreshNotebooks();
3111@@ -61,30 +75,28 @@
3112
3113 void notebookAdded(const QString &guid);
3114 void notebookChanged(const QString &guid);
3115+ void notebookRemoved(const QString &guid);
3116
3117 private slots:
3118- void fetchNotesJobDone(ErrorCode errorCode, const evernote::edam::NotesMetadataList &results);
3119- void fetchNotebooksJobDone(ErrorCode errorCode, const std::vector<evernote::edam::Notebook> &results);
3120- void fetchNoteJobDone(ErrorCode errorCode, const evernote::edam::Note &result);
3121- void createNoteJobDone(ErrorCode errorCode, Note *note);
3122- void saveNoteJobDone(ErrorCode errorCode, Note *note);
3123- void deleteNoteJobDone(ErrorCode errorCode, const QString &guid);
3124-
3125- void startJobQueue();
3126- void startNextJob();
3127+ void fetchNotesJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const evernote::edam::NotesMetadataList &results);
3128+ void fetchNotebooksJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const std::vector<evernote::edam::Notebook> &results);
3129+ void fetchNoteJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const evernote::edam::Note &result);
3130+ void createNoteJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const evernote::edam::Note &result);
3131+ void saveNoteJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const evernote::edam::Note &result);
3132+ void deleteNoteJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const QString &guid);
3133+ void createNotebookJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const evernote::edam::Notebook &result);
3134+ void expungeNotebookJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const QString &guid);
3135
3136 private:
3137 explicit NotesStore(QObject *parent = 0);
3138 static NotesStore *s_instance;
3139
3140- QString m_token;
3141- evernote::edam::NoteStoreClient *m_client;
3142-
3143- QHash<QString, Notebook*> m_notebooks;
3144- QHash<QString, Note*> m_notes;
3145-
3146- QList<EvernoteJob*> m_jobQueue;
3147- QThread *m_currentJob;
3148+ QList<Note*> m_notes;
3149+ QList<Notebook*> m_notebooks;
3150+
3151+ // Keep hashes for faster lookups as we always identify notes via guid
3152+ QHash<QString, Note*> m_notesHash;
3153+ QHash<QString, Notebook*> m_notebooksHash;
3154 };
3155
3156 #endif // NOTESSTORE_H
3157
3158=== modified file 'src/plugin/Evernote/userstore.cpp'
3159--- src/plugin/Evernote/userstore.cpp 2013-11-26 17:18:33 +0000
3160+++ src/plugin/Evernote/userstore.cpp 2013-12-14 00:07:45 +0000
3161@@ -19,6 +19,8 @@
3162 */
3163
3164 #include "userstore.h"
3165+#include "evernoteconnection.h"
3166+#include "jobs/fetchusernamejob.h"
3167
3168 // Evernote sdk
3169 #include <UserStore.h>
3170@@ -34,106 +36,47 @@
3171
3172 #include <QDebug>
3173
3174-using namespace evernote::edam;
3175 using namespace apache::thrift;
3176 using namespace apache::thrift::protocol;
3177 using namespace apache::thrift::transport;
3178
3179+UserStore* UserStore::s_instance = 0;
3180+
3181 UserStore::UserStore(QObject *parent) :
3182 QObject(parent)
3183 {
3184-
3185- try {
3186- // FIXME: need to populate this string from the system
3187- // The structure should be:
3188- // application/version; platform/version; [ device/version ]
3189- // E.g. "Evernote Windows/3.0.1; Windows/XP SP3"
3190- QString EDAM_CLIENT_NAME = QStringLiteral("Reminders/0.1; Ubuntu/13.10");
3191- QString EVERNOTE_HOST = QStringLiteral("sandbox.evernote.com");
3192- QString EDAM_USER_STORE_PATH = QStringLiteral("/edam/user");
3193- boost::shared_ptr<TSocket> socket;
3194- bool use_SSL = false;
3195-
3196- if (use_SSL) {
3197- // Create an SSL socket
3198- // FIXME: this fails with the following error:
3199- // Thrift: Fri Nov 15 12:47:31 2013 SSL_shutdown: error code: 0
3200- // SSL_get_verify_result(), unable to get local issuer certificate
3201- // Additionally, the UI blocks and does not load for about 2 minutes
3202- boost::shared_ptr<TSSLSocketFactory> sslSocketFactory(new TSSLSocketFactory());
3203- socket = sslSocketFactory->createSocket(EVERNOTE_HOST.toStdString(), 443);
3204- } else {
3205- // Create a non-secure socket
3206- socket = boost::shared_ptr<TSocket> (new TSocket(EVERNOTE_HOST.toStdString(), 80));
3207- }
3208-
3209- boost::shared_ptr<TBufferedTransport> bufferedTransport(new TBufferedTransport(socket));
3210- boost::shared_ptr<THttpClient> userStoreHttpClient (new THttpClient(bufferedTransport,
3211- EVERNOTE_HOST.toStdString(),
3212- EDAM_USER_STORE_PATH.toStdString()));
3213- userStoreHttpClient->open();
3214-
3215- boost::shared_ptr<TProtocol> iprot(new TBinaryProtocol(userStoreHttpClient));
3216- UserStoreClient m_client(iprot);
3217- UserStoreConstants constants;
3218-
3219- // checkVersion returns true if the client is capable of talking to the service,
3220- // false otherwise
3221- qDebug() << "version check:" << m_client.checkVersion(EDAM_CLIENT_NAME.toStdString(),
3222- constants.EDAM_VERSION_MAJOR,
3223- constants.EDAM_VERSION_MINOR);
3224-
3225- } catch(...) {
3226- displayException();
3227- }
3228-}
3229-
3230-void UserStore::getPublicUserInfo(const QString &user)
3231-{
3232- qDebug() << "should get public user info for user" << user;
3233- // PublicUserInfo userInfo;
3234-
3235-}
3236-
3237-// TODO: move to a common place instead of copying it through *store.cpps
3238-void UserStore::displayException()
3239-{
3240- QString error_message = "Unknown Exception";
3241- try
3242- {
3243- // this function is meant to be called from a catch block
3244- // rethrow the exception to catch it again
3245- throw;
3246- }
3247- catch (const EDAMNotFoundException & e)
3248- {
3249- qDebug() << e.what();
3250- }
3251- catch (const EDAMSystemException & e)
3252- {
3253- qDebug() << e.what();
3254- }
3255- catch (const EDAMUserException & e)
3256- {
3257- qDebug() << e.what();
3258- }
3259- catch (const TTransportException & e)
3260- {
3261- qDebug() << e.what();
3262- }
3263- catch (const TException & e)
3264- {
3265- qDebug() << e.what();
3266- }
3267- catch (const std::exception & e)
3268- {
3269- qDebug() << e.what();
3270- }
3271- catch (...)
3272- {
3273- error_message = "Tried to sync, but something went wrong.\n Unknown exception.";
3274- }
3275-
3276- qDebug() << error_message;
3277- disconnect();
3278+ connect(EvernoteConnection::instance(), &EvernoteConnection::tokenChanged, this, &UserStore::fetchUsername);
3279+
3280+ fetchUsername();
3281+}
3282+
3283+UserStore *UserStore::instance()
3284+{
3285+ if (!s_instance) {
3286+ s_instance = new UserStore();
3287+ }
3288+ return s_instance;
3289+}
3290+
3291+QString UserStore::username() const
3292+{
3293+ return m_username;
3294+}
3295+
3296+void UserStore::fetchUsername()
3297+{
3298+ FetchUsernameJob *job = new FetchUsernameJob();
3299+ connect(job, &FetchUsernameJob::jobDone, this, &UserStore::fetchUsernameJobDone);
3300+ EvernoteConnection::instance()->enqueue(job);
3301+}
3302+
3303+void UserStore::fetchUsernameJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const QString &result)
3304+{
3305+ if (errorCode != EvernoteConnection::ErrorCodeNoError) {
3306+ qWarning() << "Error fetching username:" << errorMessage;
3307+ return;
3308+ }
3309+
3310+ m_username = result;
3311+ emit usernameChanged();
3312 }
3313
3314=== modified file 'src/plugin/Evernote/userstore.h'
3315--- src/plugin/Evernote/userstore.h 2013-11-24 17:03:28 +0000
3316+++ src/plugin/Evernote/userstore.h 2013-12-14 00:07:45 +0000
3317@@ -1,6 +1,9 @@
3318 #ifndef USERSTORE_H
3319 #define USERSTORE_H
3320
3321+#include "evernoteconnection.h"
3322+
3323+//Evernote SDK
3324 #include "UserStore.h"
3325
3326 #include <QObject>
3327@@ -8,17 +11,28 @@
3328 class UserStore : public QObject
3329 {
3330 Q_OBJECT
3331+
3332+ // TODO: Once we need more than just the username, turn this into a class User
3333+ Q_PROPERTY(QString username READ username NOTIFY usernameChanged)
3334+
3335 public:
3336- explicit UserStore(QObject *parent = 0);
3337+ static UserStore* instance();
3338+
3339+ QString username() const;
3340
3341 signals:
3342-
3343-public slots:
3344- void getPublicUserInfo(const QString &user);
3345+ void usernameChanged();
3346+
3347+private slots:
3348+ void fetchUsername();
3349+
3350+ void fetchUsernameJobDone(EvernoteConnection::ErrorCode errorCode, const QString &errorMessage, const QString &result);
3351
3352 private:
3353+ static UserStore* s_instance;
3354+ explicit UserStore(QObject *parent = 0);
3355
3356- void displayException();
3357+ QString m_username;
3358 };
3359
3360 #endif // USERSTORE_H
3361
3362=== modified file 'src/plugin/Evernote/utils/html2enmlconverter.cpp'
3363--- src/plugin/Evernote/utils/html2enmlconverter.cpp 2013-11-25 19:06:38 +0000
3364+++ src/plugin/Evernote/utils/html2enmlconverter.cpp 2013-12-14 00:07:45 +0000
3365@@ -82,3 +82,25 @@
3366
3367 return evml;
3368 }
3369+
3370+QString Html2EnmlConverter::enml2plaintext(const QString &enml)
3371+{
3372+ // output
3373+ QString plaintext;
3374+
3375+ // input
3376+ QXmlStreamReader reader(enml);
3377+
3378+ while (!reader.atEnd() && !reader.hasError()) {
3379+ QXmlStreamReader::TokenType token = reader.readNext();
3380+
3381+ // Write all normal text inside <body> </body> to output
3382+ if (token == QXmlStreamReader::Characters) {
3383+ plaintext.append(reader.text().toString());
3384+ plaintext.append(' ');
3385+ }
3386+ }
3387+
3388+ plaintext.remove('\n');
3389+ return plaintext;
3390+}
3391
3392=== modified file 'src/plugin/Evernote/utils/html2enmlconverter.h'
3393--- src/plugin/Evernote/utils/html2enmlconverter.h 2013-11-25 19:06:38 +0000
3394+++ src/plugin/Evernote/utils/html2enmlconverter.h 2013-12-14 00:07:45 +0000
3395@@ -9,6 +9,8 @@
3396 Html2EnmlConverter();
3397
3398 static QString html2enml(const QString &html);
3399+
3400+ static QString enml2plaintext(const QString &enml);
3401 };
3402
3403 #endif // HTML2ENMLCONVERTER_H

Subscribers

People subscribed via source and target branches