Merge lp:~ubuntu-docviewer-dev/ubuntu-docviewer-app/add-poppler-plugin into lp:ubuntu-docviewer-app/trunk

Proposed by David Planella
Status: Merged
Approved by: David Planella
Approved revision: 56
Merged at revision: 35
Proposed branch: lp:~ubuntu-docviewer-dev/ubuntu-docviewer-app/add-poppler-plugin
Merge into: lp:ubuntu-docviewer-app/trunk
Prerequisite: lp:~dpm/ubuntu-docviewer-app/add-plugin
Diff against target: 1115 lines (+830/-135)
19 files modified
.bzrignore (+1/-0)
debian/control (+1/-0)
src/app/qml/PdfPage.qml (+47/-25)
src/app/qml/PdfView.qml (+156/-106)
src/app/qml/ubuntu-docviewer-app.qml (+2/-3)
src/plugin/CMakeLists.txt (+1/-0)
src/plugin/poppler-qml-plugin/CMakeLists.txt (+51/-0)
src/plugin/poppler-qml-plugin/pageImageProvider.cpp (+69/-0)
src/plugin/poppler-qml-plugin/pageImageProvider.h (+35/-0)
src/plugin/poppler-qml-plugin/pagesWorkerThread.cpp (+36/-0)
src/plugin/poppler-qml-plugin/pagesWorkerThread.h (+42/-0)
src/plugin/poppler-qml-plugin/pdfModel.cpp (+186/-0)
src/plugin/poppler-qml-plugin/pdfModel.h (+76/-0)
src/plugin/poppler-qml-plugin/pdfPage.cpp (+36/-0)
src/plugin/poppler-qml-plugin/pdfPage.h (+36/-0)
src/plugin/poppler-qml-plugin/plugin.cpp (+18/-0)
src/plugin/poppler-qml-plugin/plugin.h (+34/-0)
src/plugin/poppler-qml-plugin/qmldir (+2/-0)
tests/autopilot/ubuntu_docviewer_app/tests/test_docviewer.py (+1/-1)
To merge this branch: bzr merge lp:~ubuntu-docviewer-dev/ubuntu-docviewer-app/add-poppler-plugin
Reviewer Review Type Date Requested Status
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Stefano Verzegnassi Approve
Review via email: mp+239918@code.launchpad.net

This proposal supersedes a proposal from 2014-10-28.

Commit message

Use the new Poppler QML plugin (with asynchronous page loading) in Pdf view.

Description of the change

Use the new Poppler QML plugin (with asynchronous page loading) in Pdf view.

To post a comment you must log in.
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:47
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~verzegnassi-stefano/ubuntu-docviewer-app/add-poppler-plugin/+merge/239838/+edit-commit-message

http://91.189.93.70:8080/job/ubuntu-docviewer-app-ci/82/
Executed test runs:
    FAILURE: http://91.189.93.70:8080/job/generic-mediumtests-utopic-python3/1342/console
    FAILURE: http://91.189.93.70:8080/job/ubuntu-docviewer-app-utopic-amd64-ci/54/console

Click here to trigger a rebuild:
http://91.189.93.70:8080/job/ubuntu-docviewer-app-ci/82/rebuild

