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

Proposed by Michael Zanetti on 2015-02-16
Status: Merged
Approved by: Riccardo Padovani on 2015-02-23
Approved revision: 352
Merged at revision: 348
Proposed branch: lp:~mzanetti/reminders-app/contenthub
Merge into: lp:reminders-app
Prerequisite: lp:~mzanetti/reminders-app/listitemwithactions
Diff against target: 463 lines (+143/-53)
14 files modified
reminders.apparmor (+2/-1)
src/app/qml/components/NotesDelegate.qml (+9/-6)
src/app/qml/ui/NotePage.qml (+1/-1)
src/app/qml/ui/NoteView.qml (+51/-5)
src/app/qml/ui/reminders-scripts.js (+13/-3)
src/libqtevernote/evernoteconnection.cpp (+4/-2)
src/libqtevernote/note.cpp (+2/-0)
src/libqtevernote/note.h (+1/-1)
src/libqtevernote/notesstore.cpp (+4/-4)
src/libqtevernote/resource.cpp (+7/-2)
src/libqtevernote/resource.h (+2/-0)
src/libqtevernote/resourceimageprovider.cpp (+5/-2)
src/libqtevernote/utils/enmldocument.cpp (+40/-26)
src/libqtevernote/utils/enmldocument.h (+2/-0)
To merge this branch: bzr merge lp:~mzanetti/reminders-app/contenthub
Reviewer Review Type Date Requested Status
Riccardo Padovani 2015-02-16 Approve on 2015-02-23
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve on 2015-02-20
Review via email: mp+249894@code.launchpad.net

Commit Message

Add better attachment handling and integrate with ContentHub

To post a comment you must log in.
348. By Michael Zanetti on 2015-02-16

cleanup

349. By Michael Zanetti on 2015-02-16

hide page title when in ContentPeerPicker

350. By Michael Zanetti on 2015-02-20

merge trunk

Riccardo Padovani (rpadovani) wrote :

lgtm, but I'm a bit puzzled by an if, see inline comment please :-)

review: Needs Information
351. By Michael Zanetti on 2015-02-23

drop a debug print

352. By Michael Zanetti on 2015-02-23

cleanup more debug prints

Riccardo Padovani (rpadovani) wrote :

