Merge lp:~verzegnassi-stefano/ubuntu-docviewer-app/content-hub-support into lp:ubuntu-docviewer-app/trunk

Proposed by Stefano Verzegnassi
Status: Merged
Approved by: Stefano Verzegnassi
Approved revision: 45
Merged at revision: 39
Proposed branch: lp:~verzegnassi-stefano/ubuntu-docviewer-app/content-hub-support
Merge into: lp:ubuntu-docviewer-app/trunk
Prerequisite: lp:~verzegnassi-stefano/ubuntu-docviewer-app/fix-1387651-1387023
Diff against target: 431 lines (+216/-35)
14 files modified
CMakeLists.txt (+2/-2)
docviewer-content.json (+7/-0)
docviewer.apparmor (+4/-2)
manifest.json.in (+4/-3)
src/app/main.cpp (+3/-0)
src/app/qml/ContentHubProxy.qml (+38/-0)
src/app/qml/DetailsPage.qml (+3/-2)
src/app/qml/ErrorDialog.qml (+16/-0)
src/app/qml/ImageView.qml (+16/-0)
src/app/qml/PdfView.qml (+13/-1)
src/app/qml/TextView.qml (+16/-0)
src/app/qml/WelcomePage.qml (+51/-0)
src/app/qml/ubuntu-docviewer-app.qml (+35/-22)
tests/autopilot/ubuntu_docviewer_app/tests/test_docviewer.py (+8/-3)
To merge this branch: bzr merge lp:~verzegnassi-stefano/ubuntu-docviewer-app/content-hub-support
Reviewer Review Type Date Requested Status
Arthur Mello (community) Approve
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Ubuntu Document Viewer Developers Pending
Review via email: mp+240331@code.launchpad.net

Commit message

Added ContentHub support

Description of the change

Now we support ContentHub to load documents through other apps.
There are two ways to load a document on the device:
1) From the Application scope: a "welcome" page is shown and user can choose a peer from the list.
2) From an external app: e.g. ubuntu-filemanager-app. docviewer-app will appear in the list of apps that can import that type of content.

KNOWN ISSUES:
* On a device, 'Creation Date' always refers to the moment we import some content from the ContentHub. This is because ContentHub creates a new copy of the file in "$HOME/.cache".

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)
42. By Stefano Verzegnassi

Fixed autopilot error: 'Too many blank lines'

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
43. By Stefano Verzegnassi

Added header backAction in imageView and textView

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
44. By Stefano Verzegnassi

It's called head.backAction...

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
45. By Stefano Verzegnassi

Fixed issue with ContentPeerPicker (binding loop for visible property while importing a file from an external source)

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Arthur Mello (artmello) wrote :