review: Needs Fixing (continuous-integration)
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
Stefano Verzegnassi (verzegnassi-stefano) :
review: Approve
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2014-10-28 22:26:31 +0000
3+++ .bzrignore 2014-10-28 22:26:31 +0000
4@@ -8,6 +8,7 @@
5 *.cmake
6 CMakeFiles
7 *_automoc.cpp
8+moc_*
9 debian/files
10 debian/app-template/
11 debian/*.debhelper.log
12
13=== modified file 'debian/control'
14--- debian/control 2014-10-28 22:26:31 +0000
15+++ debian/control 2014-10-28 22:26:31 +0000
16@@ -4,6 +4,7 @@
17 Build-Depends: cmake,
18 debhelper (>= 9),
19 intltool,
20+ libpoppler-qt5-dev,
21 pep8,
22 pkg-config,
23 pkg-kde-tools,
24
25=== modified file 'src/app/qml/PdfPage.qml'
26--- src/app/qml/PdfPage.qml 2014-10-28 22:26:31 +0000
27+++ src/app/qml/PdfPage.qml 2014-10-28 22:26:31 +0000
28@@ -1,30 +1,52 @@
29 import QtQuick 2.3
30 import Ubuntu.Components 1.1
31-
32-Image
33-{
34-
35- property double fixedWidth
36-
37- id: imagePage
38- asynchronous: true
39+import QtGraphicalEffects 1.0
40+
41+Rectangle {
42+ id: pdfPage
43 width: parent.width
44- sourceSize.width: fixedWidth
45- fillMode: Image.PreserveAspectCrop
46- source: "image://poppler/page/1"
47-
48- Connections {
49- target: parent
50-
51- onShouldReloadImgChanged: {
52- if (parent.shouldReloadImg)
53- {
54- fixedWidth = parent.width
55- }
56- }
57- }
58-
59- Component.onCompleted: {
60- fixedWidth = parent.width
61+
62+ height: width * (model.height / model.width)
63+
64+ border {
65+ width: 1
66+ color: "#808080"
67+ }
68+
69+ Image {
70+ id: imagePage
71+ anchors {
72+ fill: parent
73+ margins: 1
74+ }
75+ asynchronous: true
76+ sourceSize.width: parent.width - 2
77+ fillMode: Image.PreserveAspectCrop
78+
79+ Component.onCompleted: source = "image://poppler/page/" + (model.index + 1)
80+ }
81+
82+ Rectangle {
83+ anchors.fill: parent
84+ color: "white"
85+ visible: imagePage.status === Image.Loading
86+
87+ ActivityIndicator {
88+ anchors.centerIn: parent
89+ running: parent.visible
90+ }
91+ }
92+
93+ DropShadow {
94+ anchors.fill: parent
95+ cached: true;
96+ horizontalOffset: 0;
97+ verticalOffset: 2;
98+ radius: 8.0;
99+ samples: 16;
100+ color: "#80000000";
101+ smooth: true;
102+ source: parent;
103+ z: -10
104 }
105 }
106
107=== modified file 'src/app/qml/PdfView.qml'
108--- src/app/qml/PdfView.qml 2014-10-28 22:26:31 +0000
109+++ src/app/qml/PdfView.qml 2014-10-28 22:26:31 +0000
110@@ -1,6 +1,6 @@
111 import QtQuick 2.3
112 import Ubuntu.Components 1.1
113-import org.docviewer.poppler 1.0
114+import com.ubuntu.popplerqmlplugin 1.0
115
116 import "utils.js" as Utils
117
118@@ -8,110 +8,160 @@
119 id: pageMain
120 title: Utils.getNameOfFile(file.path);
121
122- head.actions: [
123- Action {
124- text: i18n.tr("Details")
125- iconName: "info"
126- onTriggered: pageStack.push(Qt.resolvedUrl("DetailsPage.qml"))
127- }
128+ // Disable header auto-hide
129+ flickable: null
130+
131+ // TODO: Restore zooming
132+ ListView {
133+ id: pdfView
134+ anchors {
135+ fill: parent
136+ leftMargin: units.gu(2)
137+ rightMargin: units.gu(2)
138+ }
139+ spacing: units.gu(4)
140+
141+ clip: true
142+ focus: false
143+ boundsBehavior: Flickable.StopAtBounds
144+
145+ cacheBuffer: height
146+
147+ highlightFollowsCurrentItem: false
148+ keyNavigationWraps: false
149+
150+ // TODO: Not a good way to have spacing
151+ header: Item {
152+ width: parent.width
153+ height: units.gu(2)
154+ }
155+
156+ footer: Item {
157+ width: parent.width
158+ height: units.gu(2)
159+ }
160+
161+ model: Poppler {
162+ id: poppler
163+ path: file.path
164+
165+ onPagesLoaded: {
166+ activity.running = false;
167+
168+ pdfView.currentIndex = 0
169+
170+ var title = getDocumentInfo("Title")
171+ if (title !== "")
172+ titleLabel.text = title
173+ }
174+ }
175+
176+ delegate: PdfPage {}
177+
178+ onWidthChanged: {
179+ /* On resizing window, pages size changes but contentY is still the same.
180+ For that reason, it shows the wrong page (which is settled at the same contentY).
181+ We need to force flickable to show the current page. */
182+ //pdfView.positionViewAtIndex(currentIndex, ListView.Contain)
183+ }
184+
185+ onContentYChanged: {
186+ // FIXME: On wheeling up, ListView automatically center currentItem to the view.
187+ // This causes some strange "jump" of ~200px in contentY
188+ var i = pdfView.indexAt(pdfView.width * 0.5, contentY + (pdfView.height * 0.5))
189+
190+ if (i < 0) {
191+ // returned index could be -1 when the delegate spacing is shown at the center of the view (e.g. while scrolling pages)
192+ i = pdfView.indexAt(pdfView.width * 0.5, contentY + (pdfView.height * 0.5) + units.gu(4))
193+ }
194+
195+ if (i !== -1) {
196+ currentPageLabel.text = i18n.tr("Page %1 of %2").arg(i + 1).arg(pdfView.count)
197+
198+ if (!pdfView.flickingVertically) {
199+ pdfView.currentIndex = i
200+ }
201+ }
202+ }
203+ }
204+
205+ ActivityIndicator {
206+ id: activity
207+ anchors.centerIn: parent
208+
209+ running: true
210+ }
211+
212+ // *** HEADER ***
213+ state: "default"
214+ states: [
215+ PageHeadState {
216+ name: "default"
217+ head: pageMain.head
218+
219+ contents: Column {
220+ anchors.centerIn: parent
221+
222+ Label {
223+ id: titleLabel
224+ text: Utils.getNameOfFile(file.path)
225+ font.weight: Font.DemiBold
226+ anchors.horizontalCenter: parent.horizontalCenter
227+ }
228+ Label {
229+ id: currentPageLabel
230+ text: i18n.tr("Page %1 of %2").arg(pdfView.currentIndex + 1).arg(pdfView.count)
231+ fontSize: "small"
232+ anchors.horizontalCenter: parent.horizontalCenter
233+ }
234+ }
235+
236+ backAction: Action {
237+ iconName: "back"
238+ }
239+
240+ actions: [
241+ Action {
242+ iconName: "search"
243+ // onTriggered: pageMain.state = "search"
244+ //Disable it until we provide search in Poppler plugin.
245+ enabled: false
246+ },
247+
248+ Action {
249+ iconName: "browser-tabs"
250+ text: "Go to page..."
251+ enabled: false
252+ },
253+
254+ Action {
255+ text: i18n.tr("Details")
256+ iconName: "info"
257+ onTriggered: pageStack.push(Qt.resolvedUrl("DetailsPage.qml"))
258+ }
259+ ]
260+ }
261+
262+ /* PageHeadState {
263+ id: headerState
264+ name: "search"
265+ head: pageMain.head
266+ actions: [
267+ Action {
268+ iconName: "go-up"
269+ },
270+
271+ Action {
272+ iconName: "go-down"
273+ }
274+ ]
275+
276+ backAction: Action {
277+ id: leaveSearchAction
278+ text: "back"
279+ iconName: "back"
280+ onTriggered: pageMain.state = "default"
281+ }
282+ }*/
283 ]
284-
285- Flickable {
286- id: flickable
287- anchors.fill: parent
288-
289- contentHeight: columnPages.height + 10
290- contentWidth: parent.width
291-
292- PinchArea {
293- id: pinchy
294- anchors.fill: columnPages
295- enabled: true
296- pinch.target: flickable
297-
298- property real lastWidth
299- /*property real lastHeight
300- property double p1toC_X
301- property double p1toC_Y
302- property double contentInitX
303- property double contentInitY*/
304-
305- onPinchStarted: {
306- lastWidth = flickable.width
307-
308- /*contentInitX = flickImg.contentX
309- contentInitY = flickImg.contentY*/
310-
311- }
312-
313- onPinchUpdated: {
314-
315- var newWidth = 0;
316-
317- newWidth = lastWidth*pinch.scale;
318-
319- /*if (newWidth < image.startWidth)
320- newWidth = image.startWidth;
321- else if (newWidth > image.sourceSize.width)
322- newWidth = image.sourceSize.width;*/
323-
324- flickable.contentWidth = newWidth;
325-
326- /*flickImg.contentX = contentInitX-(lastWidth-newWidth)/2
327- flickImg.contentY = contentInitY-(lastHeight-image.height)/2*/
328-
329- }
330-
331- onPinchFinished: {
332-
333- columnPages.shouldReloadImg = true;
334- console.log("FINISHED");
335- }
336- }
337-
338-
339- Poppler {
340- id: popplerProp
341- path: file.path
342- }
343-
344- Column {
345- id: columnPages
346-
347- property bool shouldReloadImg : false
348-
349- width: parent.width - 10
350- x: 5
351- y: 5
352- spacing: 10
353-
354- onWidthChanged: {
355- if (!pinchy.pinch.active)
356- shouldReloadImg=true
357- else
358- shouldReloadImg=false
359- }
360-
361- }
362-
363- Component.onCompleted: {
364-
365- var i=0;
366- for(i=1; i <= popplerProp.numPages; i++)
367- {
368- var component = Qt.createComponent("PdfPage.qml");
369-
370- if (component.status === Component.Error)
371- {
372- console.debug("Error creating component");
373- }
374- else
375- {
376- var page = component.createObject(columnPages);
377-
378- page.source = "image://poppler/page/"+i;
379- }
380- }
381- }
382- }
383 }
384
385=== modified file 'src/app/qml/ubuntu-docviewer-app.qml'
386--- src/app/qml/ubuntu-docviewer-app.qml 2014-10-28 22:26:31 +0000
387+++ src/app/qml/ubuntu-docviewer-app.qml 2014-10-28 22:26:31 +0000
388@@ -16,7 +16,7 @@
389 width: units.gu(50)
390 height: units.gu(75)
391
392- property string minetype: "none"
393+ property string mimetype: "none"
394
395 Arguments {
396 id: args
397@@ -30,7 +30,7 @@
398 id: file
399 path: args.defaultArgument.at(0)
400
401- onMimetypeChanged: mainView.minetype = LoadComponent.load(file.mimetype);
402+ onMimetypeChanged: mainView.mimetype = LoadComponent.load(file.mimetype);
403 }
404
405 PageStack {
406@@ -40,7 +40,6 @@
407 DetailsPage {
408 objectName: "TabDetails"
409 id: tabDetails;
410-
411 }
412 }
413 }
414
415=== modified file 'src/plugin/CMakeLists.txt'
416--- src/plugin/CMakeLists.txt 2014-10-28 22:26:31 +0000
417+++ src/plugin/CMakeLists.txt 2014-10-28 22:26:31 +0000
418@@ -1,1 +1,2 @@
419 add_subdirectory(file-qml-plugin)
420+add_subdirectory(poppler-qml-plugin)
421
422=== added directory 'src/plugin/poppler-qml-plugin'
423=== added file 'src/plugin/poppler-qml-plugin/CMakeLists.txt'
424--- src/plugin/poppler-qml-plugin/CMakeLists.txt 1970-01-01 00:00:00 +0000
425+++ src/plugin/poppler-qml-plugin/CMakeLists.txt 2014-10-28 22:26:31 +0000
426@@ -0,0 +1,51 @@
427+cmake_minimum_required(VERSION 2.8.9)
428+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
429+
430+set(PLUGIN_DIR com/ubuntu/popplerqmlplugin)
431+
432+#set cpp flags
433+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-permissive -pedantic -Wall -Wextra -fPIC")
434+
435+# Standard install paths
436+include(GNUInstallDirs)
437+
438+#add the sources to compile
439+set(popplerqmlplugin_SRCS
440+ plugin.cpp
441+ plugin.h
442+ pdfModel.cpp
443+ pdfModel.h
444+ pageImageProvider.cpp
445+ pageImageProvider.h
446+ pagesWorkerThread.cpp
447+ pagesWorkerThread.h
448+ pdfPage.cpp
449+ pdfPage.h
450+ )
451+
452+#should be deprecated in current cmake version
453+#qt5_use_modules(Qml Quick)
454+
455+add_library(popplerqmlplugin MODULE
456+ ${popplerqmlplugin_SRCS}
457+)
458+
459+target_link_libraries(popplerqmlplugin poppler-qt5)
460+
461+qt5_use_modules(popplerqmlplugin Gui Qml Quick)
462+
463+# Copy the plugin, the qmldir file and other assets to the build dir for running in QtCreator
464+if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
465+ add_custom_command(TARGET popplerqmlplugin POST_BUILD
466+ COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR}
467+ COMMENT "Creating plugin directory layout in the build directory"
468+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/qmldir ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR}
469+ COMMENT "Copying the qmldir file to the build directory"
470+ COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:popplerqmlplugin> ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR}
471+ COMMENT "Copying the plugin binary to the build directory"
472+ )
473+endif(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
474+
475+# Install plugin file
476+install(TARGETS popplerqmlplugin DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN_DIR})
477+install(FILES qmldir DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN_DIR})
478
479=== added file 'src/plugin/poppler-qml-plugin/pageImageProvider.cpp'
480--- src/plugin/poppler-qml-plugin/pageImageProvider.cpp 1970-01-01 00:00:00 +0000
481+++ src/plugin/poppler-qml-plugin/pageImageProvider.cpp 2014-10-28 22:26:31 +0000
482@@ -0,0 +1,69 @@
483+/*
484+ * Copyright (C) 2013 Canonical, Ltd.
485+ *
486+ * This program is free software: you can redistribute it and/or modify it
487+ * under the terms of the GNU General Public License version 3, as published
488+ * by the Free Software Foundation.
489+ *
490+ * This program is distributed in the hope that it will be useful, but
491+ * WITHOUT ANY WARRANTY; without even the implied warranties of
492+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
493+ * PURPOSE. See the GNU General Public License for more details.
494+ *
495+ * You should have received a copy of the GNU General Public License along
496+ * with this program. If not, see <http://www.gnu.org/licenses/>.
497+ *
498+ * Author: Anthony Granger <grangeranthony@gmail.com>
499+ */
500+
501+
502+#include <poppler/qt5/poppler-qt5.h>
503+#include <QQuickImageProvider>
504+#include <QDebug>
505+#include <QPaintDevice>
506+
507+#include "pageImageProvider.h"
508+
509+PageImageProvider::PageImageProvider(Poppler::Document *pdfDocument):QQuickImageProvider(QQuickImageProvider::Image)
510+{
511+ this->document = pdfDocument;
512+}
513+
514+QImage PageImageProvider::requestImage(const QString & id, QSize * size, const QSize & requestedSize)
515+{
516+ float scale = 1.0;
517+ QString type = id.section("/", 0, 0);
518+ QImage result;
519+ QSizeF pageSize;
520+ QSizeF pageSizePhys;
521+ float res = 0;
522+ Poppler::Page *page;
523+
524+ if (type == "page")
525+ {
526+ int numPage = id.section("/", 1, 1).toInt();
527+
528+ qDebug() << "Page" << numPage << "requested";
529+
530+ page = document->page(numPage -1);
531+
532+ pageSize = page->pageSizeF();
533+
534+ pageSizePhys.setWidth(pageSize.width() / 72);
535+ //pageSizePhys.setHeight(pageSize.height() / 72);
536+
537+ qDebug() << "Requested size :" << requestedSize.width() << ";" << requestedSize.height();
538+
539+ //if (pageSizePhys.height() >= pageSizePhys.width())
540+ res = requestedSize.width() / pageSizePhys.width();
541+ /*else
542+ res = requestedSize.height() / pageSizePhys.height();*/
543+
544+ qDebug() << "Size :" << pageSizePhys.width() << ";" << pageSizePhys.height();
545+ qDebug() << "Resolution :" << res;
546+
547+ result = page->renderToImage(scale * res, scale * res); //For poppler the first page have the id 0
548+ }
549+
550+ return result;
551+}
552
553=== added file 'src/plugin/poppler-qml-plugin/pageImageProvider.h'
554--- src/plugin/poppler-qml-plugin/pageImageProvider.h 1970-01-01 00:00:00 +0000
555+++ src/plugin/poppler-qml-plugin/pageImageProvider.h 2014-10-28 22:26:31 +0000
556@@ -0,0 +1,35 @@
557+/*
558+ * Copyright (C) 2013 Canonical, Ltd.
559+ *
560+ * This program is free software: you can redistribute it and/or modify it
561+ * under the terms of the GNU General Public License version 3, as published
562+ * by the Free Software Foundation.
563+ *
564+ * This program is distributed in the hope that it will be useful, but
565+ * WITHOUT ANY WARRANTY; without even the implied warranties of
566+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
567+ * PURPOSE. See the GNU General Public License for more details.
568+ *
569+ * You should have received a copy of the GNU General Public License along
570+ * with this program. If not, see <http://www.gnu.org/licenses/>.
571+ *
572+ * Author: Anthony Granger <grangeranthony@gmail.com>
573+ */
574+
575+#ifndef PAGEIMAGEPROVIDER_H
576+#define PAGEIMAGEPROVIDER_H
577+
578+#include <QQuickImageProvider>
579+#include <poppler/qt5/poppler-qt5.h>
580+
581+class PageImageProvider : public QQuickImageProvider
582+{
583+public:
584+ PageImageProvider(Poppler::Document *pdfDocument);
585+ QImage requestImage(const QString & id, QSize * size, const QSize & requestedSize);
586+
587+private:
588+ Poppler::Document *document;
589+};
590+
591+#endif // PAGEIMAGEPROVIDER_H
592
593=== added file 'src/plugin/poppler-qml-plugin/pagesWorkerThread.cpp'
594--- src/plugin/poppler-qml-plugin/pagesWorkerThread.cpp 1970-01-01 00:00:00 +0000
595+++ src/plugin/poppler-qml-plugin/pagesWorkerThread.cpp 2014-10-28 22:26:31 +0000
596@@ -0,0 +1,36 @@
597+/*
598+ * Copyright (C) 2014 Canonical, Ltd.
599+ *
600+ * This program is free software: you can redistribute it and/or modify it
601+ * under the terms of the GNU General Public License version 3, as published
602+ * by the Free Software Foundation.
603+ *
604+ * This program is distributed in the hope that it will be useful, but
605+ * WITHOUT ANY WARRANTY; without even the implied warranties of
606+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
607+ * PURPOSE. See the GNU General Public License for more details.
608+ *
609+ * You should have received a copy of the GNU General Public License along
610+ * with this program. If not, see <http://www.gnu.org/licenses/>.
611+ *
612+ * Author: Stefano Verzegnassi <stefano92.100@gmail.com>
613+ */
614+
615+#include <pagesWorkerThread.h>
616+#include <QDebug>
617+
618+void PDFPagesWorkerThread::run()
619+{
620+ PdfPagesList pages;
621+
622+ for( int i=0; i<m_document->numPages(); i++ ){
623+ pages.append(m_document->page(i));
624+ }
625+
626+ emit resultReady(pages);
627+}
628+
629+void PDFPagesWorkerThread::setDocument(Poppler::Document *document)
630+{
631+ m_document = document;
632+}
633
634=== added file 'src/plugin/poppler-qml-plugin/pagesWorkerThread.h'
635--- src/plugin/poppler-qml-plugin/pagesWorkerThread.h 1970-01-01 00:00:00 +0000
636+++ src/plugin/poppler-qml-plugin/pagesWorkerThread.h 2014-10-28 22:26:31 +0000
637@@ -0,0 +1,42 @@
638+/*
639+ * Copyright (C) 2014 Canonical, Ltd.
640+ *
641+ * This program is free software: you can redistribute it and/or modify it
642+ * under the terms of the GNU General Public License version 3, as published
643+ * by the Free Software Foundation.
644+ *
645+ * This program is distributed in the hope that it will be useful, but
646+ * WITHOUT ANY WARRANTY; without even the implied warranties of
647+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
648+ * PURPOSE. See the GNU General Public License for more details.
649+ *
650+ * You should have received a copy of the GNU General Public License along
651+ * with this program. If not, see <http://www.gnu.org/licenses/>.
652+ *
653+ * Author: Stefano Verzegnassi <stefano92.100@gmail.com>
654+ */
655+
656+#ifndef PAGESWORKERTHREAD_H
657+#define PAGESWORKERTHREAD_H
658+
659+#include <QThread>
660+#include <poppler/qt5/poppler-qt5.h>
661+
662+typedef QList<Poppler::Page*> PdfPagesList;
663+
664+class PDFPagesWorkerThread : public QThread
665+{
666+ Q_OBJECT
667+ void run();
668+
669+public:
670+ void setDocument(Poppler::Document *document);
671+
672+private:
673+ Poppler::Document *m_document;
674+
675+signals:
676+ void resultReady(PdfPagesList pages);
677+};
678+
679+#endif // PAGESWORKERTHREAD_H
680
681=== added file 'src/plugin/poppler-qml-plugin/pdfModel.cpp'
682--- src/plugin/poppler-qml-plugin/pdfModel.cpp 1970-01-01 00:00:00 +0000
683+++ src/plugin/poppler-qml-plugin/pdfModel.cpp 2014-10-28 22:26:31 +0000
684@@ -0,0 +1,186 @@
685+/*
686+ * Copyright (C) 2013 Canonical, Ltd.
687+ *
688+ * This program is free software: you can redistribute it and/or modify it
689+ * under the terms of the GNU General Public License version 3, as published
690+ * by the Free Software Foundation.
691+ *
692+ * This program is distributed in the hope that it will be useful, but
693+ * WITHOUT ANY WARRANTY; without even the implied warranties of
694+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
695+ * PURPOSE. See the GNU General Public License for more details.
696+ *
697+ * You should have received a copy of the GNU General Public License along
698+ * with this program. If not, see <http://www.gnu.org/licenses/>.
699+ *
700+ * Authors: Anthony Granger <grangeranthony@gmail.com>
701+ * Stefano Verzegnassi <stefano92.100@gmail.com>
702+ */
703+
704+#include <pdfModel.h>
705+#include <pdfPage.h>
706+#include <pageImageProvider.h>
707+#include <pagesWorkerThread.h>
708+
709+#include <poppler/qt5/poppler-qt5.h>
710+#include <QDebug>
711+#include <QQmlEngine>
712+#include <QQmlContext>
713+
714+PdfModel::PdfModel(QAbstractListModel *parent):
715+ QAbstractListModel(parent)
716+{
717+ int metatype_id = qRegisterMetaType<PdfPagesList>("PdfPagesList");
718+}
719+
720+QHash<int, QByteArray> PdfModel::roleNames() const
721+{
722+ QHash<int, QByteArray> roles;
723+ roles[WidthRole] = "width";
724+ roles[HeightRole] = "height";
725+ return roles;
726+}
727+
728+int PdfModel::rowCount(const QModelIndex & parent) const
729+{
730+ return m_pages.count();
731+}
732+
733+QVariant PdfModel::data(const QModelIndex & index, int role) const
734+{
735+ if (index.row() < 0 || index.row() > m_pages.count())
736+ return QVariant();
737+
738+ const PdfPage &pdfPage = m_pages.at(index.row());
739+
740+ switch (role) {
741+ case WidthRole:
742+ return pdfPage.width();
743+ case HeightRole:
744+ return pdfPage.height();
745+ default:
746+ return 0;
747+ }
748+}
749+
750+void PdfModel::setPath(QString &pathName)
751+{
752+ if (pathName.isEmpty())
753+ {
754+ return;
755+ }
756+
757+ this->path = pathName;
758+
759+ emit pathChanged(pathName);
760+
761+ if ( !loadDocument(pathName) ) {
762+ return;
763+ }
764+
765+ loadPages();
766+ loadProvider();
767+}
768+
769+int PdfModel::loadDocument(QString &pathName)
770+{
771+ qDebug() << "Loading document...";
772+
773+ if (pathName.isEmpty()) {
774+ qDebug() << "Can't load the document, path is empty.";
775+ return 0;
776+ }
777+
778+ this->document = Poppler::Document::load(pathName);
779+
780+ if (!document || document->isLocked()) {
781+ qDebug() << "ERROR : Can't open the document located at " + pathName;
782+ emit error("Can't open the document located at " + pathName);
783+
784+ delete document;
785+ return 0;
786+ }
787+
788+ qDebug() << "Document loaded successfully !";
789+
790+ document->setRenderHint(Poppler::Document::Antialiasing, true);
791+ document->setRenderHint(Poppler::Document::TextAntialiasing, true);
792+
793+ return 1;
794+}
795+
796+QDateTime PdfModel::getDocumentDate(QString data)
797+{
798+ if (!document) {
799+ return QDateTime();
800+ }
801+
802+ if (data == "CreationDate" || data == "ModDate") {
803+ return document->date(data);
804+ } else {
805+ return QDateTime();
806+ }
807+}
808+
809+QString PdfModel::getDocumentInfo(QString data)
810+{
811+ if (!document) {
812+ return QString("");
813+ }
814+
815+ if (data == "Title" || data == "Subject" || data == "Author" || data == "Creator" || data == "Producer") {
816+ return document->info(data);
817+ } else {
818+ return QString("");
819+ }
820+}
821+
822+int PdfModel::loadPages()
823+{
824+ qDebug() << "Populating model...";
825+
826+ m_pages.clear();
827+
828+ if (!document) {
829+ return 0;
830+ }
831+
832+ PDFPagesWorkerThread *workerThread = new PDFPagesWorkerThread();
833+ workerThread->setDocument(this->document);
834+
835+ connect(workerThread, SIGNAL(resultReady(PdfPagesList)), this, SLOT(populate(PdfPagesList)));
836+ connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
837+ workerThread->start();
838+
839+ return 1;
840+}
841+
842+void PdfModel::populate(PdfPagesList pagesList)
843+{
844+ qDebug() << "Number of pages:" << pagesList.length();
845+
846+ foreach (Poppler::Page *page, pagesList) {
847+ beginInsertRows(QModelIndex(), rowCount(), rowCount());
848+ m_pages << page;
849+ endInsertRows();
850+ }
851+
852+ qDebug() << "Model has been successfully populated!";
853+ emit pagesLoaded();
854+}
855+
856+int PdfModel::loadProvider()
857+{
858+ qDebug() << "Loading image provider...";
859+ QQmlEngine *engine = QQmlEngine::contextForObject(this)->engine();
860+
861+ engine->addImageProvider(QLatin1String("poppler"), new PageImageProvider(document));
862+
863+ qDebug() << "Image provider loaded successfully !";
864+
865+ return 1;
866+}
867+
868+PdfModel::~PdfModel()
869+{
870+}
871
872=== added file 'src/plugin/poppler-qml-plugin/pdfModel.h'
873--- src/plugin/poppler-qml-plugin/pdfModel.h 1970-01-01 00:00:00 +0000
874+++ src/plugin/poppler-qml-plugin/pdfModel.h 2014-10-28 22:26:31 +0000
875@@ -0,0 +1,76 @@
876+/*
877+ * Copyright (C) 2013 Canonical, Ltd.
878+ *
879+ * This program is free software: you can redistribute it and/or modify it
880+ * under the terms of the GNU General Public License version 3, as published
881+ * by the Free Software Foundation.
882+ *
883+ * This program is distributed in the hope that it will be useful, but
884+ * WITHOUT ANY WARRANTY; without even the implied warranties of
885+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
886+ * PURPOSE. See the GNU General Public License for more details.
887+ *
888+ * You should have received a copy of the GNU General Public License along
889+ * with this program. If not, see <http://www.gnu.org/licenses/>.
890+ *
891+ * Author: Anthony Granger <grangeranthony@gmail.com>
892+ * Stefano Verzegnassi <stefano92.100@gmail.com>
893+ */
894+
895+#ifndef PDFMODEL_H
896+#define PDFMODEL_H
897+
898+#include <QAbstractListModel>
899+#include <poppler/qt5/poppler-qt5.h>
900+#include <pdfPage.h>
901+
902+typedef QList<Poppler::Page*> PdfPagesList;
903+
904+class PdfModel : public QAbstractListModel
905+{
906+ Q_OBJECT
907+ Q_DISABLE_COPY(PdfModel)
908+
909+public:
910+ enum Roles {
911+ WidthRole = Qt::UserRole + 1,
912+ HeightRole
913+ };
914+
915+ explicit PdfModel(QAbstractListModel *parent = 0);
916+ virtual ~PdfModel();
917+
918+ QHash<int, QByteArray> roleNames() const;
919+
920+ int rowCount(const QModelIndex & parent = QModelIndex()) const;
921+ QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
922+
923+ Q_PROPERTY(QString path READ getPath WRITE setPath NOTIFY pathChanged)
924+ void setPath(QString &pathName);
925+ QString getPath() const { return path; }
926+
927+ QString path;
928+
929+ Q_INVOKABLE QDateTime getDocumentDate(QString data);
930+ Q_INVOKABLE QString getDocumentInfo(QString data);
931+
932+private:
933+ int loadDocument(QString &pathNAme);
934+ int loadProvider();
935+ int loadPages();
936+
937+ Poppler::Document *document;
938+ QList<PdfPage> m_pages;
939+
940+private slots:
941+ void populate(PdfPagesList pagesList);
942+
943+signals:
944+ void pathChanged(const QString& newPath);
945+ void error(const QString& errorMessage);
946+ void pagesLoaded();
947+};
948+
949+//QML_DECLARE_TYPE(PdfModel)
950+
951+#endif // PDFMODEL_H
952
953=== added file 'src/plugin/poppler-qml-plugin/pdfPage.cpp'
954--- src/plugin/poppler-qml-plugin/pdfPage.cpp 1970-01-01 00:00:00 +0000
955+++ src/plugin/poppler-qml-plugin/pdfPage.cpp 2014-10-28 22:26:31 +0000
956@@ -0,0 +1,36 @@
957+/*
958+ * Copyright (C) 2014 Canonical, Ltd.
959+ *
960+ * This program is free software: you can redistribute it and/or modify it
961+ * under the terms of the GNU General Public License version 3, as published
962+ * by the Free Software Foundation.
963+ *
964+ * This program is distributed in the hope that it will be useful, but
965+ * WITHOUT ANY WARRANTY; without even the implied warranties of
966+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
967+ * PURPOSE. See the GNU General Public License for more details.
968+ *
969+ * You should have received a copy of the GNU General Public License along
970+ * with this program. If not, see <http://www.gnu.org/licenses/>.
971+ *
972+ * Author: Stefano Verzegnassi <stefano92.100@gmail.com>
973+ */
974+
975+#include <pdfPage.h>
976+#include <poppler/qt5/poppler-qt5.h>
977+
978+PdfPage::PdfPage(Poppler::Page *page)
979+{
980+ m_width = page->pageSize().width();
981+ m_height = page->pageSize().height();
982+}
983+
984+int PdfPage::width() const
985+{
986+ return m_width;
987+}
988+
989+int PdfPage::height() const
990+{
991+ return m_height;
992+}
993
994=== added file 'src/plugin/poppler-qml-plugin/pdfPage.h'
995--- src/plugin/poppler-qml-plugin/pdfPage.h 1970-01-01 00:00:00 +0000
996+++ src/plugin/poppler-qml-plugin/pdfPage.h 2014-10-28 22:26:31 +0000
997@@ -0,0 +1,36 @@
998+/*
999+ * Copyright (C) 2014 Canonical, Ltd.
1000+ *
1001+ * This program is free software: you can redistribute it and/or modify it
1002+ * under the terms of the GNU General Public License version 3, as published
1003+ * by the Free Software Foundation.
1004+ *
1005+ * This program is distributed in the hope that it will be useful, but
1006+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1007+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1008+ * PURPOSE. See the GNU General Public License for more details.
1009+ *
1010+ * You should have received a copy of the GNU General Public License along
1011+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1012+ *
1013+ * Author: Stefano Verzegnassi <stefano92.100@gmail.com>
1014+ */
1015+
1016+#ifndef PDFPAGE_H
1017+#define PDFPAGE_H
1018+
1019+#include <poppler/qt5/poppler-qt5.h>
1020+
1021+class PdfPage
1022+{
1023+public:
1024+ PdfPage(Poppler::Page *page);
1025+ int width() const;
1026+ int height() const;
1027+
1028+private:
1029+ int m_width;
1030+ int m_height;
1031+};
1032+
1033+#endif // PDFPAGE_H
1034
1035=== added file 'src/plugin/poppler-qml-plugin/plugin.cpp'
1036--- src/plugin/poppler-qml-plugin/plugin.cpp 1970-01-01 00:00:00 +0000
1037+++ src/plugin/poppler-qml-plugin/plugin.cpp 2014-10-28 22:26:31 +0000
1038@@ -0,0 +1,18 @@
1039+#include <QtQml>
1040+#include <QtQml/QQmlContext>
1041+
1042+#include "plugin.h"
1043+#include "pdfModel.h"
1044+
1045+void PopplerPlugin::registerTypes(const char *uri)
1046+{
1047+ Q_ASSERT(uri == QLatin1String("com.ubuntu.popplerqmlplugin"));
1048+
1049+ //@uri com.ubuntu.popplerqmlplugin
1050+ qmlRegisterType<PdfModel>(uri, 1, 0, "Poppler");
1051+}
1052+
1053+void PopplerPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
1054+{
1055+ QQmlExtensionPlugin::initializeEngine(engine, uri);
1056+}
1057
1058=== added file 'src/plugin/poppler-qml-plugin/plugin.h'
1059--- src/plugin/poppler-qml-plugin/plugin.h 1970-01-01 00:00:00 +0000
1060+++ src/plugin/poppler-qml-plugin/plugin.h 2014-10-28 22:26:31 +0000
1061@@ -0,0 +1,34 @@
1062+/*
1063+ * Copyright (C) 2013 Canonical, Ltd.
1064+ *
1065+ * This program is free software: you can redistribute it and/or modify it
1066+ * under the terms of the GNU General Public License version 3, as published
1067+ * by the Free Software Foundation.
1068+ *
1069+ * This program is distributed in the hope that it will be useful, but
1070+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1071+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1072+ * PURPOSE. See the GNU General Public License for more details.
1073+ *
1074+ * You should have received a copy of the GNU General Public License along
1075+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1076+ *
1077+ * Author: Anthony Granger <grangeranthony@gmail.com>
1078+ */
1079+
1080+#ifndef POPPLERPLUGIN_H
1081+#define POPPLERPLUGIN_H
1082+
1083+#include <QQmlExtensionPlugin>
1084+
1085+class PopplerPlugin : public QQmlExtensionPlugin
1086+{
1087+ Q_OBJECT
1088+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
1089+
1090+public:
1091+ void registerTypes(const char *uri);
1092+ void initializeEngine(QQmlEngine *engine, const char *uri);
1093+};
1094+
1095+#endif // POPPLERPLUGIN_H
1096
1097=== added file 'src/plugin/poppler-qml-plugin/qmldir'
1098--- src/plugin/poppler-qml-plugin/qmldir 1970-01-01 00:00:00 +0000
1099+++ src/plugin/poppler-qml-plugin/qmldir 2014-10-28 22:26:31 +0000
1100@@ -0,0 +1,2 @@
1101+module com.ubuntu.popplerqmlplugin
1102+plugin popplerqmlplugin
1103
1104=== modified file 'tests/autopilot/ubuntu_docviewer_app/tests/test_docviewer.py'
1105--- tests/autopilot/ubuntu_docviewer_app/tests/test_docviewer.py 2014-10-28 22:26:31 +0000
1106+++ tests/autopilot/ubuntu_docviewer_app/tests/test_docviewer.py 2014-10-28 22:26:31 +0000
1107@@ -76,7 +76,7 @@
1108 def check_mimeType(self):
1109 self.assertThat(
1110 self.app.select_single("MainView",
1111- objectName="docviewer").minetype,
1112+ objectName="docviewer").mimetype,
1113 Eventually(NotEquals(False)))
1114
1115 def test_unknown_file_type(self):

Subscribers

People subscribed via source and target branches