Now it's perfect, thanks :-)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'reminders.apparmor'
2--- reminders.apparmor 2015-02-12 20:34:11 +0000
3+++ reminders.apparmor 2015-02-23 17:57:16 +0000
4@@ -7,7 +7,8 @@
5 "webview",
6 "push-notification-client",
7 "calendar",
8- "connectivity"
9+ "connectivity",
10+ "content_exchange_source"
11 ],
12 "policy_version": 1.2
13 }
14\ No newline at end of file
15
16=== modified file 'src/app/qml/components/NotesDelegate.qml'
17--- src/app/qml/components/NotesDelegate.qml 2015-02-23 11:31:34 +0000
18+++ src/app/qml/components/NotesDelegate.qml 2015-02-23 17:57:16 +0000
19@@ -94,15 +94,10 @@
20 anchors.fill: parent
21 spacing: 0
22
23- Rectangle {
24+ Item {
25 Layout.fillWidth: true
26 Layout.fillHeight: true
27
28- gradient: Gradient {
29- GradientStop{ position: 0.8; color: "transparent" }
30- GradientStop{ position: 1; color: "#d9d9d9" }
31- }
32-
33 RowLayout {
34 anchors.fill: parent
35 anchors.margins: units.gu(1)
36@@ -177,6 +172,14 @@
37 fillMode: Image.PreserveAspectCrop
38 }
39 }
40+ Rectangle {
41+ anchors.fill: parent
42+ gradient: Gradient {
43+ GradientStop{ position: 0.8; color: "transparent" }
44+ GradientStop{ position: 1; color: "#d9d9d9" }
45+ }
46+ }
47 }
48+
49 }
50 }
51
52=== modified file 'src/app/qml/ui/NotePage.qml'
53--- src/app/qml/ui/NotePage.qml 2014-12-10 18:09:10 +0000
54+++ src/app/qml/ui/NotePage.qml 2015-02-23 17:57:16 +0000
55@@ -23,7 +23,7 @@
56
57 Page {
58 id: root
59- title: noteView.title || i18n.tr("Untitled")
60+ title: noteView.title
61 property alias note: noteView.note
62
63 signal editNote(var note)
64
65=== modified file 'src/app/qml/ui/NoteView.qml'
66--- src/app/qml/ui/NoteView.qml 2014-12-10 18:09:10 +0000
67+++ src/app/qml/ui/NoteView.qml 2015-02-23 17:57:16 +0000
68@@ -19,12 +19,14 @@
69 import QtQuick 2.3
70 import Ubuntu.Components 1.1
71 import com.canonical.Oxide 1.0
72+import Ubuntu.Content 1.0
73 import Evernote 0.1
74 import "../components"
75
76 Item {
77 id: root
78- property string title: note ? note.title : ""
79+ property string title: contentPeerPicker.visible ? ""
80+ : note ? note.title : i18n.tr("Untitled")
81 property var note: null
82
83 signal openTaggedNotes(string title, string tagGuid)
84@@ -40,7 +42,7 @@
85
86 userScripts: [
87 UserScript {
88- context: 'reminders://todo'
89+ context: 'reminders://interaction'
90 url: Qt.resolvedUrl("reminders-scripts.js");
91 }
92 ]
93@@ -70,16 +72,32 @@
94
95 messageHandlers: [
96 ScriptMessageHandler {
97- msgId: 'todo'
98- contexts: ['reminders://todo']
99+ msgId: 'interaction'
100+ contexts: ['reminders://interaction']
101 callback: function(message, frame) {
102 var data = message.args;
103
104 switch (data.type) {
105- case "checkboxChanged":
106+ case "checkboxChanged":
107 note.markTodo(data.todoId, data.checked);
108 NotesStore.saveNote(note.guid);
109 break;
110+ case "attachmentOpened":
111+ var filePath = root.note.resource(data.resourceHash).hashedFilePath;
112+ contentPeerPicker.filePath = filePath;
113+
114+ if (data.mediaType == "application/pdf") {
115+ contentPeerPicker.contentType = ContentType.Documents;
116+ } else if (data.mediaType.split("/")[0] == "audio" ) {
117+ contentPeerPicker.contentType = ContentType.Music;
118+ } else if (data.mediaType.split("/")[0] == "image" ) {
119+ contentPeerPicker.contentType = ContentType.Pictures;
120+ } else if (data.mediaType == "application/octet-stream" ) {
121+ contentPeerPicker.contentType = ContentType.All;
122+ } else {
123+ contentPeerPicker.contentType = ContentType.Unknown;
124+ }
125+ contentPeerPicker.visible = true;
126 }
127 }
128 }
129@@ -121,4 +139,32 @@
130 }
131 }
132 }
133+
134+ ContentItem {
135+ id: exportItem
136+ name: i18n.tr("Attachment")
137+ }
138+
139+ ContentPeerPicker {
140+ id: contentPeerPicker
141+ visible: false
142+ contentType: ContentType.Unknown
143+ handler: ContentHandler.Destination
144+ anchors.fill: parent
145+
146+ property string filePath: ""
147+ onPeerSelected: {
148+ var transfer = peer.request();
149+ if (transfer.state === ContentTransfer.InProgress) {
150+ var items = new Array()
151+ var path = contentPeerPicker.filePath;
152+ exportItem.url = path
153+ items.push(exportItem);
154+ transfer.items = items;
155+ transfer.state = ContentTransfer.Charged;
156+ }
157+ contentPeerPicker.visible = false
158+ }
159+ onCancelPressed: contentPeerPicker.visible = false
160+ }
161 }
162
163=== modified file 'src/app/qml/ui/reminders-scripts.js'
164--- src/app/qml/ui/reminders-scripts.js 2014-07-14 15:40:30 +0000
165+++ src/app/qml/ui/reminders-scripts.js 2015-02-23 17:57:16 +0000
166@@ -1,12 +1,22 @@
167 function handleClickEvent(event) {
168 var todoTag = "en-todo";
169- if (event.srcElement.id.slice(0, todoTag.length) === todoTag) {
170+ var attachmentTag = "en-attachment";
171+
172+ var idFields = event.srcElement.id.split("/");
173+ if (idFields[0] === todoTag) {
174 message = new Object;
175 message.type = "checkboxChanged";
176- message.todoId = event.srcElement.id;
177+ message.todoId = idFields[1];
178 message.checked = event.srcElement.checked;
179- oxide.sendMessage('todo', message);
180+ oxide.sendMessage('interaction', message);
181+ } else if (idFields[0] === attachmentTag) {
182+ message = new Object;
183+ message.type = "attachmentOpened";
184+ message.resourceHash = idFields[1];
185+ message.mediaType = idFields[2] + "/" + idFields[3]
186+ oxide.sendMessage('interaction', message);
187 }
188+
189 }
190
191 var doc = document.documentElement;
192
193=== modified file 'src/libqtevernote/evernoteconnection.cpp'
194--- src/libqtevernote/evernoteconnection.cpp 2014-12-14 20:19:58 +0000
195+++ src/libqtevernote/evernoteconnection.cpp 2015-02-23 17:57:16 +0000
196@@ -161,8 +161,10 @@
197 m_errorMessage.clear();
198 emit errorChanged();
199
200- m_notesStoreHttpClient->close();
201- m_userStoreHttpClient->close();
202+ try {
203+ m_notesStoreHttpClient->close();
204+ m_userStoreHttpClient->close();
205+ } catch (...) {}
206 emit isConnectedChanged();
207 }
208
209
210=== modified file 'src/libqtevernote/note.cpp'
211--- src/libqtevernote/note.cpp 2015-02-12 22:57:46 +0000
212+++ src/libqtevernote/note.cpp 2015-02-23 17:57:16 +0000
213@@ -501,9 +501,11 @@
214 return m_resources.value(hash);
215 }
216
217+ qDebug() << "adding resource" << fileName << type;
218 Resource *resource = new Resource(data, hash, fileName, type, this);
219 m_resources.insert(hash, resource);
220 emit resourcesChanged();
221+ emit contentChanged();
222
223 QSettings infoFile(m_infoFile, QSettings::IniFormat);
224 infoFile.beginGroup("resources");
225
226=== modified file 'src/libqtevernote/note.h'
227--- src/libqtevernote/note.h 2014-12-16 21:01:28 +0000
228+++ src/libqtevernote/note.h 2015-02-23 17:57:16 +0000
229@@ -148,7 +148,7 @@
230 bool conflicting() const;
231
232 QStringList resourceUrls() const;
233- Resource* resource(const QString &hash);
234+ Q_INVOKABLE Resource* resource(const QString &hash);
235 QList<Resource*> resources() const;
236 Resource *addResource(const QByteArray &data, const QString &hash, const QString &fileName, const QString &type);
237
238
239=== modified file 'src/libqtevernote/notesstore.cpp'
240--- src/libqtevernote/notesstore.cpp 2015-02-12 21:57:51 +0000
241+++ src/libqtevernote/notesstore.cpp 2015-02-23 17:57:16 +0000
242@@ -787,7 +787,7 @@
243 qDebug() << "refetching for image";
244 refreshWithResourceData = true;
245 }
246- roles << RoleResourceUrls;
247+ roles << RoleHtmlContent << RoleEnmlContent << RoleResourceUrls;
248 }
249
250 if (what == FetchNoteJob::LoadContent) {
251@@ -822,10 +822,10 @@
252 if (refreshWithResourceData) {
253 qDebug() << "refreshWithResourceData";
254 refreshNoteContent(note->guid(), FetchNoteJob::LoadResources);
255+ } else {
256+ syncToCacheFile(note); // Syncs into the list cache
257+ note->syncToCacheFile(); // Syncs note's content into notes cache
258 }
259-
260- syncToCacheFile(note); // Syncs into the list cache
261- note->syncToCacheFile(); // Syncs note's content into notes cache
262 }
263
264 void NotesStore::refreshNotebooks()
265
266=== modified file 'src/libqtevernote/resource.cpp'
267--- src/libqtevernote/resource.cpp 2015-02-12 20:30:07 +0000
268+++ src/libqtevernote/resource.cpp 2015-02-23 17:57:16 +0000
269@@ -35,7 +35,7 @@
270 m_type(type)
271 {
272
273- m_filePath = QStandardPaths::standardLocations(QStandardPaths::CacheLocation).first() + "/" + NotesStore::instance()->username() + "/" + hash + "." + type.split('/').last();
274+ m_filePath = QStandardPaths::standardLocations(QStandardPaths::CacheLocation).first() + "/" + NotesStore::instance()->username() + "/" + hash + "." + m_fileName.split('.').last();
275
276 QFile file(m_filePath);
277 if (!data.isEmpty() && !file.exists()) {
278@@ -84,7 +84,7 @@
279 qWarning() << "cannot determine mime type of file" << m_fileName;
280 }
281
282- m_filePath = QStandardPaths::standardLocations(QStandardPaths::CacheLocation).first() + "/" + NotesStore::instance()->username() + "/" + m_hash + "." + m_type.split('/').last();
283+ m_filePath = QStandardPaths::standardLocations(QStandardPaths::CacheLocation).first() + "/" + NotesStore::instance()->username() + "/" + m_hash + "." + m_fileName.split('.').last();
284
285 QFile copy(m_filePath);
286 if (!copy.exists()) {
287@@ -108,6 +108,11 @@
288 return m_type;
289 }
290
291+QString Resource::hashedFilePath() const
292+{
293+ return m_filePath;
294+}
295+
296 QByteArray Resource::imageData(const QSize &size)
297 {
298 if (!m_type.startsWith("image/")) {
299
300=== modified file 'src/libqtevernote/resource.h'
301--- src/libqtevernote/resource.h 2014-10-23 21:27:46 +0000
302+++ src/libqtevernote/resource.h 2015-02-23 17:57:16 +0000
303@@ -32,6 +32,7 @@
304 Q_PROPERTY(QString hash READ hash CONSTANT)
305 Q_PROPERTY(QString fileName READ fileName CONSTANT)
306 Q_PROPERTY(QString type READ type CONSTANT)
307+ Q_PROPERTY(QString hashedFilePath READ hashedFilePath CONSTANT)
308
309 public:
310 Resource(const QString &path, QObject *parent = 0);
311@@ -43,6 +44,7 @@
312 QString hash() const;
313 QString fileName() const;
314 QString type() const;
315+ QString hashedFilePath() const;
316
317 QByteArray imageData(const QSize &size = QSize());
318
319
320=== modified file 'src/libqtevernote/resourceimageprovider.cpp'
321--- src/libqtevernote/resourceimageprovider.cpp 2015-02-20 18:30:08 +0000
322+++ src/libqtevernote/resourceimageprovider.cpp 2015-02-23 17:57:16 +0000
323@@ -32,10 +32,13 @@
324 }
325 image = QImage::fromData(NotesStore::instance()->note(noteGuid)->resource(resourceHash)->imageData(tmpSize));
326 } else if (mediaType.startsWith("audio")) {
327- image.load("/usr/share/icons/ubuntu-mobile/actions/scalable/media-playback-start.svg");
328+ image.load("/usr/share/icons/suru/mimetypes/scalable/audio-x-generic-symbolic.svg");
329+ } else if (mediaType == "application/pdf") {
330+ image.load("/usr/share/icons/suru/mimetypes/scalable/application-pdf-symbolic.svg");
331 } else {
332- image.load("/usr/share/icons/ubuntu-mobile/actions/scalable/help.svg");
333+ image.load("/usr/share/icons/suru/mimetypes/scalable/empty-symbolic.svg");
334 }
335+
336 *size = image.size();
337 return image;
338 }
339
340=== modified file 'src/libqtevernote/utils/enmldocument.cpp'
341--- src/libqtevernote/utils/enmldocument.cpp 2014-12-14 23:31:19 +0000
342+++ src/libqtevernote/utils/enmldocument.cpp 2015-02-23 17:57:16 +0000
343@@ -157,15 +157,11 @@
344 writer.writeStartElement("img");
345 if (mediaType.startsWith("image")) {
346 if (type == TypeRichText) {
347- QUrl url("image://resource/" + mediaType);
348- QUrlQuery arguments;
349- arguments.addQueryItem("noteGuid", noteGuid);
350- arguments.addQueryItem("hash", hash);
351- url.setQuery(arguments);
352- writer.writeAttribute("src", url.toString());
353+ writer.writeAttribute("src", composeMediaTypeUrl(mediaType, noteGuid, hash));
354 } else if (type == TypeHtml) {
355 QString imagePath = QStandardPaths::standardLocations(QStandardPaths::CacheLocation).first() + "/" + NotesStore::instance()->username() + "/" + hash + "." + mediaType.split('/').last();
356 writer.writeAttribute("src", imagePath);
357+ writer.writeAttribute("id", "en-attachment/" + hash + "/" + mediaType);
358 }
359
360 //set the width
361@@ -183,29 +179,37 @@
362 }
363 } else if (mediaType.startsWith("audio")) {
364 if (type == TypeRichText) {
365- QUrl url("image://resource/" + mediaType);
366- QUrlQuery arguments;
367- arguments.addQueryItem("noteGuid", noteGuid);
368- arguments.addQueryItem("hash", hash);
369- url.setQuery(arguments);
370- writer.writeAttribute("src", url.toString());
371- } else if (type == TypeHtml) {
372- QString imagePath = "file:///usr/share/icons/ubuntu-mobile/actions/scalable/media-playback-start.svg";
373- writer.writeAttribute("src", imagePath);
374- writer.writeCharacters(NotesStore::instance()->note(noteGuid)->resource(hash)->fileName());
375+ writer.writeAttribute("src", composeMediaTypeUrl(mediaType, noteGuid, hash));
376+ } else if (type == TypeHtml) {
377+ QString imagePath = "file:///usr/share/icons/suru/mimetypes/scalable/audio-x-generic-symbolic.svg";
378+ writer.writeAttribute("src", imagePath);
379+ writer.writeAttribute("id", "en-attachment/" + hash + "/" + mediaType);
380+ if (NotesStore::instance()->note(noteGuid)->resource(hash)) {
381+ writer.writeCharacters(NotesStore::instance()->note(noteGuid)->resource(hash)->fileName());
382+ }
383+ }
384+ } else if (mediaType == "application/pdf") {
385+ if (type == TypeRichText) {
386+ writer.writeAttribute("src", composeMediaTypeUrl(mediaType, noteGuid, hash));
387+ } else if (type == TypeHtml) {
388+ QString imagePath = "file:///usr/share/icons/suru/mimetypes/scalable/application-pdf-symbolic.svg";
389+ writer.writeAttribute("src", imagePath);
390+ writer.writeAttribute("id", "en-attachment/" + hash + "/" + mediaType);
391+ if (NotesStore::instance()->note(noteGuid)->resource(hash)) {
392+ writer.writeCharacters(NotesStore::instance()->note(noteGuid)->resource(hash)->fileName());
393+ }
394 }
395 } else {
396+ qDebug() << "unknown mediatype" << mediaType;
397 if (type == TypeRichText) {
398- QUrl url("image://resource/" + mediaType);
399- QUrlQuery arguments;
400- arguments.addQueryItem("noteGuid", noteGuid);
401- arguments.addQueryItem("hash", hash);
402- url.setQuery(arguments);
403- writer.writeAttribute("src", url.toString());
404+ writer.writeAttribute("src", composeMediaTypeUrl(mediaType, noteGuid, hash));
405 } else if (type == TypeHtml) {
406- QString imagePath = "file:///usr/share/icons/ubuntu-mobile/actions/scalable/help.svg";
407+ QString imagePath = "file:///usr/share/icons/suru/mimetypes/scalable/empty-symbolic.svg";
408 writer.writeAttribute("src", imagePath);
409- writer.writeCharacters(NotesStore::instance()->note(noteGuid)->resource(hash)->fileName());
410+ writer.writeAttribute("id", "en-attachment/" + hash + "/" + mediaType);
411+ if (NotesStore::instance()->note(noteGuid)->resource(hash)) {
412+ writer.writeCharacters(NotesStore::instance()->note(noteGuid)->resource(hash)->fileName());
413+ }
414 }
415 }
416 }
417@@ -225,7 +229,7 @@
418 writer.writeAttribute("height", QString::number(gu(2)));
419 } else if (type == TypeHtml){
420 writer.writeStartElement("input");
421- writer.writeAttribute("id", "en-todo" + QString::number(todoIndex++));
422+ writer.writeAttribute("id", "en-todo/" + QString::number(todoIndex++));
423 writer.writeAttribute("type", "checkbox");
424 if (checked) {
425 writer.writeAttribute("checked", "true");
426@@ -283,6 +287,16 @@
427 return px * ppgu;
428 }
429
430+QString EnmlDocument::composeMediaTypeUrl(const QString &mediaType, const QString &noteGuid, const QString &hash) const
431+{
432+ QUrl url("image://resource/" + mediaType);
433+ QUrlQuery arguments;
434+ arguments.addQueryItem("noteGuid", noteGuid);
435+ arguments.addQueryItem("hash", hash);
436+ url.setQuery(arguments);
437+ return url.toString();
438+}
439+
440 void EnmlDocument::setRichText(const QString &richText)
441 {
442 // output
443@@ -408,7 +422,7 @@
444 writer.writeDTD("<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml2.dtd\">");
445
446 QString tmp = todoId;
447- int todoIndex = tmp.remove("en-todo").toInt();
448+ int todoIndex = tmp.toInt();
449 int todoCounter = 0;
450
451 while (!reader.atEnd() && !reader.hasError()) {
452
453=== modified file 'src/libqtevernote/utils/enmldocument.h'
454--- src/libqtevernote/utils/enmldocument.h 2014-11-10 00:54:16 +0000
455+++ src/libqtevernote/utils/enmldocument.h 2015-02-23 17:57:16 +0000
456@@ -53,6 +53,8 @@
457
458 qreal gu(qreal px) const;
459
460+ QString composeMediaTypeUrl(const QString &mediaType, const QString &noteGuid, const QString &hash) const;
461+
462 private:
463 QString m_enml;
464

Subscribers

People subscribed via source and target branches