Code looks good to me.
I tested the branch opening PDF files from the Browser and the GMail web app and it worked as expected.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2014-10-21 13:23:11 +0000
3+++ CMakeLists.txt 2014-11-04 18:55:53 +0000
4@@ -54,11 +54,11 @@
5 set(QT_IMPORTS_DIR "/lib/${ARCH_TRIPLET}")
6 set(BIN_DIR /lib/${ARCH_TRIPLET}/bin)
7 set(DATA_DIR /)
8- set (ICON ${ICON_FILE})
9+ set(ICON ${ICON_FILE})
10 set(DESKTOP_DIR ${DATA_DIR})
11 set(URLS_DIR ${DATA_DIR})
12 configure_file(manifest.json.in ${CMAKE_CURRENT_BINARY_DIR}/manifest.json)
13- install(FILES ${CMAKE_CURRENT_BINARY_DIR}/manifest.json docviewer.apparmor
14+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/manifest.json docviewer.apparmor docviewer-content.json
15 DESTINATION ${CMAKE_INSTALL_PREFIX})
16 # Make the click files visible in Qt Creator
17 file(GLOB CLICK_FILES
18
19=== added file 'docviewer-content.json'
20--- docviewer-content.json 1970-01-01 00:00:00 +0000
21+++ docviewer-content.json 2014-11-04 18:55:53 +0000
22@@ -0,0 +1,7 @@
23+{
24+ "destination": [
25+ "pictures",
26+ "documents",
27+ "unknown"
28+ ]
29+}
30
31=== modified file 'docviewer.apparmor'
32--- docviewer.apparmor 2014-09-24 04:46:27 +0000
33+++ docviewer.apparmor 2014-11-04 18:55:53 +0000
34@@ -1,4 +1,6 @@
35 {
36- "policy_groups": [],
37+ "policy_groups": [
38+ "content_exchange"
39+ ],
40 "policy_version": 1.2
41-}
42\ No newline at end of file
43+}
44
45=== modified file 'manifest.json.in'
46--- manifest.json.in 2014-11-04 18:55:53 +0000
47+++ manifest.json.in 2014-11-04 18:55:53 +0000
48@@ -1,14 +1,15 @@
49 {
50 "description": "Document Viewer application for Ubuntu devices",
51 "framework": "ubuntu-sdk-14.10-qml-dev3",
52- "architecture": "all",
53+ "architecture": "@CLICK_ARCH@",
54 "hooks": {
55 "docviewer": {
56 "apparmor": "docviewer.apparmor",
57- "desktop": "com.ubuntu.docviewer.desktop"
58+ "desktop": "com.ubuntu.docviewer.desktop",
59+ "content-hub": "docviewer-content.json"
60 }
61 },
62- "maintainer": "Stefano Verzegnassi <stefano92.100@gmail.com>",
63+ "maintainer": "Ubuntu App Cats <ubuntu-touch-coreapps@lists.launchpad.net>",
64 "name": "com.ubuntu.docviewer",
65 "title": "Document viewer",
66 "version": "0.1.@BZR_REVNO@"
67
68=== modified file 'src/app/main.cpp'
69--- src/app/main.cpp 2014-10-08 05:09:22 +0000
70+++ src/app/main.cpp 2014-11-04 18:55:53 +0000
71@@ -122,6 +122,9 @@
72 cacheDir.mkpath(cacheDir.absolutePath());
73 }
74
75+ // Expose quit() signal to QML
76+ QObject::connect(view.engine(), SIGNAL(quit()), &a, SLOT(quit()));
77+
78 qDebug() << "using main qml file from:" << qmlfile;
79 view.setSource(QUrl::fromLocalFile(qmlfile));
80 view.show();
81
82=== added file 'src/app/qml/ContentHubProxy.qml'
83--- src/app/qml/ContentHubProxy.qml 1970-01-01 00:00:00 +0000
84+++ src/app/qml/ContentHubProxy.qml 2014-11-04 18:55:53 +0000
85@@ -0,0 +1,38 @@
86+/*
87+ * Copyright (C) 2012-2014 Canonical, Ltd.
88+ *
89+ * This program is free software; you can redistribute it and/or modify
90+ * it under the terms of the GNU General Public License as published by
91+ * the Free Software Foundation; version 3.
92+ *
93+ * This program is distributed in the hope that it will be useful,
94+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
95+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
96+ * GNU General Public License for more details.
97+ *
98+ * You should have received a copy of the GNU General Public License
99+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
100+ */
101+
102+import QtQuick 2.3
103+import Ubuntu.Content 1.1 as ContentHub
104+
105+QtObject {
106+ property QtObject pageStack: null
107+ property list<QtObject> objects: [
108+ Connections {
109+ target: ContentHub.ContentHub
110+
111+ onImportRequested: {
112+ if (transfer.state === ContentHub.ContentTransfer.Charged) {
113+ // We have no signals to know if an import was requested before Component.completed signal
114+ // is emitted. So clear the stack when this occurs.
115+ pageStack.clear()
116+
117+ console.log("[CONTENT-HUB] Incoming Import Request")
118+ file.path = transfer.items[0].url.toString().replace("file://", "");
119+ }
120+ }
121+ }
122+ ]
123+}
124
125=== modified file 'src/app/qml/DetailsPage.qml'
126--- src/app/qml/DetailsPage.qml 2014-10-28 22:41:46 +0000
127+++ src/app/qml/DetailsPage.qml 2014-11-04 18:55:53 +0000
128@@ -6,6 +6,8 @@
129
130 Page {
131 id: detailsPage
132+ objectName: "detailsPage"
133+
134 title: i18n.tr("Details")
135
136 Column {
137@@ -22,7 +24,6 @@
138
139 ListItem.Subtitled {
140 text: i18n.tr("Created")
141- // FIXME: the creationTime property is not yet available
142 subText: file.creationTime.toLocaleString(Qt.locale())
143 }
144
145@@ -35,7 +36,7 @@
146 id: mimetypeItem
147 objectName: "mimetypeItem"
148 text: i18n.tr("MIME type")
149- subText: mainView.mimetype
150+ subText: file.mimetype
151 }
152 }
153 }
154
155=== added file 'src/app/qml/ErrorDialog.qml'
156--- src/app/qml/ErrorDialog.qml 1970-01-01 00:00:00 +0000
157+++ src/app/qml/ErrorDialog.qml 2014-11-04 18:55:53 +0000
158@@ -0,0 +1,16 @@
159+import QtQuick 2.3
160+import Ubuntu.Components 1.1
161+import Ubuntu.Components.Popups 1.0
162+
163+Dialog {
164+ id: errorDialogue
165+ title: i18n.tr("Error")
166+ text: i18n.tr("File does not exist")
167+
168+ Button {
169+ text: i18n.tr("Close")
170+ color: "red"
171+
172+ onClicked: Qt.quit();
173+ }
174+}
175
176=== modified file 'src/app/qml/ImageView.qml'
177--- src/app/qml/ImageView.qml 2014-10-20 20:31:41 +0000
178+++ src/app/qml/ImageView.qml 2014-11-04 18:55:53 +0000
179@@ -7,8 +7,24 @@
180 id: pageMain
181 title: Utils.getNameOfFile(file.path);
182
183+ head.backAction: Action {
184+ iconName: "back"
185+ text: (pageStack.depth > 1) ? i18n.tr("Back") : i18n.tr("Close")
186+ onTriggered: {
187+ if (pageStack.depth > 1) {
188+ // Go back to Welcome page
189+ pageStack.pop();
190+ } else {
191+ // File has been imported through Content Hub (or was not chosen through WelcomePage)
192+ // Close the application and show our source app (e.g. ubuntu-filemanager-app if used to open a document)
193+ Qt.quit()
194+ }
195+ }
196+ }
197+
198 head.actions: [
199 Action {
200+ objectName: "detailsAction"
201 text: i18n.tr("Details")
202 iconName: "info"
203 onTriggered: pageStack.push(Qt.resolvedUrl("DetailsPage.qml"))
204
205=== modified file 'src/app/qml/PdfView.qml'
206--- src/app/qml/PdfView.qml 2014-11-04 18:55:53 +0000
207+++ src/app/qml/PdfView.qml 2014-11-04 18:55:53 +0000
208@@ -47,7 +47,7 @@
209 /* FIXME: Don't set 'path' property directly, but set it through onCompleted signal.
210 By doing otherwise, PDF pages are loaded two times, but only
211 the first delegates are working. Asking to the image provider
212- to get the second ones makes the app instable.
213+ to get the second ones, makes the app instable.
214 (e.g. We have a PDF document with 10 pages. The plugin loads
215 them twice - 2x10 = 20 pages - but only the first 10 are shown.
216 While trying to get the 11th, the app crashes). */
217@@ -126,6 +126,17 @@
218
219 backAction: Action {
220 iconName: "back"
221+ text: (pageStack.depth > 1) ? i18n.tr("Back") : i18n.tr("Close")
222+ onTriggered: {
223+ if (pageStack.depth > 1) {
224+ // Go back to Welcome page
225+ pageStack.pop();
226+ } else {
227+ // File has been imported through Content Hub (or was not chosen through WelcomePage)
228+ // Close the application and show our source app (e.g. ubuntu-filemanager-app if used to open a document)
229+ Qt.quit()
230+ }
231+ }
232 }
233
234 actions: [
235@@ -143,6 +154,7 @@
236 },
237
238 Action {
239+ objectName: "detailsAction"
240 text: i18n.tr("Details")
241 iconName: "info"
242 onTriggered: pageStack.push(Qt.resolvedUrl("DetailsPage.qml"))
243
244=== modified file 'src/app/qml/TextView.qml'
245--- src/app/qml/TextView.qml 2014-10-21 15:15:11 +0000
246+++ src/app/qml/TextView.qml 2014-11-04 18:55:53 +0000
247@@ -8,8 +8,24 @@
248 id: pageMain
249 title: Utils.getNameOfFile(file.path);
250
251+ head.backAction: Action {
252+ iconName: "back"
253+ text: (pageStack.depth > 1) ? i18n.tr("Back") : i18n.tr("Close")
254+ onTriggered: {
255+ if (pageStack.depth > 1) {
256+ // Go back to Welcome page
257+ pageStack.pop();
258+ } else {
259+ // File has been imported through Content Hub (or was not chosen through WelcomePage)
260+ // Close the application and show our source app (e.g. ubuntu-filemanager-app if used to open a document)
261+ Qt.quit()
262+ }
263+ }
264+ }
265+
266 head.actions: [
267 Action {
268+ objectName: "detailsAction"
269 text: i18n.tr("Details")
270 iconName: "info"
271 onTriggered: pageStack.push(Qt.resolvedUrl("DetailsPage.qml"))
272
273=== added file 'src/app/qml/WelcomePage.qml'
274--- src/app/qml/WelcomePage.qml 1970-01-01 00:00:00 +0000
275+++ src/app/qml/WelcomePage.qml 2014-11-04 18:55:53 +0000
276@@ -0,0 +1,51 @@
277+import QtQuick 2.0
278+import Ubuntu.Components 1.1
279+import Ubuntu.Content 1.1
280+
281+Page {
282+ id: picker
283+
284+ property var activeTransfer
285+
286+ ContentTransferHint {
287+ id: transferHint
288+ anchors.fill: parent
289+ activeTransfer: picker.activeTransfer
290+ }
291+
292+ title: i18n.tr("Open with...")
293+ head.sections.model: [i18n.tr("Pictures"), i18n.tr("Documents"), i18n.tr("Unknown")]
294+ head.backAction: Action {
295+ iconName: "close"
296+ text: i18n.tr("Close")
297+ onTriggered: Qt.quit()
298+ }
299+
300+ ContentPeerPicker {
301+ showTitle: false
302+
303+ contentType: {
304+ switch (picker.head.sections.selectedIndex) {
305+ case 0:
306+ return ContentType.Pictures
307+ case 1:
308+ return ContentType.Documents
309+ case 2:
310+ return ContentType.Unknown
311+ }
312+ }
313+ handler: ContentHandler.Source
314+
315+ onPeerSelected: picker.activeTransfer = peer.request();
316+ }
317+
318+ Connections {
319+ target: picker.activeTransfer ? picker.activeTransfer : null
320+ onStateChanged: {
321+ if (picker.activeTransfer.state === ContentTransfer.Charged) {
322+ file.path = picker.activeTransfer.items[0].url.toString().replace("file://", "")
323+ console.log("[CONTENT-HUB] Content imported!")
324+ }
325+ }
326+ }
327+}
328
329=== modified file 'src/app/qml/ubuntu-docviewer-app.qml'
330--- src/app/qml/ubuntu-docviewer-app.qml 2014-11-04 18:55:53 +0000
331+++ src/app/qml/ubuntu-docviewer-app.qml 2014-11-04 18:55:53 +0000
332@@ -15,11 +15,11 @@
333 width: units.gu(50)
334 height: units.gu(75)
335
336- property string mimetype: "none"
337-
338- Arguments {
339+ Arguments {
340 id: args
341
342+ // It returns "expected argument" message when not specified a path.
343+ // It works anyway, but it may be worth to use Argument{} in future
344 defaultArgument.help: "Path of the document"
345 defaultArgument.valueNames: ["path"]
346 }
347@@ -27,29 +27,42 @@
348 File {
349 objectName: "fileObject"
350 id: file
351- path: args.defaultArgument.at(0)
352-
353- onMimetypeChanged: mainView.mimetype = LoadComponent.load(file.mimetype);
354- }
355-
356- PageStack {
357- id: pageStack
358-
359- Component {
360- DetailsPage {
361- objectName: "TabDetails"
362- id: tabDetails;
363+
364+ onMimetypeChanged: LoadComponent.load(mimetype)
365+ onErrorChanged: { if (error == -1); PopupUtils.open(errorDialog) }
366+ }
367+
368+ Component.onCompleted: {
369+ // Check if a value has been specified for "path" argument
370+ if (args.defaultArgument.at(0)) {
371+ // If so, send the path to the File plugin
372+ console.log("Path argument is:", args.defaultArgument.at(0))
373+ file.path = args.defaultArgument.at(0)
374+ } else {
375+ // Otherwise, push a welcome screen in the stack
376+ pageStack.push(Qt.resolvedUrl("WelcomePage.qml"))
377+ }
378+ }
379+
380+ // Content Importer
381+ Loader {
382+ id: contentHubLoader
383+
384+ asynchronous: true
385+ source: Qt.resolvedUrl("ContentHubProxy.qml")
386+ onStatusChanged: {
387+ if (status === Loader.Ready) {
388+ item.pageStack = pageStack
389 }
390 }
391 }
392
393- Component {
394- id: unknownTypeDialog
395- UnknownTypeDialog {}
396- }
397-
398- function runUnknownTypeDialog()
399- {
400+ function runUnknownTypeDialog() {
401 PopupUtils.open(unknownTypeDialog);
402 }
403+
404+ PageStack { id: pageStack }
405+
406+ Component { id: errorDialog; ErrorDialog {} }
407+ Component { id: unknownTypeDialog; UnknownTypeDialog {} }
408 }
409
410=== modified file 'tests/autopilot/ubuntu_docviewer_app/tests/test_docviewer.py'
411--- tests/autopilot/ubuntu_docviewer_app/tests/test_docviewer.py 2014-10-28 22:01:16 +0000
412+++ tests/autopilot/ubuntu_docviewer_app/tests/test_docviewer.py 2014-11-04 18:55:53 +0000
413@@ -74,10 +74,15 @@
414 self.check_mimeType()
415
416 def check_mimeType(self):
417+ # Click "Details" action in the header
418+ header = self.main_view.get_header()
419+ header.click_action_button('detailsAction')
420+
421+ mimetypeItem = self.main_view.select_single(
422+ "Subtitled", objectName="mimetypeItem")
423+
424 self.assertThat(
425- self.app.select_single("MainView",
426- objectName="docviewer").mimetype,
427- Eventually(NotEquals(False)))
428+ mimetypeItem.subText, Eventually(NotEquals(False)))
429
430 def test_unknown_file_type(self):
431 filePath = 'ubuntu_docviewer_app/files/unknown.type'

Subscribers

People subscribed via source and target branches