Merge lp:~jonas-drange/ubuntu-printing-app/soft-depend-on-printjob into lp:ubuntu-printing-app

Proposed by Jonas G. Drange
Status: Superseded
Proposed branch: lp:~jonas-drange/ubuntu-printing-app/soft-depend-on-printjob
Merge into: lp:ubuntu-printing-app
Diff against target: 6026 lines (+3783/-1507)
66 files modified
CMakeLists.txt (+34/-34)
backend/CMakeLists.txt (+12/-21)
backend/UbuntuPrintingApp/backend.cpp (+22/-16)
backend/UbuntuPrintingApp/backend.h (+20/-1)
backend/UbuntuPrintingApp/document.cpp (+80/-275)
backend/UbuntuPrintingApp/document.h (+35/-6)
backend/UbuntuPrintingApp/pagehelper.cpp (+104/-0)
backend/UbuntuPrintingApp/pagehelper.h (+55/-0)
backend/UbuntuPrintingApp/popplerimageprovider.cpp (+58/-18)
backend/UbuntuPrintingApp/popplerimageprovider.h (+19/-0)
backend/UbuntuPrintingApp/qmldir (+2/-2)
backend/Ubuntu_Printing_App/printer.cpp (+0/-355)
backend/Ubuntu_Printing_App/printer.h (+0/-94)
backend/Ubuntu_Printing_App/printerinfo.cpp (+0/-39)
backend/Ubuntu_Printing_App/printerinfo.h (+0/-30)
backend/tests/unit/tst_mytype.qml (+0/-49)
debian/changelog (+1/-1)
debian/control (+15/-6)
debian/copyright (+1/-1)
manifest.json.in (+0/-16)
po/CMakeLists.txt (+44/-0)
po/ubuntu-printing-app.pot (+122/-0)
runner/CMakeLists.txt (+5/-2)
runner/ubuntu-printing-app (+0/-3)
runner/ubuntu-printing-app.in (+3/-0)
setup/gui/ubuntu-printing-app.desktop (+8/-0)
snapcraft.yaml (+75/-0)
tests/CMakeLists.txt (+3/-0)
tests/qmltests/CMakeLists.txt (+46/-0)
tests/qmltests/tst_CheckBoxRow.qml (+87/-0)
tests/qmltests/tst_LabelRow.qml (+73/-0)
tests/qmltests/tst_PreviewRow.qml (+316/-0)
tests/qmltests/tst_PrintPage.qml (+437/-0)
tests/qmltests/tst_PrintRow.qml (+110/-0)
tests/qmltests/tst_SelectorRow.qml (+136/-0)
tests/qmltests/tst_TextFieldRow.qml (+174/-0)
tests/resources/CMakeLists.txt (+6/-0)
tests/resources/pdf/CMakeLists.txt (+3/-0)
tests/resources/pdf/corrupt.pdf (+3/-0)
tests/unittests/CMakeLists.txt (+1/-0)
tests/unittests/backend/CMakeLists.txt (+19/-0)
tests/unittests/backend/tst_document.cpp (+301/-0)
tests/unittests/backend/tst_pagehelper.cpp (+171/-0)
tests/unittests/backend/tst_popplerimageprovider.cpp (+127/-0)
ubuntu-printing-app/CMakeLists.txt (+2/-1)
ubuntu-printing-app/Main.qml (+113/-281)
ubuntu-printing-app/components/AlertDialog.qml (+32/-0)
ubuntu-printing-app/components/CMakeLists.txt (+6/-1)
ubuntu-printing-app/components/CheckBoxRow.qml (+76/-0)
ubuntu-printing-app/components/ExpandableListItem.qml (+0/-82)
ubuntu-printing-app/components/LabelRow.qml (+52/-0)
ubuntu-printing-app/components/PreviewRow.qml (+142/-0)
ubuntu-printing-app/components/PrintRow.qml (+20/-1)
ubuntu-printing-app/components/PrintingHelper.qml (+38/-0)
ubuntu-printing-app/components/SelectorRow.qml (+43/-3)
ubuntu-printing-app/components/TextFieldRow.qml (+54/-0)
ubuntu-printing-app/pages/CMakeLists.txt (+9/-0)
ubuntu-printing-app/pages/ContentPeerPickerPage.qml (+138/-0)
ubuntu-printing-app/pages/PrintPage.qml (+299/-0)
ubuntu-printing-app/tests/autopilot/run (+0/-11)
ubuntu-printing-app/tests/autopilot/ubuntu_printing_app/__init__.py (+0/-41)
ubuntu-printing-app/tests/autopilot/ubuntu_printing_app/tests/__init__.py (+0/-54)
ubuntu-printing-app/tests/autopilot/ubuntu_printing_app/tests/test_main.py (+0/-21)
ubuntu-printing-app/tests/unit/tst_main.qml (+0/-41)
ubuntu-printing-app/ubuntu-printing-app-apparmor.manifest (+29/-0)
ubuntu-printing-app/ubuntu-printing-app.desktop.in.in (+2/-1)
To merge this branch: bzr merge lp:~jonas-drange/ubuntu-printing-app/soft-depend-on-printjob
Reviewer Review Type Date Requested Status
Ubuntu Phablet Team Pending
Review via email: mp+316775@code.launchpad.net

Commit message

* stops instantiating printerjob directly
* create printerjobs from Printers.createJob(printerName)

To post a comment you must log in.

Unmerged revisions

67. By Jonas G. Drange

set job values before page is pushed

66. By Jonas G. Drange

update to latest usc printing api

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 2016-12-13 23:40:36 +0000
3+++ CMakeLists.txt 2017-02-08 21:32:20 +0000
4@@ -17,52 +17,41 @@
5 set(APP_HARDCODE ubuntu-printing-app)
6 set(CMAKE_AUTOMOC ON)
7 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") # -fno-permissive -pedantic -Wall -Wextra")
8-set(UBUNTU_MANIFEST_PATH "manifest.json.in" CACHE INTERNAL "Tell QtCreator the location and name o the manifest file")
9 set(DESKTOP_FILE "${APP_NAME}.desktop")
10 set(ICON_FILE ubuntu-printing-app.png)
11 set(MAIN_QML Main.qml)
12+set(RUNNER ${APP_HARDCODE})
13+set(SNAP_DESKTOP_FILE setup/gui/${DESKTOP_FILE})
14
15 # Set the options
16-option(CLICK_MODE "Build as a click package" off)
17+option(SNAP_MODE "Build as a snap package" off)
18
19 # Find packages
20-find_package(Qt5Core)
21-find_package(Qt5Qml)
22-find_package(Qt5Quick)
23-find_package(Qt5PrintSupport)
24+find_package(Qt5Core REQUIRED)
25+find_package(Qt5Qml REQUIRED)
26+find_package(Qt5Quick REQUIRED)
27+find_package(Qt5PrintSupport REQUIRED)
28
29 include(GNUInstallDirs)
30
31
32 # Set the path for the QML files and the backend
33-if(CLICK_MODE)
34- message("CLICK_MODE is not supported at this time!")
35-else(CLICK_MODE)
36- set(UBUNTU_PRINTING_APP_DATA_DIR "${CMAKE_INSTALL_DATADIR}/${APP_HARDCODE}")
37- execute_process(
38- COMMAND qmake -query QT_INSTALL_QML
39- OUTPUT_VARIABLE QT_IMPORTS_DIR
40- OUTPUT_STRIP_TRAILING_WHITESPACE
41- )
42+set(UBUNTU_PRINTING_APP_DATA_DIR "${CMAKE_INSTALL_DATADIR}/${APP_HARDCODE}")
43+execute_process(
44+COMMAND qmake -query QT_INSTALL_QML
45+ OUTPUT_VARIABLE QT_IMPORTS_DIR
46+ OUTPUT_STRIP_TRAILING_WHITESPACE
47+)
48+set(MODULE_PATH ${QT_IMPORTS_DIR}/UbuntuPrintingApp)
49+
50+# Set the exec path
51+if(SNAP_MODE)
52+ set(EXEC "APP_ID=${APP_HARDCODE} qmlscene $@ -I $SNAP/${MODULE_PATH} $SNAP/${CMAKE_INSTALL_PREFIX}/${UBUNTU_PRINTING_APP_DATA_DIR}/${MAIN_QML}")
53+ set(ICON "$SNAP/${CMAKE_INSTALL_PREFIX}/${UBUNTU_PRINTING_APP_DATA_DIR}/${ICON_FILE}")
54+else(SNAP_MODE)
55+ set(EXEC "APP_ID=${APP_HARDCODE} qmlscene $@ -I ${MODULE_PATH} ${CMAKE_INSTALL_PREFIX}/${UBUNTU_PRINTING_APP_DATA_DIR}/${MAIN_QML}")
56 set(ICON ${CMAKE_INSTALL_PREFIX}/${UBUNTU_PRINTING_APP_DATA_DIR}/${ICON_FILE})
57- set(MODULE_PATH ${QT_IMPORTS_DIR}/Ubuntu_Printing_App)
58-endif(CLICK_MODE)
59-
60-# Set the exec path
61-if (CLICK_MODE)
62- message("CLICK_MODE is not supported at this time!")
63-else(CLICK_MODE)
64- # FIXME should this point to the runner?
65- set(EXEC "qmlscene $@ -I ${MODULE_PATH} ${CMAKE_INSTALL_PREFIX}/${UBUNTU_PRINTING_APP_DATA_DIR}/${MAIN_QML}")
66-endif(CLICK_MODE)
67-
68-
69-# Find translatable files
70-file(GLOB_RECURSE I18N_SRC_FILES
71- RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/po
72- *.qml *.js *.cpp)
73-list(APPEND I18N_SRC_FILES ${DESKTOP_FILE}.in.in.h)
74-list(SORT I18N_SRC_FILES)
75+endif(SNAP_MODE)
76
77
78 # Add subdirs
79@@ -70,10 +59,21 @@
80 add_subdirectory(runner)
81 add_subdirectory(ubuntu-printing-app)
82
83+# Setup gettext defs and include po directory
84+set(GETTEXT_PACKAGE "ubuntu-printing-app")
85+add_definitions(-DI18N_DOMAIN="${GETTEXT_PACKAGE}")
86+
87+add_subdirectory(po)
88+
89+# Add tests
90+find_package(Qt5Test REQUIRED)
91+enable_testing()
92+add_subdirectory(tests)
93+
94
95 # Add run command for QtC
96 add_custom_target("run" /usr/bin/qmlscene -I ${CMAKE_BINARY_DIR}/backend ${CMAKE_SOURCE_DIR}/ubuntu-printing-app/Main.qml
97- DEPENDS Ubuntu_Printing_App Ubuntu_Printing_App_qmldir
98+ DEPENDS UbuntuPrintingApp UbuntuPrintingAppqmldir
99 WORKING_DIRECTORY ./ubuntu-printing-app)
100
101 # Show files in QtC
102
103=== modified file 'backend/CMakeLists.txt'
104--- backend/CMakeLists.txt 2016-12-13 23:40:36 +0000
105+++ backend/CMakeLists.txt 2017-02-08 21:32:20 +0000
106@@ -1,43 +1,34 @@
107 include_directories(
108 ${CMAKE_CURRENT_SOURCE_DIR}
109- /usr/include/cups/
110 /usr/include/poppler/qt5/
111- ${Qt5PrintSupport_INCLUDE_DIRS}
112 )
113
114-#add_definitions(
115-# -DGETTEXT_PACKAGE=\"${PROJECT_NAME}\"
116-# -DGETTEXT_LOCALEDIR=\"${CMAKE_INSTALL_LOCALEDIR}\"
117-#)
118-
119-set(LIBNAME Ubuntu_Printing_Appbackend)
120+set(LIBNAME UbuntuPrintingAppbackend)
121
122 set(
123- Ubuntu_Printing_App_SRC
124- Ubuntu_Printing_App/backend.cpp
125- Ubuntu_Printing_App/document.cpp
126- Ubuntu_Printing_App/popplerimageprovider.cpp
127- Ubuntu_Printing_App/printer.cpp
128- Ubuntu_Printing_App/printerinfo.cpp
129+ UbuntuPrintingAppSRC
130+ UbuntuPrintingApp/backend.cpp
131+ UbuntuPrintingApp/document.cpp
132+ UbuntuPrintingApp/popplerimageprovider.cpp
133+ UbuntuPrintingApp/pagehelper.cpp
134 )
135
136-add_library(${LIBNAME} SHARED ${Ubuntu_Printing_App_SRC})
137+add_library(${LIBNAME} SHARED ${UbuntuPrintingAppSRC})
138
139-qt5_use_modules(${LIBNAME} Core Gui Qml Quick PrintSupport)
140+qt5_use_modules(${LIBNAME} Core Gui Qml Quick)
141 target_link_libraries(${LIBNAME}
142- cups
143 poppler-qt5
144 )
145
146 set_target_properties(${LIBNAME} PROPERTIES
147- LIBRARY_OUTPUT_DIRECTORY Ubuntu_Printing_App
148+ LIBRARY_OUTPUT_DIRECTORY UbuntuPrintingApp
149 )
150
151 # Copy the qmldir file to the build dir
152-add_custom_target(Ubuntu_Printing_App_qmldir ALL
153- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/Ubuntu_Printing_App/qmldir ${CMAKE_CURRENT_BINARY_DIR}/Ubuntu_Printing_App
154+add_custom_target(UbuntuPrintingApp_qmldir ALL
155+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/UbuntuPrintingApp/qmldir ${CMAKE_CURRENT_BINARY_DIR}/UbuntuPrintingApp
156 DEPENDS ${QMLFILES})
157
158 # Install the plugin file
159 install(TARGETS ${LIBNAME} DESTINATION ${MODULE_PATH})
160-install(FILES Ubuntu_Printing_App/qmldir DESTINATION ${MODULE_PATH})
161+install(FILES UbuntuPrintingApp/qmldir DESTINATION ${MODULE_PATH})
162
163=== renamed directory 'backend/Ubuntu_Printing_App' => 'backend/UbuntuPrintingApp'
164=== modified file 'backend/UbuntuPrintingApp/backend.cpp'
165--- backend/Ubuntu_Printing_App/backend.cpp 2016-12-13 12:37:45 +0000
166+++ backend/UbuntuPrintingApp/backend.cpp 2017-02-08 21:32:20 +0000
167@@ -1,30 +1,36 @@
168+/*
169+ * Copyright 2016 Canonical Ltd.
170+ *
171+ * This file is part of ubuntu-printing-app.
172+ *
173+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
174+ * it under the terms of the GNU General Public License as published by
175+ * the Free Software Foundation; version 3.
176+ *
177+ * ubuntu-printing-app is distributed in the hope that it will be useful,
178+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
179+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
180+ * GNU General Public License for more details.
181+ *
182+ * You should have received a copy of the GNU General Public License
183+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
184+ *
185+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
186+ */
187 #include <QtQml>
188 #include <QtQml/QQmlContext>
189 #include "backend.h"
190
191 #include "document.h"
192+#include "pagehelper.h"
193 #include "popplerimageprovider.h"
194-#include "printer.h"
195-#include "printerinfo.h"
196-
197-
198-#define MAKE_SINGLETON_FACTORY(type) \
199- static QObject* type##_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine) { \
200- Q_UNUSED(engine); \
201- Q_UNUSED(scriptEngine); \
202- return new type(); \
203- }
204-
205-MAKE_SINGLETON_FACTORY(PrinterInfo)
206-
207
208 void BackendPlugin::registerTypes(const char *uri)
209 {
210- Q_ASSERT(uri == QLatin1String("Ubuntu_Printing_App"));
211+ Q_ASSERT(uri == QLatin1String("UbuntuPrintingApp"));
212
213 qmlRegisterType<Document>(uri, 1, 0, "Document");
214- qmlRegisterType<Printer>(uri, 1, 0, "Printer");
215- qmlRegisterSingletonType<PrinterInfo>(uri, 1, 0, "PrinterInfo", PrinterInfo_singleton_factory);
216+ qmlRegisterType<PageHelper>(uri, 1, 0, "PageHelper");
217 }
218
219 void BackendPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
220
221=== modified file 'backend/UbuntuPrintingApp/backend.h'
222--- backend/Ubuntu_Printing_App/backend.h 2016-12-13 12:37:45 +0000
223+++ backend/UbuntuPrintingApp/backend.h 2017-02-08 21:32:20 +0000
224@@ -1,3 +1,22 @@
225+/*
226+ * Copyright 2016 Canonical Ltd.
227+ *
228+ * This file is part of ubuntu-printing-app.
229+ *
230+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
231+ * it under the terms of the GNU General Public License as published by
232+ * the Free Software Foundation; version 3.
233+ *
234+ * ubuntu-printing-app is distributed in the hope that it will be useful,
235+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
236+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
237+ * GNU General Public License for more details.
238+ *
239+ * You should have received a copy of the GNU General Public License
240+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
241+ *
242+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
243+ */
244 #ifndef BACKEND_PLUGIN_H
245 #define BACKEND_PLUGIN_H
246
247@@ -7,7 +26,7 @@
248 /*
249 ----8<-----
250
251- import Ubuntu_Printing_App 1.0
252+ import UbuntuPrintingApp 1.0
253
254 Rectangle {
255 width: 200
256
257=== modified file 'backend/UbuntuPrintingApp/document.cpp'
258--- backend/Ubuntu_Printing_App/document.cpp 2016-12-13 12:08:15 +0000
259+++ backend/UbuntuPrintingApp/document.cpp 2017-02-08 21:32:20 +0000
260@@ -1,3 +1,22 @@
261+/*
262+ * Copyright 2016 Canonical Ltd.
263+ *
264+ * This file is part of ubuntu-printing-app.
265+ *
266+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
267+ * it under the terms of the GNU General Public License as published by
268+ * the Free Software Foundation; version 3.
269+ *
270+ * ubuntu-printing-app is distributed in the hope that it will be useful,
271+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
272+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
273+ * GNU General Public License for more details.
274+ *
275+ * You should have received a copy of the GNU General Public License
276+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
277+ *
278+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
279+ */
280 #include "document.h"
281
282 #include <QtCore/QDebug>
283@@ -18,7 +37,7 @@
284 : QObject(parent),
285 m_count(0),
286 m_document(Q_NULLPTR),
287- m_url("")
288+ m_url(QStringLiteral(""))
289 {
290
291 }
292@@ -49,6 +68,21 @@
293 return fmin(destDPI.width(), destDPI.height());
294 }
295
296+QSizeF Document::getPageSize(int pageNumber)
297+{
298+ QSizeF size;
299+
300+ if (m_document) {
301+ Poppler::Page *page = m_document->page(pageNumber);
302+
303+ if (page) {
304+ size = page->pageSizeF();
305+ }
306+ }
307+
308+ return size;
309+}
310+
311 QImage Document::makeImage(QSizeF size, int pageNumber)
312 {
313 if (pageNumber < 0) {
314@@ -61,8 +95,9 @@
315 return QImage();
316 }
317
318- // Splash backend has much better rendering
319- m_document->setRenderBackend(Poppler::Document::SplashBackend);
320+ if (size == QSize(0, 0)) {
321+ return QImage();
322+ }
323
324 Poppler::Page *page = m_document->page(pageNumber);
325
326@@ -74,17 +109,16 @@
327 // Calculate the DPI to render at
328 float res = getDpi(page->pageSizeF(), size);
329
330- qDebug() << "Making image with res of" << res;
331-
332 // Make the image
333 QImage image = page->renderToImage(res, res, 0, 0, size.width(), size.height());
334
335+ delete page;
336+
337 if (image.isNull()) {
338 qWarning() << "Image is null";
339+ return QImage();
340 }
341
342- delete page;
343-
344 return image;
345 }
346
347@@ -100,13 +134,10 @@
348 return QImage();
349 }
350
351- // Splash backend has much better rendering
352- m_document->setRenderBackend(Poppler::Document::SplashBackend);
353-
354 Poppler::Page *page = m_document->page(pageNumber);
355
356 if (!page) {
357- qWarning() << "Invalid page";
358+ qWarning() << "Invalid page:" << pageNumber;
359 return QImage();
360 }
361
362@@ -120,17 +151,13 @@
363
364 // Make the image
365 QImage image = makeImage(scaledSize, pageNumber);
366-// image.setDotsPerMeterX(6000);
367-// image.setDotsPerMeterY(6000);
368
369 if (!color) {
370 image = image.convertToFormat(QImage::Format_Grayscale8);
371 }
372
373- qDebug() << "i" << image.width() << scaledSize.width() << image.dotsPerMeterX();
374-
375 // Make a container then put the content image inside
376- QImage container(size.toSize(), QImage::Format_ARGB32_Premultiplied); //QImage::Format_Grayscale8); //QImage::Format_ARGB32);
377+ QImage container(size.toSize(), QImage::Format_ARGB32_Premultiplied);
378 QPainter painter;
379
380 container.fill(QColor(0, 0, 0, 0));
381@@ -141,6 +168,7 @@
382 painter.drawImage((size.width() - scaledSize.width()) / 2, (size.height() - scaledSize.height()) / 2, image);
383 } else {
384 qWarning() << "Image is null";
385+ return QImage();
386 }
387
388 painter.end();
389@@ -148,197 +176,12 @@
390 return container;
391 }
392
393-QPixmap Document::makePixmap(QSize size, int pageNumber)
394-{
395- if (pageNumber < 0) {
396- qWarning() << "Invalid page number";
397- }
398-
399- if (!m_document) {
400- qWarning() << "No document loaded";
401- }
402-
403- // Splash backend has much better rendering
404- m_document->setRenderBackend(Poppler::Document::SplashBackend);
405-
406- Poppler::Page *page = m_document->page(pageNumber);
407-
408- if (!page) {
409- qWarning() << "Invalid page";
410- }
411-
412- float res = getDpi(page->pageSizeF(), size);
413-
414- qDebug() << "Making image with res of" << res;
415-
416- // Make QPixmap
417- QPixmap pixmap(size);
418-
419- // If using ArthurBackend can do
420- // QPainter painter(&pixmap);
421- // if (!page->renderToPainter(painter, res, res)) {
422- // qWarning() << "Failed to render to painter";
423- // }
424-
425- QImage image = page->renderToImage(res, res);
426-
427- if (image.isNull()) {
428- qWarning() << "Image is null";
429- }
430-
431- pixmap = QPixmap::fromImage(image);
432-
433- delete page;
434-
435- return pixmap;
436-}
437-
438-QImage Document::renderImage(QSize size, int pageNumber)
439-{
440- if (pageNumber < 0) {
441- qWarning() << "Invalid page number";
442- }
443-
444- if (!m_document) {
445- qWarning() << "No document loaded";
446- }
447-
448-// m_document->setRenderBackend(Poppler::Document::SplashBackend);
449-
450- Poppler::Page *page = m_document->page(pageNumber);
451-
452- if (!page) {
453- qWarning() << "Invalid page";
454- }
455-
456- /*
457- * width / res width / res
458- */
459-
460-// int res = size.width() / (page->pageSize().width() / 72);
461-
462-// qDebug() << "Res:" << res;
463-
464-
465-
466- QSizeF sourceSizeInch(page->pageSizeF().width() / 72, page->pageSizeF().height() / 72);
467-
468- QSizeF destDPI(size.width() / sourceSizeInch.width(), size.height()/ sourceSizeInch.height());
469-
470- float res;
471-
472- if (destDPI.width() > destDPI.height()) {
473- res = destDPI.height();
474- } else {
475- res = destDPI.width();
476- }
477-
478- qDebug() << "Making image with res of" << res;
479-
480- QImage image = page->renderToImage(res, res);
481-
482- if (image.isNull()) {
483- qWarning() << "Image is null";
484- }
485-
486- delete page;
487-
488- return image;
489-}
490-
491-bool Document::renderPage(QPainter *painter, int pageNumber)
492-{
493- if (!painter) {
494- qWarning() << "Invalid painter";
495- return false;
496- }
497-
498- if (pageNumber < 0) {
499- qWarning() << "Invalid page number";
500- return false;
501- }
502-
503- if (!m_document) {
504- qWarning() << "No document loaded";
505- return false;
506- }
507-
508- Poppler::Page *page = m_document->page(pageNumber);
509-
510- m_document->setRenderBackend(Poppler::Document::ArthurBackend);
511-
512- if (!page) {
513- qWarning() << "Invalid page";
514- return false;
515- }
516-
517- /*
518-A4
519-DPI: 96 1200
520-Device Size: 767 1097
521-Doc Size: 595 842
522-
523-A5
524-DPI: 96 1200
525-Device Size: 534 767
526-Doc Size: 595 842
527- */
528-
529- QSizeF sourceSizeInch(page->pageSizeF().width() / 72, page->pageSizeF().height() / 72);
530-
531- QSizeF destDPI(painter->device()->width() / sourceSizeInch.width(), painter->device()->height()/ sourceSizeInch.height());
532-
533- float res;
534-
535- if (destDPI.width() > destDPI.height()) {
536- res = destDPI.height();
537- } else {
538- res = destDPI.width();
539- }
540-
541-// Poppler::PSConverter *psConv = m_document->psConverter();
542-
543-// psConv->setLeftMargin(5);
544-// psConv->setRightMargin(1);
545-// psConv->setOutputFileName("/tmp/out.ps");
546-// psConv->setPaperHeight(painter->device()->height());
547-// psConv->setPaperWidth(painter->device()->width());
548-
549-// QList<int> pages = { 1 };
550-
551-// psConv->setPageList(pages);
552-
553-// qDebug() << "PS" << psConv->convert();
554-
555-
556-// float res = painter->device()->width() / (page->pageSize().width() / 72); //painter->device()->logicalDpiX());
557-
558- //res = 70;
559-
560- qDebug() << "DPI:" << painter->device()->logicalDpiX() << painter->device()->physicalDpiX() << res;
561-
562- qDebug() << "Device Size:" << painter->device()->width() << painter->device()->height();
563- qDebug() << "Doc Size:" << page->pageSize().width() << page->pageSize().height();
564-
565- // Create Image same dimensions as PageSize
566- // Render to the image
567- // Render the image to the printer
568- // Image can also be used for preview?
569-
570- if (!page->renderToPainter(painter, res, res)) {
571-// if (!page->renderToPainter(painter, painter->device()->logicalDpiX(), painter->device()->logicalDpiY(),
572-// 0, 0, page->pageSize().width(), page->pageSize().height())) {
573- qWarning() << "Rendering failed";
574- return false;
575- }
576-
577- delete page;
578-
579- return true;
580-}
581-
582 Document::Orientation Document::orientation() const
583 {
584+ if (!m_document) {
585+ return Portrait;
586+ }
587+
588 Poppler::Page *page = m_document->page(0);
589
590 if (page) {
591@@ -350,102 +193,64 @@
592 return Portrait;
593 }
594
595- qDebug() << "DOC" << page->orientation() << Portrait << Landscape;
596-
597- if (page->orientation() == Poppler::Page::Landscape) {
598- return Landscape;
599- } else if (page->orientation() == Poppler::Page::Portrait) {
600- return Portrait;
601- } else {
602- qWarning() << "Other orientation:" << page->orientation() << "using Portrait";
603- return Portrait;
604- }
605+ // TODO: page orientation seems to be wrong?
606+// qDebug() << "DOC" << page->orientation() << Portrait << Landscape;
607+// if (page->orientation() == Poppler::Page::Landscape) {
608+// return Landscape;
609+// } else if (page->orientation() == Poppler::Page::Portrait) {
610+// return Portrait;
611+// } else {
612+// qWarning() << "Other orientation:" << page->orientation() << "using Portrait";
613+// return Portrait;
614+// }
615 } else {
616 return Portrait;
617 }
618 }
619
620-bool Document::printFromImage(QPainter *painter, int pageNumber, QRect pageRect, double resolution)
621-{
622- // Ensure we are using the right render hints
623- m_document->setRenderBackend(Poppler::Document::SplashBackend);
624-
625- m_document->setRenderHint(Poppler::Document::Antialiasing, true);
626- m_document->setRenderHint(Poppler::Document::TextAntialiasing, true);
627- m_document->setRenderHint(Poppler::Document::TextHinting, true);
628-
629- Poppler::Page *page = m_document->page(pageNumber);
630-
631- if (!page) {
632- qWarning() << "Invalid page!";
633- return false;
634- }
635-
636- // Render at given resolution
637- QImage image = page->renderToImage(resolution, resolution);
638-
639- // Get the scalar for the image to fit within the pageRect
640- double ratioX = (double) image.width() / (double) pageRect.width();
641- double ratioY = (double) image.height() / (double) pageRect.height();
642-
643- image.setDevicePixelRatio(fmax(ratioX, ratioY));
644-
645- // Check that image isn't null
646- if (image.isNull()) {
647- return false;
648- }
649-
650- // Draw the image to the painter, should we scale? the image should be correct aspect
651- // Here we should check if the image aspect is different and position in the centre?
652- painter->drawImage(0, 0, image);
653- //painter->drawImage(QRect(QPoint(0, 0), QSize(pageRect.width(), pageRect.height())), image, image.rect());
654-
655- qDebug() << "Device Width:" << pageRect.width() << "LogicalDPI:" << painter->device()->logicalDpiX(); // << "RenderDPI:" << renderDPI.width();
656- qDebug() << "RatioX" << ratioX << "RatioY" << ratioY;
657-
658- qDebug() << "PageRect:" << pageRect.width() << pageRect.height();
659- qDebug() << "Image:" << image.width() << image.height() << image.dotsPerMeterX();
660-
661- return true;
662-}
663-
664 void Document::setUrl(QUrl url)
665 {
666 if (m_url != url) {
667 if (url.isLocalFile() && QFileInfo::exists(url.toLocalFile())) {
668 if (QMimeDatabase().mimeTypeForUrl(url).name() == "application/pdf") {
669- m_url = url;
670-
671- // Load document
672- m_document = Poppler::Document::load(m_url.toLocalFile());
673- m_document->setRenderBackend(Poppler::Document::ArthurBackend);
674-
675- m_document->setRenderHint(Poppler::Document::Antialiasing, true);
676- m_document->setRenderHint(Poppler::Document::TextAntialiasing, true);
677- m_document->setRenderHint(Poppler::Document::TextHinting, true);
678-// m_document->setRenderHint(Poppler::Document::TextSlightHinting, true);
679-// m_document->setRenderHint(Poppler::Document::OverprintPreview, true);
680-// m_document->setRenderHint(Poppler::Document::ThinLineSolid, true);
681-// m_document->setRenderHint(Poppler::Document::ThinLineShape, true);
682+ // Attempt to Load document
683+ m_document = Poppler::Document::load(url.toLocalFile());
684
685 if (!m_document || m_document->isLocked()) {
686 qWarning() << "Invalid Document";
687 delete m_document;
688 m_document = Q_NULLPTR;
689+
690+ Q_EMIT error(Errors::ErrorDocumentInvalid);
691 } else {
692+ m_url = url;
693+
694+ m_document->setRenderBackend(Poppler::Document::SplashBackend);
695+
696+ m_document->setRenderHint(Poppler::Document::Antialiasing, true);
697+ m_document->setRenderHint(Poppler::Document::TextAntialiasing, true);
698+ m_document->setRenderHint(Poppler::Document::TextHinting, true);
699+ m_document->setRenderHint(Poppler::Document::TextSlightHinting, true);
700+
701+ Q_EMIT urlChanged();
702+
703 if (m_count != m_document->numPages()) {
704 m_count = m_document->numPages();
705
706 Q_EMIT countChanged();
707 }
708+
709+ Q_EMIT orientationChanged();
710+ Q_EMIT titleChanged();
711 }
712-
713- Q_EMIT urlChanged();
714 } else {
715 qWarning() << "File is not a PDF:" << url;
716+ Q_EMIT error(Errors::ErrorNotPdf);
717 }
718 } else {
719 qWarning() << "Url is not a local file:" << url;
720+
721+ Q_EMIT error(Errors::ErrorNotFound);
722 }
723 }
724 }
725@@ -455,7 +260,7 @@
726 if (m_document) {
727 return m_document->info("Title");
728 } else {
729- return "";
730+ return QStringLiteral("");
731 }
732 }
733
734
735=== modified file 'backend/UbuntuPrintingApp/document.h'
736--- backend/Ubuntu_Printing_App/document.h 2016-12-13 12:08:15 +0000
737+++ backend/UbuntuPrintingApp/document.h 2017-02-08 21:32:20 +0000
738@@ -1,7 +1,27 @@
739+/*
740+ * Copyright 2016 Canonical Ltd.
741+ *
742+ * This file is part of ubuntu-printing-app.
743+ *
744+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
745+ * it under the terms of the GNU General Public License as published by
746+ * the Free Software Foundation; version 3.
747+ *
748+ * ubuntu-printing-app is distributed in the hope that it will be useful,
749+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
750+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
751+ * GNU General Public License for more details.
752+ *
753+ * You should have received a copy of the GNU General Public License
754+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
755+ *
756+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
757+ */
758 #ifndef DOCUMENT_H
759 #define DOCUMENT_H
760
761 #include <QtCore/QObject>
762+#include <QtCore/QSizeF>
763 #include <QtCore/QUrl>
764
765 #include <QtGui/QPainter>
766@@ -13,30 +33,39 @@
767 Q_OBJECT
768
769 Q_PROPERTY(int count READ count NOTIFY countChanged)
770+ Q_PROPERTY(Orientation orientation READ orientation NOTIFY orientationChanged)
771+ Q_PROPERTY(QString title READ title NOTIFY titleChanged)
772 Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged)
773 public:
774+ enum class Errors {
775+ ErrorDocumentInvalid,
776+ ErrorNotFound,
777+ ErrorNotPdf,
778+ };
779+
780+ Q_ENUM(Errors)
781+
782 enum Orientation {
783 Portrait,
784 Landscape,
785 };
786+ Q_ENUM(Orientation)
787
788 explicit Document(QObject *parent = 0);
789 ~Document();
790 int count() const;
791+ QSizeF getPageSize(int pageNumber);
792 Orientation orientation() const;
793 QString title() const;
794 QUrl url() const;
795
796 QImage makeImage(QSizeF size, int pageNumber);
797 QImage makeImageToFit(QSizeF size, int pageNumber, bool color);
798- QPixmap makePixmap(QSize size, int pageNumber);
799-
800- Q_INVOKABLE QImage renderImage(QSize size, int pageNumber);
801- Q_INVOKABLE bool renderPage(QPainter *painter, int pageNumber);
802-
803- bool printFromImage(QPainter *painter, int pageNumber, QRect pageRect, double resolution);
804 signals:
805 void countChanged();
806+ void error(Document::Errors errorType);
807+ void orientationChanged();
808+ void titleChanged();
809 void urlChanged();
810 public slots:
811 void setUrl(QUrl url);
812
813=== added file 'backend/UbuntuPrintingApp/pagehelper.cpp'
814--- backend/UbuntuPrintingApp/pagehelper.cpp 1970-01-01 00:00:00 +0000
815+++ backend/UbuntuPrintingApp/pagehelper.cpp 2017-02-08 21:32:20 +0000
816@@ -0,0 +1,104 @@
817+/*
818+ * Copyright 2016 Canonical Ltd.
819+ *
820+ * This file is part of ubuntu-printing-app.
821+ *
822+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
823+ * it under the terms of the GNU General Public License as published by
824+ * the Free Software Foundation; version 3.
825+ *
826+ * ubuntu-printing-app is distributed in the hope that it will be useful,
827+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
828+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
829+ * GNU General Public License for more details.
830+ *
831+ * You should have received a copy of the GNU General Public License
832+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
833+ *
834+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
835+ */
836+#include <QtCore/QSizeF>
837+
838+#include <poppler/qt5/poppler-qt5.h>
839+
840+#include "pagehelper.h"
841+
842+#define A4_ASPECT_RATIO 595.0 / 842.0
843+
844+PageHelper::PageHelper(QObject *parent)
845+ : QObject(parent)
846+ , m_aspect(A4_ASPECT_RATIO)
847+ , m_document(Q_NULLPTR)
848+ , m_page(0)
849+{
850+
851+}
852+
853+double PageHelper::aspect() const
854+{
855+ return m_aspect;
856+}
857+
858+Document *PageHelper::document() const
859+{
860+ return m_document;
861+}
862+
863+void PageHelper::loadAspect()
864+{
865+ if (!m_document) {
866+ setAspect(A4_ASPECT_RATIO);
867+ }
868+
869+ QSizeF pageSize = m_document->getPageSize(m_page);
870+
871+ if (pageSize.isValid()) {
872+ setAspect(pageSize.width() / pageSize.height());
873+ } else {
874+ setAspect(A4_ASPECT_RATIO);
875+ }
876+}
877+
878+int PageHelper::page() const
879+{
880+ return m_page;
881+}
882+
883+void PageHelper::setAspect(double aspect)
884+{
885+ if (m_aspect != aspect) {
886+ m_aspect = aspect;
887+
888+ Q_EMIT aspectChanged();
889+ }
890+}
891+
892+void PageHelper::setDocument(Document *document)
893+{
894+ if (m_document != document) {
895+ if (m_document) { // disconnect old signals
896+ m_document->disconnect();
897+ }
898+
899+ m_document = document;
900+
901+ // If the document URL changes reload the aspect
902+ PageHelper::connect(m_document, SIGNAL(urlChanged()), this, SLOT(loadAspect()));
903+
904+ Q_EMIT documentChanged();
905+
906+ loadAspect();
907+ }
908+}
909+
910+void PageHelper::setPage(int page)
911+{
912+ if (m_page != page) {
913+ m_page = page;
914+
915+ Q_EMIT pageChanged();
916+
917+ loadAspect();
918+ }
919+}
920+
921
922=== added file 'backend/UbuntuPrintingApp/pagehelper.h'
923--- backend/UbuntuPrintingApp/pagehelper.h 1970-01-01 00:00:00 +0000
924+++ backend/UbuntuPrintingApp/pagehelper.h 2017-02-08 21:32:20 +0000
925@@ -0,0 +1,55 @@
926+/*
927+ * Copyright 2016 Canonical Ltd.
928+ *
929+ * This file is part of ubuntu-printing-app.
930+ *
931+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
932+ * it under the terms of the GNU General Public License as published by
933+ * the Free Software Foundation; version 3.
934+ *
935+ * ubuntu-printing-app is distributed in the hope that it will be useful,
936+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
937+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
938+ * GNU General Public License for more details.
939+ *
940+ * You should have received a copy of the GNU General Public License
941+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
942+ *
943+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
944+ */
945+#ifndef PAGEHELPER_H
946+#define PAGEHELPER_H
947+
948+#include <QtCore/QObject>
949+
950+#include "document.h"
951+
952+class PageHelper : public QObject
953+{
954+ Q_OBJECT
955+
956+ Q_PROPERTY(double aspect READ aspect NOTIFY aspectChanged)
957+ Q_PROPERTY(Document *document READ document WRITE setDocument NOTIFY documentChanged)
958+ Q_PROPERTY(int page READ page WRITE setPage NOTIFY pageChanged)
959+public:
960+ explicit PageHelper(QObject *parent = 0);
961+ double aspect() const;
962+ Document *document() const;
963+ int page() const;
964+signals:
965+ void aspectChanged();
966+ void documentChanged();
967+ void pageChanged();
968+public slots:
969+ void setDocument(Document *document);
970+ void setPage(int page);
971+private slots:
972+ void setAspect(double aspect);
973+ void loadAspect();
974+private:
975+ double m_aspect;
976+ Document *m_document;
977+ int m_page;
978+};
979+
980+#endif // PAGEGELPER_H
981
982=== modified file 'backend/UbuntuPrintingApp/popplerimageprovider.cpp'
983--- backend/Ubuntu_Printing_App/popplerimageprovider.cpp 2016-12-12 17:09:39 +0000
984+++ backend/UbuntuPrintingApp/popplerimageprovider.cpp 2017-02-08 21:32:20 +0000
985@@ -1,9 +1,27 @@
986+/*
987+ * Copyright 2016 Canonical Ltd.
988+ *
989+ * This file is part of ubuntu-printing-app.
990+ *
991+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
992+ * it under the terms of the GNU General Public License as published by
993+ * the Free Software Foundation; version 3.
994+ *
995+ * ubuntu-printing-app is distributed in the hope that it will be useful,
996+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
997+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
998+ * GNU General Public License for more details.
999+ *
1000+ * You should have received a copy of the GNU General Public License
1001+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1002+ *
1003+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
1004+ */
1005 #include "popplerimageprovider.h"
1006
1007 #include <QDebug>
1008
1009 #include "document.h"
1010-#include "printer.h"
1011
1012 PopplerImageProvider::PopplerImageProvider()
1013 : QQuickImageProvider(QQuickImageProvider::Image, QQuickImageProvider::ForceAsynchronousImageLoading)
1014@@ -14,35 +32,57 @@
1015
1016 QImage PopplerImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
1017 {
1018- qDebug() << "ID" << id << requestedSize.height() << requestedSize.width();
1019-
1020- // Load id ( image://poppler/{pageNumber}/{colorMode}/{filePath} )
1021+ // Load id ( image://poppler/{pageNumber}/{color}/{filePath} )
1022 QStringList parts = id.split("/");
1023
1024 bool colorOk, numberOk;
1025 int pageNumber = parts.takeFirst().toInt(&numberOk, 10);
1026- int colorModeInt = parts.takeFirst().toInt(&colorOk, 10);
1027-
1028- Printer::ColorMode colorMode = static_cast<Printer::ColorMode>(colorModeInt);
1029+ QString colorMode = QString::fromStdString(parts.takeFirst().toStdString());
1030+
1031+ bool color;
1032+
1033+ if (colorMode == "true") {
1034+ color = true;
1035+ colorOk = true;
1036+ } else if (colorMode == "false") {
1037+ color = false;
1038+ colorOk = true;
1039+ } else {
1040+ colorOk = false;
1041+ }
1042
1043 QString url = parts.join("/");
1044
1045+ // Check request size is valid
1046+ if (requestedSize.height() <= 0 || requestedSize.width() <= 0) {
1047+ qWarning() << "Invalid requestedSize given" << requestedSize;
1048+
1049+ // Requested size is invalid, return a 1x1 image to prevent QML errors
1050+ // when resizing the window really small
1051+ if (size) {
1052+ *size = QSize(1, 1);
1053+ }
1054+
1055+ return QImage(QSize(1, 1), QImage::Format_ARGB32_Premultiplied);
1056+ } else if (size) {
1057+ // Set the size of the 'orignal' image to the requestedSize
1058+ // as we generate an image dynamically
1059+ *size = requestedSize;
1060+ }
1061+
1062+ // Check all parts given were OK
1063 if (url.isEmpty() || !numberOk || !colorOk) {
1064+ qWarning() << "Invalid id given to poppler image provider:" << id;
1065 return QImage();
1066 }
1067
1068- // Fallback size if none is given for QImage
1069- int width = 100;
1070- int height = 50;
1071-
1072- if (size)
1073- *size = QSize(width, height);
1074-
1075- qDebug() << "Url:" << url;
1076- qDebug() << "Page:" << pageNumber;
1077-
1078+ // Build a Document and generate an image to fit the given requestedSize
1079 Document *doc = new Document();
1080 doc->setUrl(url);
1081
1082- return doc->makeImageToFit(requestedSize, pageNumber, colorMode == Printer::Color);
1083+ QImage image = doc->makeImageToFit(requestedSize, pageNumber, color);
1084+
1085+ doc->deleteLater();
1086+
1087+ return image;
1088 }
1089
1090=== modified file 'backend/UbuntuPrintingApp/popplerimageprovider.h'
1091--- backend/Ubuntu_Printing_App/popplerimageprovider.h 2016-12-09 17:14:23 +0000
1092+++ backend/UbuntuPrintingApp/popplerimageprovider.h 2017-02-08 21:32:20 +0000
1093@@ -1,3 +1,22 @@
1094+/*
1095+ * Copyright 2016 Canonical Ltd.
1096+ *
1097+ * This file is part of ubuntu-printing-app.
1098+ *
1099+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
1100+ * it under the terms of the GNU General Public License as published by
1101+ * the Free Software Foundation; version 3.
1102+ *
1103+ * ubuntu-printing-app is distributed in the hope that it will be useful,
1104+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1105+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1106+ * GNU General Public License for more details.
1107+ *
1108+ * You should have received a copy of the GNU General Public License
1109+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1110+ *
1111+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
1112+ */
1113 #ifndef POPPLERIMAGEPROVIDER_H
1114 #define POPPLERIMAGEPROVIDER_H
1115
1116
1117=== modified file 'backend/UbuntuPrintingApp/qmldir'
1118--- backend/Ubuntu_Printing_App/qmldir 2016-12-13 12:37:45 +0000
1119+++ backend/UbuntuPrintingApp/qmldir 2017-02-08 21:32:20 +0000
1120@@ -1,2 +1,2 @@
1121-module Ubuntu_Printing_App
1122-plugin Ubuntu_Printing_Appbackend
1123+module UbuntuPrintingApp
1124+plugin UbuntuPrintingAppbackend
1125
1126=== removed file 'backend/Ubuntu_Printing_App/printer.cpp'
1127--- backend/Ubuntu_Printing_App/printer.cpp 2016-12-13 12:08:15 +0000
1128+++ backend/Ubuntu_Printing_App/printer.cpp 1970-01-01 00:00:00 +0000
1129@@ -1,355 +0,0 @@
1130-#include "printer.h"
1131-
1132-#include <QtCore/QDateTime>
1133-#include <QtCore/QDir>
1134-#include <QtCore/QFileInfo>
1135-#include <QtCore/QStandardPaths>
1136-#include <QtCore/QStringList>
1137-#include <QtCore/QVector>
1138-
1139-#include <QtCore/QDebug>
1140-
1141-#include <cups/cups.h>
1142-#include <cups/ppd.h>
1143-
1144-#define __CUPS_ADD_OPTION(dest, name, value) dest->num_options = \
1145- cupsAddOption(name, value, dest->num_options, &dest->options);
1146-
1147-Printer::Printer(QObject *parent)
1148- : QObject(parent)
1149- , m_color_mode(Color)
1150- , m_copies(1)
1151- , m_cups_dest(0)
1152- , m_cups_instance(QStringLiteral(""))
1153- , m_cups_name(QStringLiteral(""))
1154- , m_duplex(false)
1155- , m_duplex_modes({})
1156- , m_duplex_supported(false)
1157- , m_job_id(0)
1158- , m_name("")
1159- , m_ppd(0)
1160- , m_pdf_mode(false)
1161- , m_quality(Normal)
1162-{
1163-
1164-}
1165-
1166-Printer::~Printer()
1167-{
1168- if (m_ppd) {
1169- ppdClose(m_ppd);
1170- m_ppd = 0;
1171- }
1172-
1173- if (m_cups_dest) {
1174- cupsFreeDests(1, m_cups_dest);
1175-
1176- m_cups_dest = 0;
1177- }
1178-}
1179-
1180-Printer::ColorMode Printer::colorMode() const
1181-{
1182- return m_color_mode;
1183-}
1184-
1185-int Printer::copies() const
1186-{
1187- return m_copies;
1188-}
1189-
1190-bool Printer::duplex() const
1191-{
1192- return m_duplex;
1193-}
1194-
1195-bool Printer::duplexSupported() const
1196-{
1197- return m_duplex_supported;
1198-}
1199-
1200-void Printer::loadDuplexModes(const QString name)
1201-{
1202- if (m_ppd) {
1203- ppdClose(m_ppd);
1204- m_ppd = 0;
1205- }
1206-
1207- const char *ppdFile = cupsGetPPD(name.toLocal8Bit().data());
1208-
1209- if (ppdFile) {
1210- m_ppd = ppdOpenFile(ppdFile);
1211- unlink(ppdFile);
1212-
1213- if (m_ppd) {
1214- ppdMarkDefaults(m_ppd);
1215- } else {
1216- m_ppd = 0;
1217- return;
1218- }
1219- }
1220-
1221- ppd_option_t *duplexModes = ppdFindOption(m_ppd, "Duplex");
1222- ppd_option_t *defaultDuplexModes = ppdFindOption(m_ppd, "DefaultDuplex");
1223-
1224- // Build list of supported duplex modes
1225- bool duplexSupported = false;
1226- m_duplex_modes.clear();
1227-
1228- for (int i=0; i < duplexModes->num_choices; i++) {
1229- m_duplex_modes.append(QString::fromLocal8Bit(duplexModes->choices[i].choice));
1230-
1231- if (QString::fromLocal8Bit(duplexModes->choices[i].choice) != "None") {
1232- duplexSupported = true;
1233- }
1234- }
1235-
1236- setDuplexSupported(duplexSupported);
1237-
1238- // Load default duplex mode
1239- // TODO: do we need as option gets disable?
1240- if (defaultDuplexModes) {
1241- if (QString::fromLocal8Bit(defaultDuplexModes->choices[0].choice) == "None") {
1242- setDuplex(false);
1243- } else {
1244- setDuplex(true);
1245- }
1246- }
1247-}
1248-
1249-bool Printer::loadOptions(cups_dest_t *cups_dest, Document *doc)
1250-{
1251- // Load options
1252- // Copies
1253- if (m_copies > 1) {
1254- __CUPS_ADD_OPTION(cups_dest, "copies", QString::number(m_copies).toLocal8Bit());
1255- }
1256-
1257- // Colour mode
1258- if (m_color_mode == GrayScale) {
1259- __CUPS_ADD_OPTION(cups_dest, "ColorModel", "CMYGray");
1260- }
1261-
1262- // Duplex
1263- if (m_duplex_supported && m_duplex) {
1264- if (doc->orientation() == Document::Portrait && m_duplex_modes.contains("DuplexNoTumble")) {
1265- __CUPS_ADD_OPTION(cups_dest, "Duplex", "DuplexNoTumble");
1266-// __CUPS_ADD_OPTION(m_cups_dest, "sides", "two-sided-long-edge")
1267- } else if (doc->orientation() == Document::Portrait && m_duplex_modes.contains("DuplexTumble")) {
1268- __CUPS_ADD_OPTION(cups_dest, "Duplex", "DuplexTumble");
1269-// __CUPS_ADD_OPTION(m_cups_dest, "sides", "two-sided-long-edge")
1270- } else {
1271- // Fallback to pick first found duplex mode
1272- for (QString mode : m_duplex_modes) {
1273- if (mode != "None") {
1274- __CUPS_ADD_OPTION(cups_dest, "Duplex", mode.toLocal8Bit().data());
1275- break;
1276- }
1277- }
1278- }
1279- } else {
1280- __CUPS_ADD_OPTION(cups_dest, "Duplex", "None");
1281- }
1282-
1283- // Orientation
1284- if (doc->orientation() == Document::Landscape) {
1285- __CUPS_ADD_OPTION(cups_dest, "landscape", "");
1286- }
1287-
1288- // Page range
1289-// __CUPS_ADD_OPTION(cups_dest, "number-up", "4"); // 1, 2, 4, 6, 9
1290-// __CUPS_ADD_OPTION(cups_dest, "number-up-layout", "lrtb"); // "lrtb", "lrbt", "rlbt", "rltb", "btlr", "btrl", "tblr", "tbrl"
1291-// __CUPS_ADD_OPTION(cups_dest, "page-ranges", "1-2"); // 3-5,7,10-20
1292-
1293- // Print quality
1294- QString printQuality = "";
1295- switch (m_quality) {
1296- case Draft:
1297- printQuality = "FastDraft";
1298- break;
1299- case Best:
1300- printQuality = "Best";
1301- break;
1302- case Photo:
1303- printQuality = "Photo";
1304- break;
1305- case Normal:
1306- default:
1307- printQuality = "Normal";
1308- break;
1309- }
1310- __CUPS_ADD_OPTION(cups_dest, "OutputMode", printQuality.toLocal8Bit());
1311-
1312- return true;
1313-}
1314-
1315-QString Printer::makeOutputFilepath() const
1316-{
1317- QDir dir(QStandardPaths::writableLocation(QStandardPaths::TempLocation));
1318-
1319- if (!dir.exists()) {
1320- dir.mkpath(".");
1321- }
1322-
1323- QFileInfo fileInfo(dir.path(), QDateTime::currentDateTime().toString(Qt::ISODate));
1324- return fileInfo.absoluteFilePath();
1325-}
1326-
1327-QString Printer::name() const
1328-{
1329- return m_name;
1330-}
1331-
1332-bool Printer::pdfMode() const
1333-{
1334- return m_pdf_mode;
1335-}
1336-
1337-bool Printer::print(Document *doc)
1338-{
1339- // TODO: PDF mode!
1340- if (m_pdf_mode) {
1341- Q_EMIT exportRequest(doc->url().toLocalFile());
1342-
1343-// cupsTempFd();
1344- return true;
1345- }
1346-
1347- // Get all the dests
1348- int num_dests; Q_UNUSED(num_dests)
1349- cups_dest_t *dests;
1350-
1351- num_dests = cupsGetDests(&dests); // FIXME: appear to need to run this first?
1352-
1353- for (int i=0; i < num_dests; i++) {
1354- qDebug() << "Dest" << dests[i].name;
1355- }
1356-
1357- cupsFreeDests(num_dests, dests);
1358-
1359- // Ensure the destination is free
1360- if (m_cups_dest) {
1361- cupsFreeDests(1, m_cups_dest);
1362-
1363- m_cups_dest = 0;
1364- }
1365-
1366- // Get the destination
1367- // TODO: IPP, cupsGetDestWithURI()
1368- m_cups_dest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, m_cups_name.toLocal8Bit().data(), m_cups_instance.toLocal8Bit().data());
1369-
1370- if (!m_cups_dest) {
1371- qWarning() << "Could not find printer:" << m_name;
1372- return false;
1373- }
1374-
1375- // Load the printer options
1376- loadOptions(m_cups_dest, doc);
1377-
1378- // Load title
1379- QString title = doc->title();
1380-
1381- if (title.isEmpty()) {
1382- title = doc->url().fileName();
1383- }
1384-
1385- // Send to the printer
1386- m_job_id = cupsPrintFile(m_cups_dest->name,
1387- doc->url().toLocalFile().toLocal8Bit().data(),
1388- title.toLocal8Bit().data(),
1389- m_cups_dest->num_options, m_cups_dest->options);
1390-
1391- if (m_job_id == 0) {
1392- qWarning() << "Creating Job Failed:" << cupsLastErrorString();
1393- return false;
1394- } else {
1395- qDebug() << "JobID" << m_job_id;
1396- return true;
1397- }
1398-}
1399-
1400-void Printer::setColorMode(Printer::ColorMode colorMode)
1401-{
1402- if (m_color_mode != colorMode) {
1403- m_color_mode = colorMode;
1404-
1405- Q_EMIT colorModeChanged();
1406- }
1407-}
1408-
1409-void Printer::setCopies(int copies)
1410-{
1411- if (m_copies != copies) {
1412- m_copies = copies;
1413-
1414- Q_EMIT copiesChanged();
1415- }
1416-}
1417-
1418-void Printer::setDuplex(bool duplex)
1419-{
1420- if (m_duplex != duplex) {
1421- m_duplex = duplex;
1422-
1423- Q_EMIT duplexChanged();
1424- }
1425-}
1426-
1427-void Printer::setDuplexSupported(bool duplexSupported)
1428-{
1429- if (m_duplex_supported != duplexSupported) {
1430- m_duplex_supported = duplexSupported;
1431-
1432- Q_EMIT duplexSupportedChanged();
1433- }
1434-}
1435-
1436-void Printer::setName(QString name)
1437-{
1438- if (m_name != name) {
1439- m_name = name;
1440-
1441- if (m_pdf_mode) {
1442- setDuplexSupported(false);
1443- } else {
1444- // Extract the cups name and instance from the m_name
1445- QStringList split = m_name.split("/");
1446-
1447- m_cups_name = split.takeFirst();
1448- m_cups_instance = split.isEmpty() ? "" : split.takeFirst();
1449-
1450- if (split.length() > 0) {
1451- qWarning() << "Unknown printer name pattern:" << m_name;
1452- return;
1453- }
1454-
1455- loadDuplexModes(m_cups_name);
1456- }
1457-
1458- Q_EMIT nameChanged();
1459- Q_EMIT settingsChanged();
1460- }
1461-}
1462-
1463-void Printer::setPdfMode(bool pdfMode)
1464-{
1465- if (m_pdf_mode != pdfMode) {
1466- m_pdf_mode = pdfMode;
1467-
1468- Q_EMIT pdfModeChanged();
1469- }
1470-}
1471-
1472-void Printer::setQuality(Quality quality)
1473-{
1474- if (m_quality != quality) {
1475- m_quality = quality;
1476-
1477- Q_EMIT qualityChanged();
1478- }
1479-}
1480-
1481-Printer::Quality Printer::quality() const
1482-{
1483- return m_quality;
1484-}
1485
1486=== removed file 'backend/Ubuntu_Printing_App/printer.h'
1487--- backend/Ubuntu_Printing_App/printer.h 2016-12-13 12:08:15 +0000
1488+++ backend/Ubuntu_Printing_App/printer.h 1970-01-01 00:00:00 +0000
1489@@ -1,94 +0,0 @@
1490-#ifndef PRINTER_H
1491-#define PRINTER_H
1492-
1493-#include <QtCore/QObject>
1494-
1495-#include <cups/cups.h>
1496-#include <cups/ppd.h>
1497-
1498-#include "document.h"
1499-
1500-class Printer : public QObject
1501-{
1502- Q_OBJECT
1503-
1504- Q_PROPERTY(ColorMode colorMode READ colorMode WRITE setColorMode NOTIFY colorModeChanged)
1505- Q_PROPERTY(int copies READ copies WRITE setCopies NOTIFY copiesChanged)
1506- Q_PROPERTY(bool duplex READ duplex WRITE setDuplex NOTIFY duplexChanged)
1507- Q_PROPERTY(bool duplexSupported READ duplexSupported NOTIFY duplexSupportedChanged)
1508- Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
1509- Q_PROPERTY(bool pdfMode READ pdfMode WRITE setPdfMode NOTIFY pdfModeChanged)
1510- Q_PROPERTY(Quality quality READ quality WRITE setQuality NOTIFY qualityChanged)
1511-public:
1512- enum ColorMode
1513- {
1514- Color,
1515- GrayScale,
1516- };
1517- Q_ENUMS(ColorMode)
1518-
1519- enum Quality
1520- {
1521- Draft,
1522- Normal,
1523- Best,
1524- Photo,
1525- };
1526- Q_ENUMS(Quality)
1527-
1528- explicit Printer(QObject *parent = 0);
1529- ~Printer();
1530- ColorMode colorMode() const;
1531- int copies() const;
1532- bool duplex() const;
1533- bool duplexSupported() const;
1534- QString name() const;
1535- bool pdfMode() const;
1536- Quality quality() const;
1537-
1538- Q_INVOKABLE bool print(Document *doc);
1539-signals:
1540- void colorModeChanged();
1541- void copiesChanged();
1542- void duplexChanged();
1543- void duplexSupportedChanged();
1544- void nameChanged();
1545- void settingsChanged();
1546- void pdfModeChanged();
1547- void qualityChanged();
1548-
1549- void exportRequest(const QString &filepath);
1550-public slots:
1551- void setColorMode(ColorMode colorMode);
1552- void setCopies(int copies);
1553- void setDuplex(bool duplex);
1554- void setDuplexSupported(bool duplexSupported);
1555- void setName(QString name);
1556- void setPdfMode(bool pdfMode);
1557- void setQuality(Quality quality);
1558-private:
1559- void loadDuplexModes(const QString name);
1560- bool loadOptions(cups_dest_t *cups_dest, Document *doc);
1561- QString makeOutputFilepath() const;
1562-
1563- ColorMode m_color_mode;
1564- int m_copies;
1565-
1566- cups_dest_t *m_cups_dest;
1567- QString m_cups_instance;
1568- QString m_cups_name;
1569-
1570- bool m_duplex;
1571- QList<QString> m_duplex_modes;
1572- bool m_duplex_supported;
1573- int m_job_id;
1574- QString m_name;
1575-
1576- ppd_file_t *m_ppd;
1577-
1578- bool m_pdf_mode;
1579- Quality m_quality;
1580-
1581-};
1582-
1583-#endif // PRINTER_H
1584
1585=== removed file 'backend/Ubuntu_Printing_App/printerinfo.cpp'
1586--- backend/Ubuntu_Printing_App/printerinfo.cpp 2016-12-12 17:09:39 +0000
1587+++ backend/Ubuntu_Printing_App/printerinfo.cpp 1970-01-01 00:00:00 +0000
1588@@ -1,39 +0,0 @@
1589-#include "printerinfo.h"
1590-
1591-#include <QtPrintSupport/QPrinterInfo>
1592-
1593-PrinterInfo::PrinterInfo(QObject *parent) : QObject(parent)
1594-{
1595- m_available_printer_names = QStringList() << QPrinterInfo::availablePrinterNames() << "Create PDF";
1596- m_default_printer_name = QPrinterInfo::defaultPrinterName();
1597-
1598- // Watch printers for updates
1599- m_timer_printers = new QTimer(this);
1600- connect(m_timer_printers, SIGNAL(timeout()), this, SLOT(updatePrinters()));
1601- m_timer_printers->start(5000);
1602-}
1603-
1604-QStringList PrinterInfo::availablePrinterNames() const
1605-{
1606- return m_available_printer_names;
1607-}
1608-
1609-QString PrinterInfo::defaultPrinterName() const
1610-{
1611- return m_default_printer_name;
1612-}
1613-
1614-void PrinterInfo::updatePrinters()
1615-{
1616- if (m_available_printer_names != QStringList() << QPrinterInfo::availablePrinterNames() << "Create PDF") {
1617- m_available_printer_names = QStringList() << QPrinterInfo::availablePrinterNames() << "Create PDF";
1618-
1619- Q_EMIT availablePrinterNamesChanged();
1620- }
1621-
1622- if (m_default_printer_name != QPrinterInfo::defaultPrinterName()) {
1623- m_default_printer_name = QPrinterInfo::defaultPrinterName();
1624-
1625- Q_EMIT defaultPrinterNameChanged();
1626- }
1627-}
1628
1629=== removed file 'backend/Ubuntu_Printing_App/printerinfo.h'
1630--- backend/Ubuntu_Printing_App/printerinfo.h 2016-11-25 16:47:10 +0000
1631+++ backend/Ubuntu_Printing_App/printerinfo.h 1970-01-01 00:00:00 +0000
1632@@ -1,30 +0,0 @@
1633-#ifndef PRINTERINFO_H
1634-#define PRINTERINFO_H
1635-
1636-#include <QtCore/QObject>
1637-#include <QtCore/QString>
1638-#include <QtCore/QStringList>
1639-#include <QtCore/QTimer>
1640-
1641-class PrinterInfo : public QObject
1642-{
1643- Q_OBJECT
1644-
1645- Q_PROPERTY(QStringList availablePrinterNames READ availablePrinterNames NOTIFY availablePrinterNamesChanged)
1646- Q_PROPERTY(QString defaultPrinterName READ defaultPrinterName NOTIFY defaultPrinterNameChanged)
1647-public:
1648- explicit PrinterInfo(QObject *parent = 0);
1649- QStringList availablePrinterNames() const;
1650- QString defaultPrinterName() const;
1651-signals:
1652- void availablePrinterNamesChanged();
1653- void defaultPrinterNameChanged();
1654-private slots:
1655- void updatePrinters();
1656-private:
1657- QStringList m_available_printer_names;
1658- QString m_default_printer_name;
1659- QTimer *m_timer_printers;
1660-};
1661-
1662-#endif // PRINTERINFO_H
1663
1664=== removed directory 'backend/tests'
1665=== removed directory 'backend/tests/unit'
1666=== removed file 'backend/tests/unit/tst_mytype.qml'
1667--- backend/tests/unit/tst_mytype.qml 2016-12-13 12:37:45 +0000
1668+++ backend/tests/unit/tst_mytype.qml 1970-01-01 00:00:00 +0000
1669@@ -1,49 +0,0 @@
1670-import QtQuick 2.4
1671-import QtTest 1.0
1672-import Ubuntu.Components 1.3
1673-import Ubuntu_Printing_App 1.0
1674-
1675-// See more details @ http://qt-project.org/doc/qt-5.0/qtquick/qml-testcase.html
1676-
1677-// Execute tests with:
1678-// qmltestrunner
1679-
1680-Item {
1681- // The objects
1682- MyType {
1683- id: objectUnderTest
1684- }
1685-
1686- TestCase {
1687- name: "MyType"
1688-
1689- function init() {
1690- console.debug(">> init");
1691- compare("",objectUnderTest.helloWorld,"text was not empty on init");
1692- console.debug("<< init");
1693- }
1694-
1695- function cleanup() {
1696- console.debug(">> cleanup");
1697- console.debug("<< cleanup");
1698- }
1699-
1700- function initTestCase() {
1701- console.debug(">> initTestCase");
1702- console.debug("<< initTestCase");
1703- }
1704-
1705- function cleanupTestCase() {
1706- console.debug(">> cleanupTestCase");
1707- console.debug("<< cleanupTestCase");
1708- }
1709-
1710- function test_canReadAndWriteText() {
1711- var expected = "Hello World 2";
1712-
1713- objectUnderTest.helloWorld = expected;
1714-
1715- compare(expected,objectUnderTest.helloWorld,"expected did not equal result");
1716- }
1717- }
1718-}
1719
1720=== modified file 'debian/changelog'
1721--- debian/changelog 2016-12-09 22:02:22 +0000
1722+++ debian/changelog 2017-02-08 21:32:20 +0000
1723@@ -2,4 +2,4 @@
1724
1725 * Initial release
1726
1727- -- Andrew Hayzen <ahayzen@gmail.com> Fri, 09 Dec 2016 21:54:12 +0000
1728+ -- Andrew Hayzen <andrew.hayzen@canonical.com> Fri, 09 Dec 2016 21:54:12 +0000
1729
1730=== modified file 'debian/control'
1731--- debian/control 2016-12-14 01:01:39 +0000
1732+++ debian/control 2017-02-08 21:32:20 +0000
1733@@ -1,27 +1,36 @@
1734 Source: ubuntu-printing-app
1735-Section: unknown
1736+Section: misc
1737 Priority: optional
1738-Maintainer: Andrew Hayzen <ahayzen@gmail.com>
1739+Maintainer: Andrew Hayzen <andrew.hayzen@canonical.com>
1740 Build-Depends: cmake (>= 2.8.9),
1741 debhelper (>=9),
1742 dh-apparmor,
1743 dh-translations,
1744- libcups2-dev,
1745 libpoppler-qt5-dev,
1746 qmlscene,
1747+ qml-module-qtquick2,
1748+ qml-module-qtquick-layouts,
1749+ qml-module-qttest,
1750+ qml-module-ubuntu-settings-components,
1751+ qml-module-ubuntu-test,
1752+ qtdeclarative5-ubuntu-content1,
1753+ qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3),
1754 qt5-default,
1755 qt5-qmake,
1756 qtdeclarative5-dev,
1757- ubuntu-sdk-qmake-extras
1758+ qtdeclarative5-dev-tools,
1759+ ubuntu-sdk-qmake-extras,
1760+ xvfb
1761 Standards-Version: 3.9.6
1762-Homepage: <insert the upstream URL, if relevant>
1763+Homepage: http://launchpad.net/ubuntu-printing-app
1764+Vcs-Bzr: https://code.launchpad.net/~phablet-team/ubuntu-printing-app/trunk
1765
1766 Package: ubuntu-printing-app
1767 Architecture: any
1768 Depends: ${shlibs:Depends}, ${misc:Depends},
1769- libcups2,
1770 qml-module-qtquick2,
1771 qml-module-qtquick-layouts,
1772+ qml-module-ubuntu-settings-components,
1773 qtdeclarative5-ubuntu-content1,
1774 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.3) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.3),
1775 Description: Printing app which consumes a PDF from content-hub
1776
1777=== modified file 'debian/copyright'
1778--- debian/copyright 2016-12-09 22:02:22 +0000
1779+++ debian/copyright 2017-02-08 21:32:20 +0000
1780@@ -1,6 +1,6 @@
1781 Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
1782 Upstream-Name: ubuntu-printing-app
1783-Source: <url://example.com>
1784+Source: https://code.launchpad.net/ubuntu-printing-app
1785
1786 Files: *
1787 Copyright: 2016 Canonical Ltd.
1788
1789=== removed file 'manifest.json.in'
1790--- manifest.json.in 2016-12-13 23:08:52 +0000
1791+++ manifest.json.in 1970-01-01 00:00:00 +0000
1792@@ -1,16 +0,0 @@
1793-{
1794- "name": "ubuntu-printing-app.ahayzen",
1795- "description": "A basic printing app for Ubuntu",
1796- "architecture": "@CLICK_ARCH@",
1797- "title": "ubuntu-printing-app",
1798- "hooks": {
1799- "ubuntu-printing-app": {
1800- "apparmor": "ubuntu-printing-app/ubuntu-printing-app.apparmor",
1801- "content-hub": "ubuntu-printing-app/ubuntu-printing-app-content-hub.json",
1802- "desktop": "ubuntu-printing-app/ubuntu-printing-app.desktop"
1803- }
1804- },
1805- "version": "0.1",
1806- "maintainer": "Andrew Hayzen <ahayzen@gmail.com>",
1807- "framework": "ubuntu-sdk-15.04.6"
1808-}
1809
1810=== added directory 'po'
1811=== added file 'po/CMakeLists.txt'
1812--- po/CMakeLists.txt 1970-01-01 00:00:00 +0000
1813+++ po/CMakeLists.txt 2017-02-08 21:32:20 +0000
1814@@ -0,0 +1,44 @@
1815+project(ubuntu-printing-app-translations)
1816+
1817+include(FindGettext)
1818+find_program(GETTEXT_XGETTEXT_EXECUTABLE xgettext)
1819+
1820+file(RELATIVE_PATH DESKTOP_FILE_IN_IN ${CMAKE_SOURCE_DIR}
1821+ ${CMAKE_SOURCE_DIR}/ubuntu-printing-app/${DESKTOP_FILE}.in.in)
1822+file(RELATIVE_PATH DESKTOP_FILE_IN_IN_H ${CMAKE_SOURCE_DIR}
1823+ ${CMAKE_CURRENT_SOURCE_DIR}/${DESKTOP_FILE_IN_IN}.h)
1824+
1825+file(GLOB_RECURSE I18N_SRC_FILES
1826+ RELATIVE ${CMAKE_SOURCE_DIR}
1827+ ${CMAKE_SOURCE_DIR}/ubuntu-printing-app/**.qml)
1828+list(SORT I18N_SRC_FILES)
1829+
1830+set(DOMAIN ${GETTEXT_PACKAGE})
1831+set(POT_FILE ${DOMAIN}.pot)
1832+file(GLOB PO_FILES *.po)
1833+
1834+add_custom_target(${POT_FILE} ALL
1835+ COMMENT "Generating translation template"
1836+ COMMAND touch ${POT_FILE}
1837+ COMMAND ${INTLTOOL_EXTRACT} --update --type=gettext/ini
1838+ --srcdir=${CMAKE_SOURCE_DIR} ${DESKTOP_FILE_IN_IN}
1839+ COMMAND ${GETTEXT_XGETTEXT_EXECUTABLE} -o ${POT_FILE}
1840+ -D ${CMAKE_SOURCE_DIR}
1841+ --from-code=UTF-8
1842+ --c++ --qt --add-comments=TRANSLATORS
1843+ --keyword=tr --keyword=tr:1,2 --keyword=N_
1844+ -j
1845+ --package-name=ubuntu-printing-app
1846+ --copyright-holder='Canonical Ltd.'
1847+ -D ${CMAKE_SOURCE_DIR} ${I18N_SRC_FILES}
1848+ -D ${CMAKE_BINARY_DIR} ${DESKTOP_FILE_IN_IN_H}
1849+ COMMAND ${CMAKE_COMMAND} -E copy ${POT_FILE} ${CMAKE_CURRENT_SOURCE_DIR})
1850+
1851+foreach(PO_FILE ${PO_FILES})
1852+ get_filename_component(LANG ${PO_FILE} NAME_WE)
1853+ gettext_process_po_files(${LANG} ALL PO_FILES ${PO_FILE})
1854+ set(INSTALL_DIR ${CMAKE_INSTALL_LOCALEDIR}/${LANG}/LC_MESSAGES)
1855+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${LANG}.gmo
1856+ DESTINATION ${INSTALL_DIR}
1857+ RENAME ${DOMAIN}.mo)
1858+endforeach(PO_FILE)
1859
1860=== added file 'po/ubuntu-printing-app.pot'
1861--- po/ubuntu-printing-app.pot 1970-01-01 00:00:00 +0000
1862+++ po/ubuntu-printing-app.pot 2017-02-08 21:32:20 +0000
1863@@ -0,0 +1,122 @@
1864+# SOME DESCRIPTIVE TITLE.
1865+# Copyright (C) YEAR Canonical Ltd.
1866+# This file is distributed under the same license as the ubuntu-printing-app package.
1867+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
1868+#
1869+#, fuzzy
1870+msgid ""
1871+msgstr ""
1872+"Project-Id-Version: ubuntu-printing-app\n"
1873+"Report-Msgid-Bugs-To: \n"
1874+"POT-Creation-Date: 2017-02-08 21:19+0100\n"
1875+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1876+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1877+"Language-Team: LANGUAGE <LL@li.org>\n"
1878+"Language: \n"
1879+"MIME-Version: 1.0\n"
1880+"Content-Type: text/plain; charset=CHARSET\n"
1881+"Content-Transfer-Encoding: 8bit\n"
1882+
1883+#: ubuntu-printing-app/Main.qml:55
1884+msgid "Document is invalid"
1885+msgstr ""
1886+
1887+#: ubuntu-printing-app/Main.qml:58
1888+msgid "Document not found"
1889+msgstr ""
1890+
1891+#: ubuntu-printing-app/Main.qml:61
1892+msgid "Not a PDF document"
1893+msgstr ""
1894+
1895+#: ubuntu-printing-app/Main.qml:64
1896+msgid "An unknown error occurred"
1897+msgstr ""
1898+
1899+#: ubuntu-printing-app/Main.qml:76
1900+msgid "Error"
1901+msgstr ""
1902+
1903+#: ubuntu-printing-app/Main.qml:96
1904+msgid "URL of PDF to print"
1905+msgstr ""
1906+
1907+#: ubuntu-printing-app/components/AlertDialog.qml:28
1908+msgid "OK"
1909+msgstr ""
1910+
1911+#: ubuntu-printing-app/components/PrintRow.qml:56
1912+msgid "Cancel"
1913+msgstr ""
1914+
1915+#: ubuntu-printing-app/components/PrintRow.qml:69
1916+msgid "Create PDF"
1917+msgstr ""
1918+
1919+#: ubuntu-printing-app/components/PrintRow.qml:69
1920+msgid "Print"
1921+msgstr ""
1922+
1923+#: ubuntu-printing-app/components/PrintRow.qml:69
1924+msgid "Sheets"
1925+msgstr ""
1926+
1927+#: ubuntu-printing-app/pages/ContentPeerPickerPage.qml:43
1928+msgid "Open With..."
1929+msgstr ""
1930+
1931+#: ubuntu-printing-app/pages/PrintPage.qml:47
1932+msgid "Page Setup"
1933+msgstr ""
1934+
1935+#: ubuntu-printing-app/pages/PrintPage.qml:47
1936+msgid "Printer Options"
1937+msgstr ""
1938+
1939+#: ubuntu-printing-app/pages/PrintPage.qml:85
1940+msgid "Printer"
1941+msgstr ""
1942+
1943+#: ubuntu-printing-app/pages/PrintPage.qml:97
1944+msgid "Copies"
1945+msgstr ""
1946+
1947+#: ubuntu-printing-app/pages/PrintPage.qml:120
1948+msgid "Collate"
1949+msgstr ""
1950+
1951+#: ubuntu-printing-app/pages/PrintPage.qml:140
1952+msgid "Reverse"
1953+msgstr ""
1954+
1955+#: ubuntu-printing-app/pages/PrintPage.qml:163
1956+msgid "Two-sided"
1957+msgstr ""
1958+
1959+#: ubuntu-printing-app/pages/PrintPage.qml:182
1960+msgid "All"
1961+msgstr ""
1962+
1963+#: ubuntu-printing-app/pages/PrintPage.qml:182
1964+msgid "Range"
1965+msgstr ""
1966+
1967+#: ubuntu-printing-app/pages/PrintPage.qml:186
1968+msgid "Pages"
1969+msgstr ""
1970+
1971+#: ubuntu-printing-app/pages/PrintPage.qml:228
1972+msgid "eg 1-3,8"
1973+msgstr ""
1974+
1975+#: ubuntu-printing-app/pages/PrintPage.qml:237
1976+msgid "Color"
1977+msgstr ""
1978+
1979+#: ubuntu-printing-app/pages/PrintPage.qml:258
1980+msgid "Quality"
1981+msgstr ""
1982+
1983+#: po/ubuntu-printing-app/ubuntu-printing-app.desktop.in.in.h:1
1984+msgid "ubuntu-printing-app"
1985+msgstr ""
1986
1987=== modified file 'runner/CMakeLists.txt'
1988--- runner/CMakeLists.txt 2016-12-13 23:08:52 +0000
1989+++ runner/CMakeLists.txt 2017-02-08 21:32:20 +0000
1990@@ -1,6 +1,9 @@
1991
1992 # Install runner
1993-install(FILES "ubuntu-printing-app" DESTINATION ${CMAKE_INSTALL_BINDIR})
1994+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ubuntu-printing-app.in ${CMAKE_CURRENT_BINARY_DIR}/${RUNNER})
1995+
1996+install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${RUNNER} DESTINATION ${CMAKE_INSTALL_BINDIR})
1997+
1998
1999 # Show in QtC
2000-add_custom_target(ubuntu_printing_app_runner_files ALL SOURCES ubuntu-printing-app)
2001+add_custom_target(ubuntu_printing_app_runner_files ALL SOURCES ubuntu-printing-app.in)
2002
2003=== removed file 'runner/ubuntu-printing-app'
2004--- runner/ubuntu-printing-app 2016-12-13 14:23:08 +0000
2005+++ runner/ubuntu-printing-app 1970-01-01 00:00:00 +0000
2006@@ -1,3 +0,0 @@
2007-#!/bin/sh
2008-
2009-qmlscene -qt5 /usr/share/ubuntu-printing-app/Main.qml
2010
2011=== added file 'runner/ubuntu-printing-app.in'
2012--- runner/ubuntu-printing-app.in 1970-01-01 00:00:00 +0000
2013+++ runner/ubuntu-printing-app.in 2017-02-08 21:32:20 +0000
2014@@ -0,0 +1,3 @@
2015+#!/bin/sh
2016+
2017+@EXEC@
2018
2019=== added directory 'setup'
2020=== added directory 'setup/gui'
2021=== added file 'setup/gui/ubuntu-printing-app.desktop'
2022--- setup/gui/ubuntu-printing-app.desktop 1970-01-01 00:00:00 +0000
2023+++ setup/gui/ubuntu-printing-app.desktop 2017-02-08 21:32:20 +0000
2024@@ -0,0 +1,8 @@
2025+[Desktop Entry]
2026+Name=ubuntu-printing-app
2027+Exec=ubuntu-printing-app
2028+Icon=${SNAP}/meta/gui/ubuntu-printing-app.png
2029+Terminal=false
2030+Type=Application
2031+X-Ubuntu-Touch=true
2032+X-Ubuntu-Touch-Single-Instance=false
2033
2034=== added file 'setup/gui/ubuntu-printing-app.png'
2035Binary files setup/gui/ubuntu-printing-app.png 1970-01-01 00:00:00 +0000 and setup/gui/ubuntu-printing-app.png 2017-02-08 21:32:20 +0000 differ
2036=== added directory 'snap'
2037=== added directory 'snap/ubuntu-app-platform'
2038=== added file 'snapcraft.yaml'
2039--- snapcraft.yaml 1970-01-01 00:00:00 +0000
2040+++ snapcraft.yaml 2017-02-08 21:32:20 +0000
2041@@ -0,0 +1,75 @@
2042+name: ubuntu-printing-app
2043+version: "0.1"
2044+summary: "Printing app which consumes a PDF from content-hub"
2045+description: Printing app which consumes a PDF document from
2046+ content-hub, allows for basic configuration and
2047+ then sends to a CUPS printer.
2048+confinement: strict
2049+
2050+apps:
2051+ ubuntu-printing-app:
2052+ command: desktop-launch $SNAP/usr/bin/ubuntu-printing-app --desktop_file_hint=unity8
2053+ plugs:
2054+ - cups-control
2055+ - home
2056+ - network
2057+ - opengl
2058+ - platform
2059+ - unity7
2060+ - unity8
2061+
2062+plugs:
2063+ platform:
2064+ interface: content
2065+ content: ubuntu-app-platform1
2066+ target: ubuntu-app-platform
2067+ default-provider: ubuntu-app-platform
2068+
2069+parts:
2070+ ubuntu-printing-app:
2071+ build-packages:
2072+ - intltool
2073+ - libpoppler-qt5-dev
2074+ - qml-module-qttest
2075+ - qml-module-ubuntu-test
2076+ - qt5-default
2077+ - qt5-qmake
2078+ - qtdeclarative5-dev
2079+ - ubuntu-sdk-qmake-extras
2080+ - xvfb
2081+ configflags: [-DCMAKE_INSTALL_PREFIX=/usr, -DSNAP_MODE=on]
2082+ plugin: cmake
2083+ source: .
2084+ after: [printer-components, desktop-ubuntu-app-platform]
2085+
2086+ printer-components:
2087+ plugin: cmake
2088+ configflags: [-DCMAKE_INSTALL_PREFIX=/usr]
2089+ source: https://code.launchpad.net/~phablet-team/ubuntu-settings-components/printer-components
2090+ source-type: bzr
2091+ build-packages:
2092+ - cmake-extras
2093+ - libcups2-dev
2094+ - libqt5printsupport5
2095+ - debhelper
2096+ - gettext
2097+ - pkg-config
2098+ - python3
2099+ - qml-module-qt-labs-folderlistmodel
2100+ - qml-module-qtquick-layouts
2101+ - qml-module-qtquick2
2102+ - qml-module-qttest
2103+ - qml-module-ubuntu-components
2104+ - qml-module-ubuntu-thumbnailer0.1
2105+ - qtbase5-dev
2106+ - qtbase5-private-dev
2107+ - qtdeclarative5-dev
2108+ - qtdeclarative5-dev-tools
2109+ - suru-icon-theme
2110+ stage-packages:
2111+ - libcups2
2112+ - libqt5printsupport5
2113+
2114+ environment:
2115+ source: snap/
2116+ plugin: dump
2117
2118=== added directory 'tests'
2119=== added file 'tests/CMakeLists.txt'
2120--- tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
2121+++ tests/CMakeLists.txt 2017-02-08 21:32:20 +0000
2122@@ -0,0 +1,3 @@
2123+add_subdirectory(resources)
2124+add_subdirectory(qmltests)
2125+add_subdirectory(unittests)
2126
2127=== added directory 'tests/qmltests'
2128=== added file 'tests/qmltests/CMakeLists.txt'
2129--- tests/qmltests/CMakeLists.txt 1970-01-01 00:00:00 +0000
2130+++ tests/qmltests/CMakeLists.txt 2017-02-08 21:32:20 +0000
2131@@ -0,0 +1,46 @@
2132+find_package(Qt5Core REQUIRED)
2133+find_package(Qt5Gui REQUIRED)
2134+find_package(Qt5Qml REQUIRED)
2135+find_package(Qt5Quick REQUIRED)
2136+find_package(Qt5QuickTest REQUIRED)
2137+
2138+find_program(XVFBRUN xvfb-run)
2139+if(NOT XVFBRUN)
2140+ message(FATAL_ERROR "Could not find xvfb-run, please install the xvfb package")
2141+endif()
2142+set(XVFB_COMMAND ${XVFBRUN} -s "-screen 0 640x480x24" -a)
2143+
2144+find_program(QMLTESTRUNNER qmltestrunner)
2145+if(NOT QMLTESTRUNNER)
2146+ message(FATAL_ERROR "Could not find qmltestrunner, please install the package qtdeclarative5-dev-tools")
2147+endif()
2148+
2149+set(TEST tst_QmlTests)
2150+add_test(${TEST} ${XVFB_COMMAND} ${QMLTESTRUNNER}
2151+ -input ${CMAKE_CURRENT_SOURCE_DIR}
2152+ -import ${CMAKE_BINARY_DIR}/backend)
2153+
2154+
2155+# Add the qml test files to build dir
2156+set(QMLTEST_FILES
2157+ tst_CheckBoxRow.qml
2158+ tst_LabelRow.qml
2159+ tst_PreviewRow.qml
2160+ tst_PrintRow.qml
2161+ tst_PrintPage.qml
2162+ tst_SelectorRow.qml
2163+ tst_TextFieldRow.qml
2164+)
2165+
2166+add_custom_target(qmltest_copyFiles ALL
2167+ COMMENT "Copying files: ${QMLTEST_FILES}")
2168+
2169+foreach(FILENAME ${QMLTEST_FILES})
2170+ add_custom_command(
2171+ TARGET qmltest_copyFiles
2172+ COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}" "${CMAKE_CURRENT_BINARY_DIR}/${FILENAME}"
2173+ )
2174+endforeach(FILENAME)
2175+
2176+# Show in QtC
2177+add_custom_target(qmltest_files ALL SOURCES ${QMLTEST_FILES})
2178
2179=== added file 'tests/qmltests/tst_CheckBoxRow.qml'
2180--- tests/qmltests/tst_CheckBoxRow.qml 1970-01-01 00:00:00 +0000
2181+++ tests/qmltests/tst_CheckBoxRow.qml 2017-02-08 21:32:20 +0000
2182@@ -0,0 +1,87 @@
2183+/*
2184+ * Copyright 2017 Canonical Ltd.
2185+ *
2186+ * This file is part of ubuntu-printing-app.
2187+ *
2188+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
2189+ * it under the terms of the GNU General Public License as published by
2190+ * the Free Software Foundation; version 3.
2191+ *
2192+ * ubuntu-printing-app is distributed in the hope that it will be useful,
2193+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2194+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2195+ * GNU General Public License for more details.
2196+ *
2197+ * You should have received a copy of the GNU General Public License
2198+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2199+ *
2200+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
2201+ */
2202+import QtQuick 2.4
2203+import QtTest 1.1
2204+import Ubuntu.Test 1.0
2205+import "../../ubuntu-printing-app/components"
2206+
2207+Item {
2208+ width: units.gu(100)
2209+ height: units.gu(75)
2210+
2211+ CheckBoxRow {
2212+ id: checkBoxRow
2213+ }
2214+
2215+ UbuntuTestCase {
2216+ name: "CheckBoxRowTestCase"
2217+ when: windowShown
2218+
2219+ readonly property bool dataChecked: false
2220+ readonly property string dataCheckboxText: "checkboxText"
2221+ readonly property bool dataEnabled: true
2222+ readonly property string dataText: "text"
2223+
2224+ function init() {
2225+ checkBoxRow.checked = dataChecked;
2226+ checkBoxRow.checkboxText = dataCheckboxText;
2227+ checkBoxRow.enabled = dataEnabled;
2228+ checkBoxRow.text = dataText;
2229+
2230+ waitForRendering(checkBoxRow);
2231+ }
2232+
2233+ function test_checked() {
2234+ // Check checkbox checked state is starting value
2235+ var checkbox = findChild(checkBoxRow, "checkbox");
2236+ compare(checkBoxRow.checked, dataChecked);
2237+
2238+ // Click on the checkbox
2239+ mouseClick(checkbox);
2240+
2241+ // Check that the checked state flips
2242+ tryCompare(checkBoxRow, "checked", !dataChecked);
2243+ }
2244+
2245+ function test_checkboxText() {
2246+ // Check that the checkbox label is correct
2247+ var label = findChild(checkBoxRow, "checkboxLabel");
2248+ compare(label.text, dataCheckboxText);
2249+ }
2250+
2251+ function test_enabled() {
2252+ // Check checkbox enabled state is starting value
2253+ var checkbox = findChild(checkBoxRow, "checkbox");
2254+ compare(checkBoxRow.enabled, dataEnabled);
2255+
2256+ // Flip the enabled state
2257+ checkBoxRow.enabled = !dataEnabled;
2258+
2259+ // Check that the enabled state changes
2260+ tryCompare(checkbox, "enabled", !dataEnabled);
2261+ }
2262+
2263+ function test_text() {
2264+ // Check that the text is correct
2265+ var label = findChild(checkBoxRow, "label");
2266+ compare(label.text, dataText);
2267+ }
2268+ }
2269+}
2270
2271=== added file 'tests/qmltests/tst_LabelRow.qml'
2272--- tests/qmltests/tst_LabelRow.qml 1970-01-01 00:00:00 +0000
2273+++ tests/qmltests/tst_LabelRow.qml 2017-02-08 21:32:20 +0000
2274@@ -0,0 +1,73 @@
2275+/*
2276+ * Copyright 2017 Canonical Ltd.
2277+ *
2278+ * This file is part of ubuntu-printing-app.
2279+ *
2280+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
2281+ * it under the terms of the GNU General Public License as published by
2282+ * the Free Software Foundation; version 3.
2283+ *
2284+ * ubuntu-printing-app is distributed in the hope that it will be useful,
2285+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2286+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2287+ * GNU General Public License for more details.
2288+ *
2289+ * You should have received a copy of the GNU General Public License
2290+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2291+ *
2292+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
2293+ */
2294+import QtQuick 2.4
2295+import QtTest 1.1
2296+import Ubuntu.Test 1.0
2297+import "../../ubuntu-printing-app/components"
2298+
2299+Item {
2300+ width: units.gu(100)
2301+ height: units.gu(75)
2302+
2303+ LabelRow {
2304+ id: labelRow
2305+ }
2306+
2307+ UbuntuTestCase {
2308+ name: "LabelRowTestCase"
2309+ when: windowShown
2310+
2311+ readonly property bool dataEnabled: true
2312+ readonly property string dataPrimaryText: "Primary"
2313+ readonly property string dataSecondaryText: "Secondary"
2314+
2315+ function init() {
2316+ labelRow.enabled = dataEnabled;
2317+ labelRow.primaryText = dataPrimaryText;
2318+ labelRow.secondaryText = dataSecondaryText;
2319+
2320+ waitForRendering(labelRow);
2321+ }
2322+
2323+ function test_enabled() {
2324+ // Check that label enabled state is at the starting state
2325+ var secondary = findChild(labelRow, "secondary");
2326+ compare(labelRow.enabled, dataEnabled);
2327+
2328+ // Flip the enabled state
2329+ labelRow.enabled = !dataEnabled;
2330+
2331+ // Check that the label enabled state changes
2332+ tryCompare(secondary, "enabled", !dataEnabled);
2333+ }
2334+
2335+ function test_primaryText() {
2336+ // Check primary text is correct
2337+ var primary = findChild(labelRow, "primary");
2338+ compare(primary.text, dataPrimaryText);
2339+ }
2340+
2341+ function test_secondaryText() {
2342+ // Check secondary text is correct
2343+ var secondary = findChild(labelRow, "secondary");
2344+ compare(secondary.text, dataSecondaryText);
2345+ }
2346+ }
2347+}
2348
2349=== added file 'tests/qmltests/tst_PreviewRow.qml'
2350--- tests/qmltests/tst_PreviewRow.qml 1970-01-01 00:00:00 +0000
2351+++ tests/qmltests/tst_PreviewRow.qml 2017-02-08 21:32:20 +0000
2352@@ -0,0 +1,316 @@
2353+/*
2354+ * Copyright 2017 Canonical Ltd.
2355+ *
2356+ * This file is part of ubuntu-printing-app.
2357+ *
2358+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
2359+ * it under the terms of the GNU General Public License as published by
2360+ * the Free Software Foundation; version 3.
2361+ *
2362+ * ubuntu-printing-app is distributed in the hope that it will be useful,
2363+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2364+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2365+ * GNU General Public License for more details.
2366+ *
2367+ * You should have received a copy of the GNU General Public License
2368+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2369+ *
2370+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
2371+ */
2372+import QtQuick 2.4
2373+import QtTest 1.1
2374+import Ubuntu.Test 1.0
2375+import "../../ubuntu-printing-app/components"
2376+
2377+import UbuntuPrintingApp 1.0
2378+import Ubuntu.Settings.Printers 0.1
2379+
2380+Item {
2381+ id: root
2382+ width: units.gu(100)
2383+ height: units.gu(75)
2384+
2385+ Document {
2386+ id: testDocument
2387+ url: Qt.resolvedUrl("../resources/pdf/a4_portrait.pdf")
2388+ }
2389+
2390+ QtObject {
2391+ id: mockPrinterJob
2392+
2393+ property int colorModelType: PrinterEnum.ColorType
2394+ }
2395+
2396+ Item {
2397+ id: mockView
2398+ height: units.gu(100)
2399+ width: units.gu(100)
2400+ }
2401+
2402+ PreviewRow {
2403+ id: previewRow
2404+ document: testDocument
2405+ printerJob: mockPrinterJob
2406+ view: mockView
2407+ }
2408+
2409+ SignalSpy {
2410+ id: documentCountSpy
2411+ signalName: "onCountChanged"
2412+ target: testDocument
2413+ }
2414+
2415+ SignalSpy {
2416+ id: activityIndicatorSpy
2417+ signalName: "onRunningChanged"
2418+ // Target is set at runtime
2419+ }
2420+
2421+ UbuntuTestCase {
2422+ name: "PreviewRowTestCase"
2423+ when: windowShown
2424+
2425+ function init() {
2426+ testDocument.url = Qt.resolvedUrl("../resources/pdf/a4_portrait.pdf");
2427+
2428+ mockPrinterJob.colorModelType = PrinterEnum.ColorType;
2429+
2430+ activityIndicatorSpy.target = null;
2431+ activityIndicatorSpy.clear();
2432+ documentCountSpy.clear();
2433+
2434+ waitForRendering(previewRow);
2435+ }
2436+
2437+ function test_activityIndicator() {
2438+ var image = findChild(previewRow, "previewImage");
2439+ var activityIndicator = findChild(previewRow, "activityIndicator");
2440+ activityIndicatorSpy.target = activityIndicator;
2441+
2442+ // Change the document and wait for image to finish loading
2443+ testDocument.url = Qt.resolvedUrl("../resources/pdf/mixed_portrait.pdf");
2444+ tryCompare(image, "status", Image.Ready);
2445+
2446+ // Check that the running state changed twice false=>true=>falase
2447+ compare(activityIndicatorSpy.count, 2);
2448+ }
2449+
2450+ function test_document_image() {
2451+ var image = findChild(previewRow, "previewImage");
2452+
2453+ // Change the document
2454+ testDocument.url = Qt.resolvedUrl("../resources/pdf/mixed_portrait.pdf");
2455+
2456+ // Ensure that the image has a valid state
2457+ tryCompare(image, "status", Image.Ready);
2458+ }
2459+
2460+ function test_document_image_invalid() {
2461+ var image = findChild(previewRow, "previewImage");
2462+
2463+ // Change the document to an invalid doc
2464+ testDocument.url = Qt.resolvedUrl("../resources/pdf/text.txt");
2465+
2466+ // Ensure that the image has a valid state
2467+ // This is because the poppler renderer always generates a valid image
2468+ tryCompare(image, "status", Image.Ready);
2469+ }
2470+
2471+ function test_document_change_page_reset() {
2472+ var next = findChild(previewRow, "nextButton");
2473+ var pageHelper = previewRow.pageHelper;
2474+
2475+ // Load a multi page document and change to 2nd page
2476+ testDocument.url = Qt.resolvedUrl("../resources/pdf/mixed_portrait.pdf");
2477+
2478+ documentCountSpy.wait();
2479+ compare(documentCountSpy.count, 1);
2480+ compare(testDocument.count, 3);
2481+
2482+ mouseClick(next);
2483+ tryCompare(pageHelper, "page", 1);
2484+
2485+ // Load a single page document, check we go back to page 0
2486+ testDocument.url = Qt.resolvedUrl("../resources/pdf/a4_portrait.pdf");
2487+
2488+ documentCountSpy.wait();
2489+ compare(documentCountSpy.count, 2);
2490+ compare(testDocument.count, 1);
2491+ compare(pageHelper.page, 0);
2492+ }
2493+
2494+ function test_overlay() {
2495+ var label = findChild(previewRow, "overlayLabel");
2496+ var pageHelper = previewRow.pageHelper;
2497+ var textParts = label.text.split("/");
2498+
2499+ // Check text starts with 1/1
2500+ compare(textParts.length, 2);
2501+ compare(textParts[0], "1");
2502+ compare(textParts[1], "1");
2503+
2504+ testDocument.url = Qt.resolvedUrl("../resources/pdf/mixed_portrait.pdf");
2505+
2506+ waitForRendering(previewRow);
2507+ textParts = label.text.split("/");
2508+
2509+ // Check it has changed to 1/3
2510+ compare(textParts.length, 2);
2511+ compare(textParts[0], "1");
2512+ compare(textParts[1], "3");
2513+
2514+ pageHelper.page++;
2515+
2516+ waitForRendering(previewRow);
2517+ textParts = label.text.split("/");
2518+
2519+ // Check it has changed to 2/3
2520+ compare(textParts.length, 2);
2521+ compare(textParts[0], "2");
2522+ compare(textParts[1], "3");
2523+ }
2524+
2525+ function test_page_single() {
2526+ var next = findChild(previewRow, "nextButton");
2527+ var previous = findChild(previewRow, "previousButton");
2528+
2529+ // Check with a single page doc navigation controls are disabled
2530+ compare(next.enabled, false);
2531+ compare(previous.enabled, false);
2532+ }
2533+
2534+ function test_page_next() {
2535+ var image = findChild(previewRow, "previewImage");
2536+ var next = findChild(previewRow, "nextButton");
2537+ var pageHelper = previewRow.pageHelper;
2538+
2539+ testDocument.url = Qt.resolvedUrl("../resources/pdf/mixed_portrait.pdf");
2540+
2541+ documentCountSpy.wait();
2542+ compare(documentCountSpy.count, 1);
2543+
2544+ // Check with multi page doc, next button becomes enabled
2545+ compare(testDocument.count, 3);
2546+ compare(next.enabled, true);
2547+ compare(pageHelper.page, 0);
2548+
2549+ // Check the requested image page is 0
2550+ // image://poppler/0/true/file:///path/to/file.pdf
2551+ compare(image.source.toString().slice(0, 17), "image://poppler/0");
2552+
2553+ // Click to the next page, check still enabled
2554+ mouseClick(next);
2555+ tryCompare(pageHelper, "page", 1);
2556+ compare(next.enabled, true);
2557+
2558+ // Check the requested image page is 1
2559+ // image://poppler/1/true/file:///path/to/file.pdf
2560+ compare(image.source.toString().slice(0, 17), "image://poppler/1");
2561+
2562+ // Click to the last page, check next becomes diabled
2563+ mouseClick(next);
2564+
2565+ // Change the document
2566+ testDocument.url = Qt.resolvedUrl("../resources/pdf/mixed_portrait.pdf");
2567+
2568+ // Ensure that the image has a valid state
2569+ tryCompare(image, "status", Image.Ready);
2570+ tryCompare(pageHelper, "page", 2);
2571+ compare(next.enabled, false);
2572+
2573+ // Check the requested image page is 2
2574+ // image://poppler/2/true/file:///path/to/file.pdf
2575+ compare(image.source.toString().slice(0, 17), "image://poppler/2");
2576+ }
2577+
2578+ function test_page_previous() {
2579+ var image = findChild(previewRow, "previewImage");
2580+ var previous = findChild(previewRow, "previousButton");
2581+ var pageHelper = previewRow.pageHelper;
2582+
2583+ testDocument.url = Qt.resolvedUrl("../resources/pdf/mixed_portrait.pdf");
2584+
2585+ documentCountSpy.wait();
2586+ compare(documentCountSpy.count, 1);
2587+
2588+ // Check with mulit page doc, previous is still disabled when on 1st
2589+ compare(testDocument.count, 3);
2590+ compare(previous.enabled, false);
2591+ compare(pageHelper.page, 0)
2592+
2593+ // Check the requested image page is 0
2594+ // image://poppler/0/true/file:///path/to/file.pdf
2595+ compare(image.source.toString().slice(0, 17), "image://poppler/0");
2596+
2597+ // Check when changing to the last page, previous is enabled
2598+ pageHelper.page = 2;
2599+ tryCompare(pageHelper, "page", 2);
2600+ compare(previous.enabled, true);
2601+
2602+ // Check the requested image page is 2
2603+ // image://poppler/2/true/file:///path/to/file.pdf
2604+ compare(image.source.toString().slice(0, 17), "image://poppler/2");
2605+
2606+ // Click to the previous page, check still enabled
2607+ mouseClick(previous);
2608+ tryCompare(pageHelper, "page", 1);
2609+ compare(previous.enabled, true);
2610+
2611+ // Check the requested image page is 1
2612+ // image://poppler/1/true/file:///path/to/file.pdf
2613+ compare(image.source.toString().slice(0, 17), "image://poppler/1");
2614+
2615+ // Click to the first page, check previous becomes disabled
2616+ mouseClick(previous);
2617+ tryCompare(pageHelper, "page", 0);
2618+ compare(previous.enabled, false);
2619+
2620+ // Check the requested image page is 0
2621+ // image://poppler/0/true/file:///path/to/file.pdf
2622+ compare(image.source.toString().slice(0, 17), "image://poppler/0");
2623+ }
2624+
2625+ function test_printerJob_color() {
2626+ var image = findChild(previewRow, "previewImage");
2627+ mockPrinterJob.colorModelType = PrinterEnum.ColorType;
2628+
2629+ waitForRendering(image);
2630+
2631+ // Check the image requested is color
2632+ // image://poppler/0/true/file:///path/to/file.pdf
2633+ compare(image.source.toString().slice(0, 22), "image://poppler/0/true");
2634+ }
2635+
2636+ function test_printerJob_grayscale() {
2637+ var image = findChild(previewRow, "previewImage");
2638+ mockPrinterJob.colorModelType = PrinterEnum.GrayType;
2639+
2640+ waitForRendering(image);
2641+
2642+ // Check the image requested is grayscale
2643+ // image://poppler/0/false/file:///path/to/file.pdf
2644+ compare(image.source.toString().slice(0, 23), "image://poppler/0/false");
2645+ }
2646+
2647+ function test_view() {
2648+ // test that the implicitHeight is set from the view height
2649+ var pageHelper = previewRow.pageHelper;
2650+
2651+ // min((WIDTH - 10) / ASPECT, HEIGHT / 1.5)
2652+
2653+ // height/width of 100GU, aspect is 0.71
2654+ // min((100 - 10) / 0.71, 100 / 1.5)
2655+ // min(126.76, 66.66)
2656+ fuzzyCompare(previewRow.implicitHeight, units.gu(66.66), units.gu(1));
2657+
2658+ // Change the view to have a short width
2659+ mockView.width = units.gu(50);
2660+ waitForRendering(previewRow);
2661+
2662+ // width 50GU, height 100GU, aspect is 0.71
2663+ // min((50 - 10) / 0.71, 100 / 1.5)
2664+ // min(56.33, 66.66)
2665+ fuzzyCompare(previewRow.implicitHeight, units.gu(56.33), units.gu(1));
2666+ }
2667+ }
2668+}
2669
2670=== added file 'tests/qmltests/tst_PrintPage.qml'
2671--- tests/qmltests/tst_PrintPage.qml 1970-01-01 00:00:00 +0000
2672+++ tests/qmltests/tst_PrintPage.qml 2017-02-08 21:32:20 +0000
2673@@ -0,0 +1,437 @@
2674+/*
2675+ * Copyright 2017 Canonical Ltd.
2676+ *
2677+ * This file is part of ubuntu-printing-app.
2678+ *
2679+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
2680+ * it under the terms of the GNU General Public License as published by
2681+ * the Free Software Foundation; version 3.
2682+ *
2683+ * ubuntu-printing-app is distributed in the hope that it will be useful,
2684+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2685+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2686+ * GNU General Public License for more details.
2687+ *
2688+ * You should have received a copy of the GNU General Public License
2689+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2690+ *
2691+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
2692+ */
2693+import QtQuick 2.4
2694+import QtTest 1.1
2695+import Ubuntu.Test 1.0
2696+import "../../ubuntu-printing-app/pages"
2697+
2698+import UbuntuPrintingApp 1.0
2699+import Ubuntu.Settings.Printers 0.1
2700+
2701+Item {
2702+ width: units.gu(100)
2703+ height: units.gu(75)
2704+
2705+ // Mock the PrintingHelper
2706+ QtObject {
2707+ id: mockPrinting
2708+
2709+ property ListModel model: ListModel {
2710+
2711+ }
2712+ property bool pdfMode: false
2713+ property var printer: QtObject {
2714+ property string name: "PrinterA"
2715+ property var supportedColorModels: []
2716+ property var supportedDuplexModes: []
2717+ property var supportedPrintQualities: []
2718+ }
2719+ property var printerJob: QtObject {
2720+ property bool collate: true
2721+ property int colorModel: 0
2722+ property int copies: 1
2723+ property int duplexMode: 0
2724+ property bool isTwoSided: false
2725+ property string printRange: ""
2726+ property var printRangeMode: 0 // var as it needs to be enum
2727+ property int quality: 0
2728+ property bool reverse: false
2729+ }
2730+ property int printerSelectedIndex: 0
2731+ }
2732+
2733+ Document {
2734+ id: document
2735+ url: Qt.resolvedUrl("../resources/pdf/a4_portrait.pdf")
2736+ }
2737+
2738+ PrintPage {
2739+ id: printPage
2740+ anchors {
2741+ fill: parent
2742+ }
2743+ currentDocument: document
2744+ printing: mockPrinting
2745+ }
2746+
2747+ SignalSpy {
2748+ id: cancelSpy
2749+ signalName: "cancel"
2750+ target: printPage
2751+ }
2752+
2753+ SignalSpy {
2754+ id: confirmSpy
2755+ signalName: "confirm"
2756+ target: printPage
2757+ }
2758+
2759+ UbuntuTestCase {
2760+ name: "PrintPageTestCase"
2761+
2762+ when: windowShown
2763+
2764+ property var dataColorModels: ["A", "B", "C"]
2765+ property var dataDuplexModes: ["A", "B", "C"]
2766+ property var dataPrinters: [
2767+ {name: "PrinterA"},
2768+ {name: "PrinterB"},
2769+ ]
2770+ property var dataPrintQualities: ["A", "B", "C"]
2771+ readonly property int timeout: 1000
2772+
2773+ function init() {
2774+ document.url = Qt.resolvedUrl("../resources/pdf/a4_portrait.pdf");
2775+
2776+ mockPrinting.model.clear();
2777+ for (var i=0; i < dataPrinters.length; i++) {
2778+ mockPrinting.model.append(dataPrinters[i]);
2779+ }
2780+
2781+ mockPrinting.pdfMode = false;
2782+
2783+ mockPrinting.printer.supportedColorModels = dataColorModels;
2784+ mockPrinting.printer.supportedDuplexModes = dataDuplexModes;
2785+ mockPrinting.printer.supportedPrintQualities = dataPrintQualities;
2786+
2787+ mockPrinting.printerJob.collate = true;
2788+ mockPrinting.printerJob.copies = 1;
2789+ mockPrinting.printerJob.printRangeMode = PrinterEnum.AllPages;
2790+ mockPrinting.printerJob.reverse = false;
2791+
2792+ mockPrinting.printerSelectedIndex = 0;
2793+
2794+ cancelSpy.clear();
2795+ confirmSpy.clear();
2796+
2797+ waitForRendering(printPage, timeout);
2798+ }
2799+
2800+ function test_cancelButton() {
2801+ var cancel = findChild(printPage, "cancel");
2802+
2803+ // Click the cancel button
2804+ mouseClick(cancel);
2805+
2806+ // Check that cancel signal was emitted
2807+ cancelSpy.wait();
2808+ compare(cancelSpy.count, 1);
2809+ }
2810+
2811+ function test_cancelHeader() {
2812+ // Note SDK adds _button to objectNames in ActionBar
2813+ var cancel = findChild(printPage, "headerBack_button");
2814+
2815+ // Click cancel in the header
2816+ mouseClick(cancel);
2817+
2818+ // Check that cancel signal was emitted
2819+ cancelSpy.wait();
2820+ compare(cancelSpy.count, 1);
2821+ }
2822+
2823+ function test_collate() {
2824+ // Set copies to 2, so collate is enabled
2825+ mockPrinting.printerJob.copies = 2;
2826+ tryCompare(mockPrinting.printerJob, "copies", 2);
2827+
2828+ // Check starting value of collate is correct
2829+ var collate = findChild(printPage, "collateCheckBox");
2830+ compare(collate.enabled, true);
2831+ compare(collate.checked, true);
2832+
2833+ // Click on the checkbox
2834+ mouseClick(collate);
2835+
2836+ // Check that the value of collate has flipped
2837+ tryCompare(collate, "checked", false, timeout);
2838+ compare(mockPrinting.printerJob.collate, false);
2839+ }
2840+
2841+ function test_collate_disabled() {
2842+ // Check collate is disabled when copies is 1
2843+ var collate = findChild(printPage, "collateCheckBox");
2844+ compare(mockPrinting.printerJob.copies, 1);
2845+ compare(collate.enabled, false);
2846+
2847+ // Check that is becomes enabled when there are two copies
2848+ mockPrinting.printerJob.copies = 2;
2849+ tryCompare(collate, "enabled", true);
2850+ }
2851+
2852+ function test_colorModel() {
2853+ var colorModel = findChild(printPage, "colorModelSelector");
2854+
2855+ // Check color model length is correct
2856+ compare(colorModel.model.length, dataColorModels.length);
2857+
2858+ // Check each of the options has the correct text
2859+ for (var i=0; i < dataColorModels.length; i++) {
2860+ var option = findChild(colorModel, "option" + i);
2861+ compare(option.text, dataColorModels[i]);
2862+ }
2863+ }
2864+
2865+ function test_colorModelEmptyModels() {
2866+ // Set the colorModel to empty
2867+ var colorModel = findChild(printPage, "colorModelSelector");
2868+ mockPrinting.printer.supportedColorModels = [];
2869+
2870+ waitForRendering(colorModel, timeout)
2871+
2872+ // Check that the selector becomes disabled
2873+ compare(colorModel.enabled, false);
2874+ }
2875+
2876+ function test_colorModelSingleModel() {
2877+ // Set the colorModel to a single entry
2878+ var colorModel = findChild(printPage, "colorModelSelector");
2879+ mockPrinting.printer.supportedColorModels = ["A"];
2880+
2881+ waitForRendering(colorModel, timeout)
2882+
2883+ // Check that the selector becomes disabled
2884+ compare(colorModel.enabled, false);
2885+ }
2886+
2887+ function test_confirm() {
2888+ var confirm = findChild(printPage, "confirm");
2889+
2890+ // Click the confirm button
2891+ mouseClick(confirm);
2892+
2893+ // Check that the confirm signal was emitted
2894+ confirmSpy.wait();
2895+ compare(confirmSpy.count, 1);
2896+ compare(confirmSpy.signalArguments.length, 1);
2897+
2898+ // Check the arg in the signal was the document url
2899+ var arg = confirmSpy.signalArguments.pop();
2900+ compare(arg.length, 1);
2901+ compare(arg[0], document.url);
2902+ }
2903+
2904+ function test_copies() {
2905+ // Check copies starting value is correct
2906+ var copies = findChild(printPage, "copiesTextField");
2907+ compare(copies.value, "1");
2908+
2909+ // Change the copies value and check the textField changes
2910+ mockPrinting.printerJob.copies = 5;
2911+ tryCompare(copies, "value", "5", timeout, "Copies value did not change");
2912+ }
2913+
2914+ function test_copiesKeyClick() {
2915+ // Check copies starting value is correct
2916+ var copies = findChild(printPage, "copiesTextField");
2917+ compare(copies.value, "1");
2918+
2919+ // Click on the textField
2920+ mouseClick(copies);
2921+
2922+ // Clear the current text and enter "2"
2923+ keyClick(Qt.Key_Backspace);
2924+ keyClick(Qt.Key_2);
2925+
2926+ // Check that "2" is set to the backend
2927+ tryCompare(copies, "value", "2", timeout, "Copies value did not change");
2928+ compare(mockPrinting.printerJob.copies, 2);
2929+ }
2930+
2931+ function test_duplex() {
2932+ var duplex = findChild(printPage, "duplexSelector");
2933+
2934+ // Check the duplex model length is correct
2935+ compare(duplex.model.length, dataDuplexModes.length);
2936+
2937+ // Check each of the options has the correct text
2938+ for (var i=0; i < dataDuplexModes.length; i++) {
2939+ var option = findChild(duplex, "option" + i);
2940+ compare(option.text, dataDuplexModes[i]);
2941+ }
2942+ }
2943+
2944+ function test_duplexEmptyModes() {
2945+ // Set the duplexModes to empty and with a multipage doc
2946+ var duplex = findChild(printPage, "duplexSelector");
2947+ document.url = Qt.resolvedUrl("../resources/pdf/mixed_portrait.pdf");
2948+ mockPrinting.printer.supportedDuplexModes = [];
2949+
2950+ // Check the selector becomes disabled
2951+ waitForRendering(duplex, timeout)
2952+ compare(duplex.enabled, false);
2953+ }
2954+ function test_duplexEnabledMultiPage() {
2955+ var duplex = findChild(printPage, "duplexSelector");
2956+
2957+ // Check that with single page doc duplex is disabled
2958+ document.url = Qt.resolvedUrl("../resources/pdf/a4_portrait.pdf");
2959+ compare(duplex.enabled, false);
2960+
2961+ // Check with multi page doc, duplex becomes enabled
2962+ document.url = Qt.resolvedUrl("../resources/pdf/mixed_portrait.pdf");
2963+ tryCompare(duplex, "enabled", true, timeout,
2964+ "Duplex selected didn't become enabled when document changed");
2965+ }
2966+ function test_duplexSingleMode() {
2967+ // Set the duplexModes to a single entry and with a multipage doc
2968+ var duplex = findChild(printPage, "duplexSelector");
2969+ document.url = Qt.resolvedUrl("../resources/pdf/mixed_portrait.pdf");
2970+ mockPrinting.printer.supportedDuplexModes = ["A"];
2971+
2972+ // Check the selector becomes disabled
2973+ waitForRendering(duplex, timeout)
2974+ compare(duplex.enabled, false);
2975+ }
2976+
2977+ function testPdfMode() {
2978+ var objects = ["collateCheckBox", "copiesTextField",
2979+ "duplexSelector", "pageRangeSelector",
2980+ "pageRangeTextField", "pageRangeLabel",
2981+ "colorModelSelector", "qualitySelector",
2982+ "reverseCheckBox"];
2983+ var pageTitle = printPage.title;
2984+
2985+ // Enable pdf mode
2986+ mockPrinting.pdfMode = true;
2987+ waitForRendering(printPage, timeout);
2988+
2989+ // Check that all the selectors become disabled
2990+ for (var obj in objects) {
2991+ compare(findChild(printPage, obj).enabled, false);
2992+ }
2993+
2994+ // Check that the page title changes
2995+ verify(pageTitle !== printPage.title, "Page title did not change");
2996+ }
2997+
2998+ function test_printers() {
2999+ var printers = findChild(printPage, "printerSelector");
3000+
3001+ // Check that the printers model length is correct
3002+ compare(printers.model.count, dataPrinters.length);
3003+
3004+ // Check each of the options has the correct text
3005+ for (var i=0; i < dataPrinters.length; i++) {
3006+ var option = findChild(printers, "option" + i);
3007+ compare(option.text, dataPrinters[i]["name"]);
3008+ }
3009+ }
3010+
3011+ function test_printRangeMode() {
3012+ var printRangeMode = findChild(printPage, "pageRangeSelector");
3013+ var printRange = findChild(printPage, "pageRangeTextField");
3014+
3015+ // Check that with AllPages, printRange is not visible
3016+ compare(mockPrinting.printerJob.printRangeMode, PrinterEnum.AllPages);
3017+ compare(printRange.visible, false);
3018+
3019+ // Change to PageRange mode
3020+ mockPrinting.printerJob.printRangeMode = PrinterEnum.PageRange;
3021+
3022+ // Check that printRange becomes visible
3023+ compare(mockPrinting.printerJob.printRangeMode, PrinterEnum.PageRange);
3024+ tryCompare(printRange, "visible", true, timeout);
3025+ }
3026+
3027+ function test_quality() {
3028+ var quality = findChild(printPage, "qualitySelector");
3029+
3030+ // Check that the qualities model length is correct
3031+ compare(quality.model.length, dataPrintQualities.length);
3032+
3033+ // Check each of the options has the correct text
3034+ for (var i=0; i < dataPrintQualities.length; i++) {
3035+ var option = findChild(quality, "option" + i);
3036+ compare(option.text, dataPrintQualities[i]);
3037+ }
3038+ }
3039+
3040+ function test_qualityEmptyModels() {
3041+ // Set the qualities model to empty
3042+ var quality = findChild(printPage, "qualitySelector");
3043+ mockPrinting.printer.supportedPrintQualities = [];
3044+
3045+ // Check that the selector becomes disabled
3046+ waitForRendering(quality, timeout)
3047+ compare(quality.enabled, false);
3048+ }
3049+
3050+ function test_qualitySingleModel() {
3051+ // Set the colorModel to a single entry
3052+ var quality = findChild(printPage, "qualitySelector");
3053+ mockPrinting.printer.supportedPrintQualities = ["A"];
3054+
3055+ // Check that the selector becomes disabled
3056+ waitForRendering(quality, timeout)
3057+ compare(quality.enabled, false);
3058+ }
3059+
3060+ function test_reverse() {
3061+ // Check starting value of reverse is correct
3062+ var reverse = findChild(printPage, "reverseCheckBox");
3063+ compare(reverse.checked, false);
3064+
3065+ // Click on the checkbox
3066+ mouseClick(reverse);
3067+
3068+ // Check that the value of reverse has flipped
3069+ tryCompare(reverse, "checked", true);
3070+ compare(mockPrinting.printerJob.reverse, true);
3071+ }
3072+
3073+ function test_sheets() {
3074+ var printRow = findChild(printPage, "printRow");
3075+ compare(document.count, 1);
3076+ compare(mockPrinting.printerJob.copies, 1);
3077+ compare(mockPrinting.printerJob.isTwoSided, false);
3078+ compare(printRow.sheets, 1);
3079+
3080+ // Enable twoSided, we should get 0.5 rounded to 1 sheet
3081+ mockPrinting.printerJob.isTwoSided = true;
3082+
3083+ compare(mockPrinting.printerJob.isTwoSided, true);
3084+ compare(printRow.sheets, 1);
3085+
3086+ // Enable two copies, we should get 2 copies with duplex, so 1 sheet
3087+ mockPrinting.printerJob.copies = 2;
3088+
3089+ compare(mockPrinting.printerJob.copies, 2);
3090+ compare(printRow.sheets, 1);
3091+
3092+ // Disable two sided, so 2 copies and 2 sheets
3093+ mockPrinting.printerJob.isTwoSided = false;
3094+
3095+ compare(mockPrinting.printerJob.isTwoSided, false);
3096+ compare(printRow.sheets, 2);
3097+
3098+ // Change to a multi page document (3 pages, 2 copies so 6 sheets)
3099+ document.url = Qt.resolvedUrl("../resources/pdf/mixed_portrait.pdf");
3100+
3101+ compare(printRow.sheets, 6);
3102+
3103+ // Enable two sided, and 1 copy, check we have 3 pages, duplex so 2 sheets
3104+ mockPrinting.printerJob.copies = 1;
3105+ mockPrinting.printerJob.isTwoSided = true;
3106+
3107+ compare(printRow.sheets, 2);
3108+ }
3109+ }
3110+}
3111
3112=== added file 'tests/qmltests/tst_PrintRow.qml'
3113--- tests/qmltests/tst_PrintRow.qml 1970-01-01 00:00:00 +0000
3114+++ tests/qmltests/tst_PrintRow.qml 2017-02-08 21:32:20 +0000
3115@@ -0,0 +1,110 @@
3116+/*
3117+ * Copyright 2017 Canonical Ltd.
3118+ *
3119+ * This file is part of ubuntu-printing-app.
3120+ *
3121+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
3122+ * it under the terms of the GNU General Public License as published by
3123+ * the Free Software Foundation; version 3.
3124+ *
3125+ * ubuntu-printing-app is distributed in the hope that it will be useful,
3126+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3127+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3128+ * GNU General Public License for more details.
3129+ *
3130+ * You should have received a copy of the GNU General Public License
3131+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3132+ *
3133+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
3134+ */
3135+import QtQuick 2.4
3136+import QtTest 1.1
3137+import Ubuntu.Test 1.0
3138+import "../../ubuntu-printing-app/components"
3139+
3140+Item {
3141+ width: units.gu(100)
3142+ height: units.gu(75)
3143+
3144+ PrintRow {
3145+ id: printRow
3146+ anchors {
3147+ fill: parent
3148+ }
3149+ }
3150+
3151+ SignalSpy {
3152+ id: cancelSignal
3153+ signalName: "cancel"
3154+ target: printRow
3155+ }
3156+
3157+ SignalSpy {
3158+ id: confirmSignal
3159+ signalName: "confirm"
3160+ target: printRow
3161+ }
3162+
3163+ UbuntuTestCase {
3164+ name: "PrintRowTestCase"
3165+
3166+ when: windowShown
3167+
3168+
3169+ function init() {
3170+ printRow.pdfMode = false;
3171+ printRow.sheets = 0;
3172+
3173+ cancelSignal.clear();
3174+ confirmSignal.clear();
3175+ }
3176+
3177+ function test_clickCancel() {
3178+ var button = findChild(printRow, "cancel");
3179+ var buttonCenter = centerOf(button);
3180+ compare(cancelSignal.count, 0)
3181+
3182+ // Click on the cancel button
3183+ mouseClick(button);
3184+
3185+ // Check that the cancel signal is emitted
3186+ cancelSignal.wait();
3187+ compare(cancelSignal.count, 1)
3188+ }
3189+
3190+ function test_clickConfirm() {
3191+ var button = findChild(printRow, "confirm");
3192+ var buttonCenter = centerOf(button);
3193+ compare(confirmSignal.count, 0)
3194+
3195+ // Click on the confirm button
3196+ mouseClick(button);
3197+
3198+ // Check that the confirm signal is emitted
3199+ confirmSignal.wait();
3200+ compare(confirmSignal.count, 1)
3201+ }
3202+
3203+ function test_pdfMode() {
3204+ var button = findChild(printRow, "confirm");
3205+ var originalText = button.text;
3206+
3207+ // Change to Pdf mode
3208+ printRow.pdfMode = true;
3209+
3210+ // Check that the confirm button text changes
3211+ verify(button.text !== originalText, 1000, "Text did not change when entering PDF Mode");
3212+ }
3213+
3214+ function test_sheets() {
3215+ var button = findChild(printRow, "confirm");
3216+ var originalText = button.text;
3217+
3218+ // Change the number of sheets
3219+ printRow.sheets = 10;
3220+
3221+ // Check that the confirm button text changes
3222+ verify(button.text !== originalText, 1000, "Text did not change when changing sheets");
3223+ }
3224+ }
3225+}
3226
3227=== added file 'tests/qmltests/tst_SelectorRow.qml'
3228--- tests/qmltests/tst_SelectorRow.qml 1970-01-01 00:00:00 +0000
3229+++ tests/qmltests/tst_SelectorRow.qml 2017-02-08 21:32:20 +0000
3230@@ -0,0 +1,136 @@
3231+/*
3232+ * Copyright 2017 Canonical Ltd.
3233+ *
3234+ * This file is part of ubuntu-printing-app.
3235+ *
3236+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
3237+ * it under the terms of the GNU General Public License as published by
3238+ * the Free Software Foundation; version 3.
3239+ *
3240+ * ubuntu-printing-app is distributed in the hope that it will be useful,
3241+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3242+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3243+ * GNU General Public License for more details.
3244+ *
3245+ * You should have received a copy of the GNU General Public License
3246+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3247+ *
3248+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
3249+ */
3250+import QtQuick 2.4
3251+import QtTest 1.1
3252+import Ubuntu.Test 1.0
3253+import "../../ubuntu-printing-app/components"
3254+
3255+Item {
3256+ width: units.gu(100)
3257+ height: units.gu(75)
3258+
3259+ SelectorRow {
3260+ id: selectorRow
3261+ model: []
3262+ }
3263+
3264+ SignalSpy {
3265+ id: expansionCompletedSpy
3266+ signalName: "expansionCompleted"
3267+ target: selectorRow
3268+ }
3269+
3270+ SignalSpy {
3271+ id: selectedIndexSpy
3272+ signalName: "onSelectedIndexChanged"
3273+ target: selectorRow
3274+ }
3275+
3276+ SignalSpy {
3277+ id: selectedValueSpy
3278+ signalName: "onSelectedValueChanged"
3279+ target: selectorRow
3280+ }
3281+
3282+ UbuntuTestCase {
3283+ name: "SelectorRowTestCase"
3284+ when: windowShown
3285+
3286+ readonly property string dataLabelText: "Text"
3287+ readonly property var dataModel: ["A", "B", "C"]
3288+ readonly property int dataSelectedIndex: 0
3289+ readonly property int dataSecondarySelectedIndex: 1
3290+
3291+ function init() {
3292+ selectorRow.model = dataModel;
3293+ selectorRow.selectedIndex = dataSelectedIndex;
3294+ selectorRow.text = dataLabelText;
3295+
3296+ expansionCompletedSpy.clear();
3297+ selectedIndexSpy.clear();
3298+ selectedValueSpy.clear();
3299+
3300+ waitForRendering(selectorRow);
3301+ }
3302+
3303+ function test_changeOption() {
3304+ // Check selectedIndex is the starting index
3305+ compare(selectorRow.selectedIndex, dataSelectedIndex);
3306+
3307+ // Expand the selector
3308+ mouseClick(selectorRow);
3309+ expansionCompletedSpy.wait();
3310+ compare(expansionCompletedSpy.count, 1);
3311+
3312+ // Click on the secondary index
3313+ var option1 = findChild(selectorRow, "option" + dataSecondarySelectedIndex);
3314+ mouseClick(option1);
3315+
3316+ // Check that the selectedIndex is the secondaryIndex
3317+ selectedIndexSpy.wait();
3318+ compare(selectedIndexSpy.count, 1);
3319+ compare(selectorRow.selectedIndex, dataSecondarySelectedIndex);
3320+ }
3321+
3322+ function test_label() {
3323+ // Check that the label is correct
3324+ var label = findChild(selectorRow, "label");
3325+ compare(label.text, dataLabelText);
3326+ }
3327+
3328+ function test_model() {
3329+ // Check the model length is the starting value
3330+ compare(selectorRow.model.length, dataModel.length);
3331+
3332+ // Remove the last entry from the model
3333+ var tmpModel = dataModel;
3334+ tmpModel.pop();
3335+ selectorRow.model = tmpModel;
3336+
3337+ // Check the model length changed
3338+ compare(selectorRow.model.length, tmpModel.length);
3339+ }
3340+
3341+ function test_selectedIndex() {
3342+ // Check selectedIndex is the starting index
3343+ compare(selectorRow.selectedIndex, dataSelectedIndex);
3344+
3345+ // Change the index to the secondaryIndex
3346+ selectorRow.selectedIndex = dataSecondarySelectedIndex;
3347+
3348+ // Check the index changed
3349+ selectedIndexSpy.wait();
3350+ compare(selectedIndexSpy.count, 1);
3351+ compare(selectorRow.selectedIndex, dataSecondarySelectedIndex);
3352+ }
3353+
3354+ function test_selectedValue() {
3355+ // Check that selectedValue is the starting value
3356+ compare(selectorRow.selectedValue, dataModel[dataSelectedIndex]);
3357+
3358+ // Change to the secondaryIndex
3359+ selectorRow.selectedIndex = dataSecondarySelectedIndex;
3360+
3361+ // Check that the selectedValue changes
3362+ selectedValueSpy.wait();
3363+ compare(selectorRow.selectedValue, dataModel[dataSecondarySelectedIndex]);
3364+ }
3365+ }
3366+}
3367
3368=== added file 'tests/qmltests/tst_TextFieldRow.qml'
3369--- tests/qmltests/tst_TextFieldRow.qml 1970-01-01 00:00:00 +0000
3370+++ tests/qmltests/tst_TextFieldRow.qml 2017-02-08 21:32:20 +0000
3371@@ -0,0 +1,174 @@
3372+/*
3373+ * Copyright 2017 Canonical Ltd.
3374+ *
3375+ * This file is part of ubuntu-printing-app.
3376+ *
3377+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
3378+ * it under the terms of the GNU General Public License as published by
3379+ * the Free Software Foundation; version 3.
3380+ *
3381+ * ubuntu-printing-app is distributed in the hope that it will be useful,
3382+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3383+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3384+ * GNU General Public License for more details.
3385+ *
3386+ * You should have received a copy of the GNU General Public License
3387+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3388+ *
3389+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
3390+ */
3391+import QtQuick 2.4
3392+import QtTest 1.1
3393+import Ubuntu.Test 1.0
3394+import "../../ubuntu-printing-app/components"
3395+
3396+Item {
3397+ width: units.gu(100)
3398+ height: units.gu(75)
3399+
3400+ TextFieldRow {
3401+ id: textFieldRow
3402+ }
3403+
3404+ IntValidator {
3405+ id: intValidator
3406+ bottom: 1
3407+ top: 9
3408+ }
3409+
3410+ SignalSpy {
3411+ id: acceptableInputSpy
3412+ signalName: "onAcceptableInputChanged"
3413+ target: textFieldRow
3414+ }
3415+
3416+ SignalSpy {
3417+ id: valueSpy
3418+ signalName: "onValueChanged"
3419+ target: textFieldRow
3420+ }
3421+
3422+ UbuntuTestCase {
3423+ name: "TextFieldRowTestCase"
3424+ when: windowShown
3425+
3426+ readonly property bool dataEnabled: true
3427+ readonly property string dataPlaceholderText: "placeholder"
3428+
3429+ function init() {
3430+ textFieldRow.enabled = dataEnabled;
3431+ textFieldRow.inputMethodHints = Qt.ImhNone;
3432+ textFieldRow.placeholderText = dataPlaceholderText;
3433+ textFieldRow.text = "test";
3434+ textFieldRow.validator = null;
3435+ textFieldRow.value = "";
3436+
3437+ acceptableInputSpy.clear();
3438+ valueSpy.clear();
3439+
3440+ waitForRendering(textFieldRow);
3441+ }
3442+
3443+ function test_acceptableInput() {
3444+ var textField = findChild(textFieldRow, "textField");
3445+
3446+ // Set the validator to int (1-9)
3447+ textFieldRow.validator = intValidator;
3448+
3449+ // Set the value to an invalid value
3450+ textFieldRow.value = "99";
3451+
3452+ valueSpy.wait();
3453+ acceptableInputSpy.wait();
3454+
3455+ compare(valueSpy.count, 1);
3456+ compare(acceptableInputSpy.count, 1);
3457+
3458+ // Check the value was not acceptable
3459+ compare(textFieldRow.acceptableInput, false);
3460+ compare(textField.acceptableInput, false);
3461+
3462+ // Set the value to a valid value
3463+ textFieldRow.value = "2";
3464+
3465+ valueSpy.wait();
3466+ acceptableInputSpy.wait();
3467+
3468+ compare(valueSpy.count, 2);
3469+ compare(acceptableInputSpy.count, 2);
3470+
3471+ // Check the value was acceptable
3472+ compare(textFieldRow.acceptableInput, true);
3473+ compare(textField.acceptableInput, true);
3474+ }
3475+
3476+ function test_enabled() {
3477+ // Check textField enabled state is starting value
3478+ var textField = findChild(textFieldRow, "textField");
3479+ compare(textFieldRow.enabled, dataEnabled);
3480+
3481+ // Flip the enabled state
3482+ textFieldRow.enabled = !dataEnabled;
3483+
3484+ // Check that the enabled state changes
3485+ tryCompare(textField, "enabled", !dataEnabled);
3486+ }
3487+
3488+ function test_inputMethodHints() {
3489+ // Check that inputMethodHints is starting value
3490+ var textField = findChild(textFieldRow, "textField");
3491+ compare(textFieldRow.inputMethodHints, Qt.ImhNone);
3492+ compare(textField.inputMethodHints, Qt.ImhNone);
3493+
3494+ // Change the inputMethodHints mode
3495+ textFieldRow.inputMethodHints = Qt.ImhDigitsOnly;
3496+
3497+ // Check it changes in the textField
3498+ compare(textField.inputMethodHints, Qt.ImhDigitsOnly);
3499+ }
3500+
3501+ function test_placeholderText() {
3502+ // Check the placeholder text is correct
3503+ var textField = findChild(textFieldRow, "textField");
3504+ compare(textField.placeholderText, dataPlaceholderText);
3505+ compare(textFieldRow.placeholderText, dataPlaceholderText);
3506+
3507+ // Check that the value is not the placeholder
3508+ verify(textField.text !== dataPlaceholderText);
3509+ verify(textFieldRow.value !== dataPlaceholderText);
3510+ }
3511+
3512+ function test_text() {
3513+ // Check that the text is the correct value
3514+ var label = findChild(textFieldRow, "label");
3515+ compare(label.text, textFieldRow.text);
3516+ }
3517+
3518+ function test_validator() {
3519+ // Check that a validator can be set
3520+ var textField = findChild(textFieldRow, "textField");
3521+ textFieldRow.validator = intValidator;
3522+
3523+ compare(textField.validator, intValidator);
3524+ }
3525+
3526+ function test_value() {
3527+ // Check that the value is the starting value
3528+ var textField = findChild(textFieldRow, "textField");
3529+ compare(textFieldRow.value, "");
3530+ compare(textField.text, "");
3531+
3532+ // Click on the text field
3533+ mouseClick(textField);
3534+
3535+ // Enter "a"
3536+ keyPress(Qt.Key_A);
3537+
3538+ // Check that "a" is set to the value
3539+ valueSpy.wait();
3540+ compare(valueSpy.count, 1);
3541+ compare(textField.text, "a");
3542+ compare(textFieldRow.value, "a");
3543+ }
3544+ }
3545+}
3546
3547=== added directory 'tests/resources'
3548=== added file 'tests/resources/CMakeLists.txt'
3549--- tests/resources/CMakeLists.txt 1970-01-01 00:00:00 +0000
3550+++ tests/resources/CMakeLists.txt 2017-02-08 21:32:20 +0000
3551@@ -0,0 +1,6 @@
3552+add_subdirectory(pdf)
3553+
3554+# Copy the test pdf files to the build dir
3555+add_custom_target(test_pdf_copyFiles ALL
3556+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/pdf ${CMAKE_CURRENT_BINARY_DIR}/pdf
3557+ DEPENDS ${PDF_TEST_FILES})
3558
3559=== added directory 'tests/resources/pdf'
3560=== added file 'tests/resources/pdf/CMakeLists.txt'
3561--- tests/resources/pdf/CMakeLists.txt 1970-01-01 00:00:00 +0000
3562+++ tests/resources/pdf/CMakeLists.txt 2017-02-08 21:32:20 +0000
3563@@ -0,0 +1,3 @@
3564+# Show files in QtC
3565+file(GLOB PDF_TEST_FILES *.pdf *.txt)
3566+add_custom_target(test_pdf_files ALL SOURCES ${PDF_TEST_FILES})
3567
3568=== added file 'tests/resources/pdf/a4_portrait.pdf'
3569Binary files tests/resources/pdf/a4_portrait.pdf 1970-01-01 00:00:00 +0000 and tests/resources/pdf/a4_portrait.pdf 2017-02-08 21:32:20 +0000 differ
3570=== added file 'tests/resources/pdf/a5_landscape.pdf'
3571Binary files tests/resources/pdf/a5_landscape.pdf 1970-01-01 00:00:00 +0000 and tests/resources/pdf/a5_landscape.pdf 2017-02-08 21:32:20 +0000 differ
3572=== added file 'tests/resources/pdf/color.pdf'
3573Binary files tests/resources/pdf/color.pdf 1970-01-01 00:00:00 +0000 and tests/resources/pdf/color.pdf 2017-02-08 21:32:20 +0000 differ
3574=== added file 'tests/resources/pdf/corrupt.pdf'
3575--- tests/resources/pdf/corrupt.pdf 1970-01-01 00:00:00 +0000
3576+++ tests/resources/pdf/corrupt.pdf 2017-02-08 21:32:20 +0000
3577@@ -0,0 +1,3 @@
3578+%PDF-1.4
3579+%äüöß
3580+%%EOF
3581
3582=== added file 'tests/resources/pdf/mixed_landscape.pdf'
3583Binary files tests/resources/pdf/mixed_landscape.pdf 1970-01-01 00:00:00 +0000 and tests/resources/pdf/mixed_landscape.pdf 2017-02-08 21:32:20 +0000 differ
3584=== added file 'tests/resources/pdf/mixed_portrait.pdf'
3585Binary files tests/resources/pdf/mixed_portrait.pdf 1970-01-01 00:00:00 +0000 and tests/resources/pdf/mixed_portrait.pdf 2017-02-08 21:32:20 +0000 differ
3586=== added file 'tests/resources/pdf/test_title.pdf'
3587Binary files tests/resources/pdf/test_title.pdf 1970-01-01 00:00:00 +0000 and tests/resources/pdf/test_title.pdf 2017-02-08 21:32:20 +0000 differ
3588=== added file 'tests/resources/pdf/text.txt'
3589=== added directory 'tests/unittests'
3590=== added file 'tests/unittests/CMakeLists.txt'
3591--- tests/unittests/CMakeLists.txt 1970-01-01 00:00:00 +0000
3592+++ tests/unittests/CMakeLists.txt 2017-02-08 21:32:20 +0000
3593@@ -0,0 +1,1 @@
3594+add_subdirectory(backend)
3595
3596=== added directory 'tests/unittests/backend'
3597=== added file 'tests/unittests/backend/CMakeLists.txt'
3598--- tests/unittests/backend/CMakeLists.txt 1970-01-01 00:00:00 +0000
3599+++ tests/unittests/backend/CMakeLists.txt 2017-02-08 21:32:20 +0000
3600@@ -0,0 +1,19 @@
3601+include_directories(
3602+ ${CMAKE_CURRENT_SOURCE_DIR}
3603+ ${CMAKE_CURRENT_BINARY_DIR}
3604+ ${CMAKE_SOURCE_DIR}/backend/
3605+)
3606+
3607+find_package(Qt5Test REQUIRED)
3608+
3609+add_executable(testDocument tst_document.cpp ${PDF_TEST_FILES})
3610+target_link_libraries(testDocument UbuntuPrintingAppbackend Qt5::Test Qt5::Gui)
3611+add_test(tst_document testDocument)
3612+
3613+add_executable(testPageHelper tst_pagehelper.cpp ${PDF_TEST_FILES})
3614+target_link_libraries(testPageHelper UbuntuPrintingAppbackend Qt5::Test Qt5::Gui)
3615+add_test(tst_pagehelper testPageHelper)
3616+
3617+add_executable(testPopplerImageProvider tst_popplerimageprovider.cpp ${PDF_TEST_FILES})
3618+target_link_libraries(testPopplerImageProvider UbuntuPrintingAppbackend Qt5::Test Qt5::Gui)
3619+add_test(tst_popplerimageprovider testPopplerImageProvider)
3620
3621=== added file 'tests/unittests/backend/tst_document.cpp'
3622--- tests/unittests/backend/tst_document.cpp 1970-01-01 00:00:00 +0000
3623+++ tests/unittests/backend/tst_document.cpp 2017-02-08 21:32:20 +0000
3624@@ -0,0 +1,301 @@
3625+/*
3626+ * Copyright 2017 Canonical Ltd.
3627+ *
3628+ * This file is part of ubuntu-printing-app.
3629+ *
3630+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
3631+ * it under the terms of the GNU General Public License as published by
3632+ * the Free Software Foundation; version 3.
3633+ *
3634+ * ubuntu-printing-app is distributed in the hope that it will be useful,
3635+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3636+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3637+ * GNU General Public License for more details.
3638+ *
3639+ * You should have received a copy of the GNU General Public License
3640+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3641+ *
3642+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
3643+ */
3644+
3645+#include <QDebug>
3646+#include <QObject>
3647+#include <QSignalSpy>
3648+#include <QTest>
3649+
3650+#include "UbuntuPrintingApp/document.h"
3651+
3652+#define A4_PORTRAIT_SIZE QSize(595, 842)
3653+#define A4_LANDSCAPE_SIZE QSize(842, 595)
3654+#define A5_LANDSCAPE_SIZE QSize(595, 420)
3655+
3656+#define INVALID_IMAGE_SIZE QSize(0, 0)
3657+#define VALID_IMAGE_SIZE QSize(100, 100)
3658+
3659+Q_DECLARE_METATYPE(Document::Errors)
3660+
3661+class TestDocument : public QObject
3662+{
3663+ Q_OBJECT
3664+private Q_SLOTS:
3665+ void init()
3666+ {
3667+ qRegisterMetaType<Document::Errors>("Errors");
3668+
3669+ m_document = new Document();
3670+ }
3671+ void cleanup()
3672+ {
3673+ QSignalSpy destroyedSpy(m_document, SIGNAL(destroyed(QObject*)));
3674+ m_document->deleteLater();
3675+ QTRY_COMPARE(destroyedSpy.count(), 1);
3676+ }
3677+ QUrl getResourceUrl(const QString &resource) const
3678+ {
3679+ return QUrl("file://" + QDir::currentPath() + "/../../resources/pdf/" + resource);
3680+ }
3681+
3682+ void testInit()
3683+ {
3684+ QCOMPARE(m_document->count(), 0);
3685+ QCOMPARE(m_document->getPageSize(0), QSizeF());
3686+ QCOMPARE(m_document->getPageSize(0).isValid(), false);
3687+ QCOMPARE(m_document->orientation(), Document::Portrait);
3688+ QCOMPARE(m_document->title(), QStringLiteral(""));
3689+ QCOMPARE(m_document->url(), QUrl(QStringLiteral("")));
3690+ }
3691+
3692+ void testCountSinglePage()
3693+ {
3694+ QSignalSpy countSpy(m_document, SIGNAL(countChanged()));
3695+ m_document->setUrl(getResourceUrl("a4_portrait.pdf"));
3696+ QTRY_COMPARE(countSpy.count(), 1);
3697+ QCOMPARE(m_document->count(), 1);
3698+ }
3699+ void testCountMultiPage()
3700+ {
3701+ QSignalSpy countSpy(m_document, SIGNAL(countChanged()));
3702+ m_document->setUrl(getResourceUrl("mixed_portrait.pdf"));
3703+ QTRY_COMPARE(countSpy.count(), 1);
3704+ QCOMPARE(m_document->count(), 3);
3705+ }
3706+
3707+ void testGetPageSizeA4()
3708+ {
3709+ QSignalSpy urlSpy(m_document, SIGNAL(urlChanged()));
3710+ m_document->setUrl(getResourceUrl("a4_portrait.pdf"));
3711+ QTRY_COMPARE(urlSpy.count(), 1);
3712+ // Use QSize to compare otherwise double's will be slightly different
3713+ QCOMPARE(m_document->getPageSize(0).toSize(), A4_PORTRAIT_SIZE);
3714+ }
3715+ void testGetPageSizeMixed()
3716+ {
3717+ QSignalSpy urlSpy(m_document, SIGNAL(urlChanged()));
3718+ m_document->setUrl(getResourceUrl("mixed_portrait.pdf"));
3719+ QTRY_COMPARE(urlSpy.count(), 1);
3720+ // Use QSize to compare otherwise double's will be slightly different
3721+ QCOMPARE(m_document->getPageSize(0).toSize(), A4_PORTRAIT_SIZE);
3722+
3723+ // Check that second page size is landscape as this is a mixed document
3724+ QCOMPARE(m_document->getPageSize(1).toSize(), A4_LANDSCAPE_SIZE);
3725+ }
3726+ void testGetPageSizeA5Landscape()
3727+ {
3728+ QSignalSpy urlSpy(m_document, SIGNAL(urlChanged()));
3729+ m_document->setUrl(getResourceUrl("a5_landscape.pdf"));
3730+ QTRY_COMPARE(urlSpy.count(), 1);
3731+ // Use QSize to compare otherwise double's will be slightly different
3732+ QCOMPARE(m_document->getPageSize(0).toSize(), A5_LANDSCAPE_SIZE);
3733+ }
3734+
3735+ void testMakeImage()
3736+ {
3737+ QSignalSpy urlSpy(m_document, SIGNAL(urlChanged()));
3738+ m_document->setUrl(getResourceUrl("a4_portrait.pdf"));
3739+ QTRY_COMPARE(urlSpy.count(), 1);
3740+
3741+ QImage image = m_document->makeImage(VALID_IMAGE_SIZE, 0);
3742+ QCOMPARE(image.isNull(), false);
3743+ QCOMPARE(image.size(), VALID_IMAGE_SIZE);
3744+ }
3745+ void testMakeImageInvalidDocument()
3746+ {
3747+ QImage image = m_document->makeImage(VALID_IMAGE_SIZE, 0);
3748+ QCOMPARE(image.isNull(), true);
3749+ }
3750+ void testMakeImageInvalidPage()
3751+ {
3752+ QSignalSpy urlSpy(m_document, SIGNAL(urlChanged()));
3753+ m_document->setUrl(getResourceUrl("a4_portrait.pdf"));
3754+ QTRY_COMPARE(urlSpy.count(), 1);
3755+
3756+ QImage image = m_document->makeImage(VALID_IMAGE_SIZE, 1000);
3757+ QCOMPARE(image.isNull(), true);
3758+ }
3759+ void testMakeImageInvalidSize()
3760+ {
3761+ QSignalSpy urlSpy(m_document, SIGNAL(urlChanged()));
3762+ m_document->setUrl(getResourceUrl("a4_portrait.pdf"));
3763+ QTRY_COMPARE(urlSpy.count(), 1);
3764+
3765+ QImage image = m_document->makeImage(INVALID_IMAGE_SIZE, 0);
3766+ QCOMPARE(image.isNull(), true);
3767+ }
3768+ void testMakeImageNegativePage()
3769+ {
3770+ QImage image = m_document->makeImage(VALID_IMAGE_SIZE, -1);
3771+ QCOMPARE(image.isNull(), true);
3772+ }
3773+ void testMakeImageInvalidRenderToImage()
3774+ {
3775+ QSKIP("TODO: need to have a test to hit the case where renderToImage returns a null image");
3776+ }
3777+
3778+
3779+ void testMakeImageToFit()
3780+ {
3781+ QSignalSpy urlSpy(m_document, SIGNAL(urlChanged()));
3782+ m_document->setUrl(getResourceUrl("a4_portrait.pdf"));
3783+ QTRY_COMPARE(urlSpy.count(), 1);
3784+
3785+ QImage image = m_document->makeImageToFit(VALID_IMAGE_SIZE, 0, true);
3786+ QCOMPARE(image.isNull(), false);
3787+ QCOMPARE(image.size(), VALID_IMAGE_SIZE);
3788+ }
3789+ void testMakeImageToFitColor()
3790+ {
3791+ QSignalSpy urlSpy(m_document, SIGNAL(urlChanged()));
3792+ m_document->setUrl(getResourceUrl("color.pdf"));
3793+ QTRY_COMPARE(urlSpy.count(), 1);
3794+
3795+ QImage image = m_document->makeImageToFit(VALID_IMAGE_SIZE, 0, true);
3796+ QCOMPARE(image.isNull(), false);
3797+ QCOMPARE(image.size(), VALID_IMAGE_SIZE);
3798+ QCOMPARE(image.isGrayscale(), false);
3799+ }
3800+ void testMakeImageToFitGrayscale()
3801+ {
3802+ QSignalSpy urlSpy(m_document, SIGNAL(urlChanged()));
3803+ m_document->setUrl(getResourceUrl("color.pdf"));
3804+ QTRY_COMPARE(urlSpy.count(), 1);
3805+
3806+ QImage image = m_document->makeImageToFit(VALID_IMAGE_SIZE, 0, false);
3807+ QCOMPARE(image.isNull(), false);
3808+ QCOMPARE(image.size(), VALID_IMAGE_SIZE);
3809+ QCOMPARE(image.isGrayscale(), true);
3810+ }
3811+ void testMakeImageToFitInvalidDocument()
3812+ {
3813+ QImage image = m_document->makeImageToFit(VALID_IMAGE_SIZE, 0, true);
3814+ QCOMPARE(image.isNull(), true);
3815+ }
3816+ void testMakeImageToFitInvalidPage()
3817+ {
3818+ QSignalSpy urlSpy(m_document, SIGNAL(urlChanged()));
3819+ m_document->setUrl(getResourceUrl("a4_portrait.pdf"));
3820+ QTRY_COMPARE(urlSpy.count(), 1);
3821+
3822+ QImage image = m_document->makeImageToFit(VALID_IMAGE_SIZE, 1000, true);
3823+ QCOMPARE(image.isNull(), true);
3824+ }
3825+ void testMakeImageToFitInvalidSize()
3826+ {
3827+ QSignalSpy urlSpy(m_document, SIGNAL(urlChanged()));
3828+ m_document->setUrl(getResourceUrl("a4_portrait.pdf"));
3829+ QTRY_COMPARE(urlSpy.count(), 1);
3830+
3831+ QImage image = m_document->makeImageToFit(INVALID_IMAGE_SIZE, 0, true);
3832+ QCOMPARE(image.isNull(), true);
3833+ }
3834+ void testMakeImageToFitNegativePage()
3835+ {
3836+ QImage image = m_document->makeImageToFit(VALID_IMAGE_SIZE, -1, true);
3837+ QCOMPARE(image.isNull(), true);
3838+ }
3839+
3840+
3841+ void testOrientationPortrait()
3842+ {
3843+ QSignalSpy orientationSpy(m_document, SIGNAL(orientationChanged()));
3844+ m_document->setUrl(getResourceUrl("a4_portrait.pdf"));
3845+ QTRY_COMPARE(orientationSpy.count(), 1);
3846+ QCOMPARE(m_document->orientation(), Document::Orientation::Portrait);
3847+ }
3848+ void testOrientationLandscape()
3849+ {
3850+ QSignalSpy orientationSpy(m_document, SIGNAL(orientationChanged()));
3851+ m_document->setUrl(getResourceUrl("a5_landscape.pdf"));
3852+ QTRY_COMPARE(orientationSpy.count(), 1);
3853+ QCOMPARE(m_document->orientation(), Document::Orientation::Landscape);
3854+ }
3855+ void testOrientationMixedPortrait()
3856+ {
3857+ QSignalSpy orientationSpy(m_document, SIGNAL(orientationChanged()));
3858+ m_document->setUrl(getResourceUrl("mixed_portrait.pdf"));
3859+ QTRY_COMPARE(orientationSpy.count(), 1);
3860+ QCOMPARE(m_document->orientation(), Document::Orientation::Portrait);
3861+ }
3862+ void testOrientationMixedLandscape()
3863+ {
3864+ QSignalSpy orientationSpy(m_document, SIGNAL(orientationChanged()));
3865+ m_document->setUrl(getResourceUrl("mixed_landscape.pdf"));
3866+ QTRY_COMPARE(orientationSpy.count(), 1);
3867+ QCOMPARE(m_document->orientation(), Document::Orientation::Landscape);
3868+ }
3869+
3870+ void testTitle()
3871+ {
3872+ QSignalSpy titleSpy(m_document, SIGNAL(titleChanged()));
3873+ m_document->setUrl(getResourceUrl("test_title.pdf"));
3874+ QTRY_COMPARE(titleSpy.count(), 1);
3875+ QCOMPARE(m_document->title(), QStringLiteral("Test Title Document"));
3876+ }
3877+
3878+ void testUrl()
3879+ {
3880+ QSignalSpy errorSpy(m_document, SIGNAL(error(Document::Errors)));
3881+ QSignalSpy urlSpy(m_document, SIGNAL(urlChanged()));
3882+
3883+ QUrl resource = getResourceUrl("a4_portrait.pdf");
3884+
3885+ m_document->setUrl(resource);
3886+ QTRY_COMPARE(urlSpy.count(), 1);
3887+ QCOMPARE(errorSpy.count(), 0);
3888+ QCOMPARE(m_document->url(), resource);
3889+ }
3890+ void testUrlNotFound()
3891+ {
3892+ QSignalSpy errorSpy(m_document, SIGNAL(error(Document::Errors)));
3893+ m_document->setUrl(getResourceUrl("notfound.pdf"));
3894+ QTRY_COMPARE(errorSpy.count(), 1);
3895+ QCOMPARE(m_document->url(), QUrl(QStringLiteral("")));
3896+
3897+ QList<QVariant> args = errorSpy.takeFirst();
3898+ QCOMPARE(args.at(0).toInt(), (int) Document::Errors::ErrorNotFound);
3899+ }
3900+ void testUrlNotPdf()
3901+ {
3902+ QSignalSpy errorSpy(m_document, SIGNAL(error(Document::Errors)));
3903+ m_document->setUrl(getResourceUrl("text.txt"));
3904+ QTRY_COMPARE(errorSpy.count(), 1);
3905+ QCOMPARE(m_document->url(), QUrl(QStringLiteral("")));
3906+
3907+ QList<QVariant> args = errorSpy.takeFirst();
3908+ QCOMPARE(args.at(0).toInt(), (int) Document::Errors::ErrorNotPdf);
3909+ }
3910+ void testUrlInvalidDocument()
3911+ {
3912+ QSignalSpy errorSpy(m_document, SIGNAL(error(Document::Errors)));
3913+ m_document->setUrl(getResourceUrl("corrupt.pdf"));
3914+ QTRY_COMPARE(errorSpy.count(), 1);
3915+ QCOMPARE(m_document->url(), QUrl(QStringLiteral("")));
3916+
3917+ QList<QVariant> args = errorSpy.takeFirst();
3918+ QCOMPARE(args.at(0).toInt(), (int) Document::Errors::ErrorDocumentInvalid);
3919+ }
3920+private:
3921+ Document *m_document;
3922+};
3923+
3924+QTEST_GUILESS_MAIN(TestDocument)
3925+#include "tst_document.moc"
3926
3927=== added file 'tests/unittests/backend/tst_pagehelper.cpp'
3928--- tests/unittests/backend/tst_pagehelper.cpp 1970-01-01 00:00:00 +0000
3929+++ tests/unittests/backend/tst_pagehelper.cpp 2017-02-08 21:32:20 +0000
3930@@ -0,0 +1,171 @@
3931+/*
3932+ * Copyright 2017 Canonical Ltd.
3933+ *
3934+ * This file is part of ubuntu-printing-app.
3935+ *
3936+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
3937+ * it under the terms of the GNU General Public License as published by
3938+ * the Free Software Foundation; version 3.
3939+ *
3940+ * ubuntu-printing-app is distributed in the hope that it will be useful,
3941+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3942+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3943+ * GNU General Public License for more details.
3944+ *
3945+ * You should have received a copy of the GNU General Public License
3946+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3947+ *
3948+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
3949+ */
3950+
3951+#include <QDebug>
3952+#include <QObject>
3953+#include <QSignalSpy>
3954+#include <QTest>
3955+
3956+#include "UbuntuPrintingApp/document.h"
3957+#include "UbuntuPrintingApp/pagehelper.h"
3958+
3959+#define A4_PORTRAIT_ASPECT_RATIO 595.0 / 842.0
3960+#define A4_LANDSCAPE_ASPECT_RATIO 842.0 / 595.0
3961+#define A5_LANDSCAPE_ASPECT_RATIO 595.0 / 420.0
3962+
3963+class TestPageHelper : public QObject
3964+{
3965+ Q_OBJECT
3966+private Q_SLOTS:
3967+ void init()
3968+ {
3969+ m_document = new Document();
3970+ m_page_helper = new PageHelper();
3971+ m_page_helper->setDocument(m_document);
3972+ }
3973+ void cleanup()
3974+ {
3975+ QSignalSpy destroyedPageHelperSpy(m_page_helper, SIGNAL(destroyed(QObject*)));
3976+ m_page_helper->deleteLater();
3977+ QTRY_COMPARE(destroyedPageHelperSpy.count(), 1);
3978+
3979+ QSignalSpy destroyedDocumentSpy(m_document, SIGNAL(destroyed(QObject*)));
3980+ m_document->deleteLater();
3981+ QTRY_COMPARE(destroyedDocumentSpy.count(), 1);
3982+ }
3983+ QUrl getResourceUrl(const QString &resource) const
3984+ {
3985+ return QUrl("file://" + QDir::currentPath() + "/../../resources/pdf/" + resource);
3986+ }
3987+
3988+ void testInit()
3989+ {
3990+ QCOMPARE(m_page_helper->aspect(), A4_PORTRAIT_ASPECT_RATIO);
3991+ QCOMPARE(m_page_helper->document(), m_document);
3992+ QCOMPARE(m_page_helper->page(), 0);
3993+ }
3994+
3995+ void testAspect()
3996+ {
3997+ QSignalSpy aspectSpy(m_page_helper, SIGNAL(aspectChanged()));
3998+ m_document->setUrl(getResourceUrl("a5_landscape.pdf"));
3999+ QTRY_COMPARE(aspectSpy.count(), 1);
4000+ QCOMPARE(m_page_helper->aspect(), A5_LANDSCAPE_ASPECT_RATIO);
4001+ }
4002+ void testAspectA4Document()
4003+ {
4004+ QSignalSpy aspectSpy(m_page_helper, SIGNAL(aspectChanged()));
4005+ m_document->setUrl(getResourceUrl("a5_landscape.pdf"));
4006+ QTRY_COMPARE(aspectSpy.count(), 1);
4007+ QCOMPARE(m_page_helper->aspect(), A5_LANDSCAPE_ASPECT_RATIO);
4008+
4009+ m_document->setUrl(getResourceUrl("a4_portrait.pdf"));
4010+ QTRY_COMPARE(aspectSpy.count(), 2);
4011+ QCOMPARE(m_page_helper->aspect(), A4_PORTRAIT_ASPECT_RATIO);
4012+ }
4013+ void testAspectFallsBack()
4014+ {
4015+ QSignalSpy aspectSpy(m_page_helper, SIGNAL(aspectChanged()));
4016+ m_document->setUrl(getResourceUrl("a5_landscape.pdf"));
4017+ QTRY_COMPARE(aspectSpy.count(), 1);
4018+ QCOMPARE(m_page_helper->aspect(), A5_LANDSCAPE_ASPECT_RATIO);
4019+
4020+ // Test when set to a new document that it goes back to A4
4021+ Document *newDoc = new Document();
4022+ m_page_helper->setDocument(newDoc);
4023+ QTRY_COMPARE(aspectSpy.count(), 2);
4024+ QCOMPARE(m_page_helper->aspect(), A4_PORTRAIT_ASPECT_RATIO);
4025+
4026+ newDoc->deleteLater();
4027+ }
4028+
4029+ void testDocument()
4030+ {
4031+ QSignalSpy documentSpy(m_page_helper, SIGNAL(documentChanged()));
4032+ Document *newDoc = new Document();
4033+ m_page_helper->setDocument(newDoc);
4034+ QTRY_COMPARE(documentSpy.count(), 1);
4035+ QCOMPARE(m_page_helper->document(), newDoc);
4036+ }
4037+ void testDocumentDisconnect()
4038+ {
4039+ QSignalSpy documentSpy(m_page_helper, SIGNAL(documentChanged()));
4040+ Document *newDoc = new Document();
4041+ m_page_helper->setDocument(newDoc);
4042+ QTRY_COMPARE(documentSpy.count(), 1);
4043+ QCOMPARE(m_page_helper->document(), newDoc);
4044+
4045+ // Check that changing the old document doesn't cause signals that were
4046+ // linked to be fired - eg loading of aspect
4047+ QSignalSpy aspectSpy(m_page_helper, SIGNAL(aspectChanged()));
4048+ QSignalSpy urlSpy(m_document, SIGNAL(urlChanged()));
4049+ m_document->setUrl(getResourceUrl("a5_landscape.pdf"));
4050+ QTRY_COMPARE(urlSpy.count(), 1);
4051+ QCOMPARE(aspectSpy.count(), 0);
4052+
4053+ newDoc->deleteLater();
4054+ }
4055+
4056+ void testDocumentUrlChange()
4057+ {
4058+ QSignalSpy aspectSpy(m_page_helper, SIGNAL(aspectChanged()));
4059+ m_document->setUrl(getResourceUrl("a5_landscape.pdf"));
4060+ QTRY_COMPARE(aspectSpy.count(), 1);
4061+
4062+ QCOMPARE(m_page_helper->aspect(), A5_LANDSCAPE_ASPECT_RATIO);
4063+ }
4064+
4065+ void testPageMixedLandscape()
4066+ {
4067+ QSignalSpy aspectSpy(m_page_helper, SIGNAL(aspectChanged()));
4068+ QSignalSpy pageSpy(m_page_helper, SIGNAL(pageChanged()));
4069+ m_document->setUrl(getResourceUrl("mixed_landscape.pdf"));
4070+ QTRY_COMPARE(aspectSpy.count(), 1);
4071+ QCOMPARE(m_page_helper->page(), 0);
4072+ QCOMPARE(m_page_helper->aspect(), A4_LANDSCAPE_ASPECT_RATIO);
4073+
4074+ m_page_helper->setPage(1);
4075+ QTRY_COMPARE(pageSpy.count(), 1);
4076+ QCOMPARE(m_page_helper->page(), 1);
4077+ QTRY_COMPARE(aspectSpy.count(), 2);
4078+ QCOMPARE(m_page_helper->aspect(), A4_PORTRAIT_ASPECT_RATIO);
4079+ }
4080+ void testPageMixedPortrait()
4081+ {
4082+ QSignalSpy aspectSpy(m_page_helper, SIGNAL(aspectChanged()));
4083+ QSignalSpy pageSpy(m_page_helper, SIGNAL(pageChanged()));
4084+ m_document->setUrl(getResourceUrl("mixed_portrait.pdf"));
4085+ QCOMPARE(aspectSpy.count(), 0);
4086+ QCOMPARE(m_page_helper->aspect(), A4_PORTRAIT_ASPECT_RATIO);
4087+
4088+ m_page_helper->setPage(1);
4089+ QTRY_COMPARE(pageSpy.count(), 1);
4090+ QCOMPARE(m_page_helper->page(), 1);
4091+ QTRY_COMPARE(aspectSpy.count(), 1);
4092+ QCOMPARE(m_page_helper->aspect(), A4_LANDSCAPE_ASPECT_RATIO);
4093+ }
4094+
4095+private:
4096+ Document *m_document;
4097+ PageHelper *m_page_helper;
4098+};
4099+
4100+QTEST_GUILESS_MAIN(TestPageHelper)
4101+#include "tst_pagehelper.moc"
4102
4103=== added file 'tests/unittests/backend/tst_popplerimageprovider.cpp'
4104--- tests/unittests/backend/tst_popplerimageprovider.cpp 1970-01-01 00:00:00 +0000
4105+++ tests/unittests/backend/tst_popplerimageprovider.cpp 2017-02-08 21:32:20 +0000
4106@@ -0,0 +1,127 @@
4107+/*
4108+ * Copyright 2017 Canonical Ltd.
4109+ *
4110+ * This file is part of ubuntu-printing-app.
4111+ *
4112+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
4113+ * it under the terms of the GNU General Public License as published by
4114+ * the Free Software Foundation; version 3.
4115+ *
4116+ * ubuntu-printing-app is distributed in the hope that it will be useful,
4117+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4118+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4119+ * GNU General Public License for more details.
4120+ *
4121+ * You should have received a copy of the GNU General Public License
4122+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4123+ *
4124+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
4125+ */
4126+
4127+#include <QDebug>
4128+#include <QObject>
4129+#include <QSignalSpy>
4130+#include <QTest>
4131+
4132+#include "UbuntuPrintingApp/popplerimageprovider.h"
4133+
4134+class TestPopplerImageProvider : public QObject
4135+{
4136+ Q_OBJECT
4137+private Q_SLOTS:
4138+ void init()
4139+ {
4140+ m_provider = new PopplerImageProvider();
4141+ }
4142+ void cleanup()
4143+ {
4144+ delete m_provider;
4145+ }
4146+ QUrl getResourceUrl(const QString &resource) const
4147+ {
4148+ return QUrl("file://" + QDir::currentPath() + "/../../resources/pdf/" + resource);
4149+ }
4150+
4151+ void testRequestImage()
4152+ {
4153+ QString id = "0/true/" + getResourceUrl("color.pdf").toString();
4154+ QSize *size = new QSize();
4155+ QSize requestedSize(250, 250);
4156+
4157+ QImage result = m_provider->requestImage(id, size, requestedSize);
4158+
4159+ QCOMPARE(result.isNull(), false);
4160+ QCOMPARE(result.size(), requestedSize);
4161+ QCOMPARE(*size, requestedSize);
4162+ QCOMPARE(result.isGrayscale(), false);
4163+ }
4164+ void testRequestImageGrayscale()
4165+ {
4166+ QString id = "0/false/" + getResourceUrl("color.pdf").toString();
4167+ QSize *size = new QSize();
4168+ QSize requestedSize(250, 250);
4169+
4170+ QImage result = m_provider->requestImage(id, size, requestedSize);
4171+
4172+ QCOMPARE(result.isNull(), false);
4173+ QCOMPARE(result.size(), requestedSize);
4174+ QCOMPARE(*size, requestedSize);
4175+ QCOMPARE(result.isGrayscale(), true);
4176+ }
4177+ void testRequestImageMultiPage()
4178+ {
4179+ // TODO: is there a way we can confirm that the image is showing the 2nd page?
4180+ QString id = "1/true/" + getResourceUrl("mixed_portrait.pdf").toString();
4181+ QSize *size = new QSize();
4182+ QSize requestedSize(250, 250);
4183+
4184+ QImage result = m_provider->requestImage(id, size, requestedSize);
4185+
4186+ QCOMPARE(result.isNull(), false);
4187+ QCOMPARE(result.size(), requestedSize);
4188+ QCOMPARE(*size, requestedSize);
4189+ QCOMPARE(result.isGrayscale(), true);
4190+ }
4191+
4192+ void testRequestImageInvalidColor()
4193+ {
4194+ QString id = "0/abc/" + getResourceUrl("a4_portrait.pdf").toString();
4195+ QSize *size = new QSize();
4196+ QSize requestedSize(250, 250);
4197+
4198+ QImage result = m_provider->requestImage(id, size, requestedSize);
4199+
4200+ QCOMPARE(result.isNull(), true);
4201+ QCOMPARE((*size), requestedSize);
4202+ }
4203+ void testRequestImageInvalidPage()
4204+ {
4205+ QString id = "1000/true/" + getResourceUrl("a4_portrait.pdf").toString();
4206+ QSize *size = new QSize();
4207+ QSize requestedSize(250, 250);
4208+
4209+ QImage result = m_provider->requestImage(id, size, requestedSize);
4210+
4211+ QCOMPARE(result.isNull(), true);
4212+ QCOMPARE((*size), requestedSize);
4213+ }
4214+ void testRequestImageInvalidRequestedSize()
4215+ {
4216+ QString id = "0/true/" + getResourceUrl("a4_portrait.pdf").toString();
4217+ QSize *size = new QSize();
4218+ QSize requestedSize(-100, -50);
4219+
4220+ QImage result = m_provider->requestImage(id, size, requestedSize);
4221+
4222+ // An invalid request size returns a size of 1,1 otherwise QML errors occur
4223+ QCOMPARE(result.isNull(), false);
4224+ QCOMPARE(result.size(), QSize(1, 1));
4225+ QCOMPARE((*size), QSize(1, 1));
4226+ }
4227+
4228+private:
4229+ PopplerImageProvider *m_provider;
4230+};
4231+
4232+QTEST_GUILESS_MAIN(TestPopplerImageProvider)
4233+#include "tst_popplerimageprovider.moc"
4234
4235=== modified file 'ubuntu-printing-app/CMakeLists.txt'
4236--- ubuntu-printing-app/CMakeLists.txt 2016-12-13 23:08:52 +0000
4237+++ ubuntu-printing-app/CMakeLists.txt 2017-02-08 21:32:20 +0000
4238@@ -1,4 +1,5 @@
4239 add_subdirectory(components)
4240+add_subdirectory(pages)
4241
4242 # Install Main.qml and icon
4243 install(FILES ${MAIN_QML} DESTINATION ${UBUNTU_PRINTING_APP_DATA_DIR})
4244@@ -23,6 +24,6 @@
4245
4246 # Show in QtCreator
4247 if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
4248- file(GLOB MAIN_QML_JS_FILES *.qml *.js)
4249+ file(GLOB MAIN_QML_JS_FILES *.apparmor *.js *.json *.qml)
4250 add_custom_target(ubuntu_printing_app_main_qml_js_files ALL SOURCES ${MAIN_QML_JS_FILES})
4251 endif(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
4252
4253=== modified file 'ubuntu-printing-app/Main.qml'
4254--- ubuntu-printing-app/Main.qml 2016-12-13 12:37:45 +0000
4255+++ ubuntu-printing-app/Main.qml 2017-02-08 21:32:20 +0000
4256@@ -1,10 +1,31 @@
4257+/*
4258+ * Copyright 2016, 2017 Canonical Ltd.
4259+ *
4260+ * This file is part of ubuntu-printing-app.
4261+ *
4262+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
4263+ * it under the terms of the GNU General Public License as published by
4264+ * the Free Software Foundation; version 3.
4265+ *
4266+ * ubuntu-printing-app is distributed in the hope that it will be useful,
4267+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4268+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4269+ * GNU General Public License for more details.
4270+ *
4271+ * You should have received a copy of the GNU General Public License
4272+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4273+ *
4274+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
4275+ */
4276 import QtQuick 2.4
4277 import QtQuick.Layouts 1.1
4278
4279 import Ubuntu.Components 1.3
4280 import Ubuntu.Components.ListItems 1.3 as ListItems
4281-import Ubuntu.Content 0.1
4282-import Ubuntu_Printing_App 1.0
4283+import Ubuntu.Components.Popups 1.3
4284+import Ubuntu.Content 1.1
4285+import UbuntuPrintingApp 1.0
4286+import Ubuntu.Settings.Printers 0.1
4287
4288 import "components"
4289
4290@@ -18,295 +39,106 @@
4291 objectName: "mainView"
4292
4293 // Note! applicationName needs to match the "name" field of the click manifest
4294- applicationName: "ubuntu-printing-app.ahayzen"
4295-
4296- width: units.gu(40)
4297- height: units.gu(60)
4298-
4299- Connections {
4300- target: ContentHub
4301-
4302- onImportRequested: {
4303- console.debug("State:", transfer.state)
4304- console.debug("Transfer:", transfer)
4305- console.debug("Items:", transfer.items)
4306-
4307- for (var i=0; i < transfer.items.length; i++) {
4308- var item = transfer.items[i];
4309-
4310- document.url = item.url;
4311- console.debug("Item URL:", item.url);
4312- }
4313- }
4314- }
4315-
4316- Printer {
4317- id: printer
4318- name: PrinterInfo.defaultPrinterName
4319-
4320- // TODO: status ?
4321-
4322- onExportRequest: console.debug("Export requested!", filepath)
4323- }
4324+ applicationName: "ubuntu-printing-app"
4325+
4326+ width: units.gu(45)
4327+ height: units.gu(70)
4328
4329 Document {
4330 id: document
4331- }
4332-
4333- /*
4334- PrinterInfo.availablePrinterNames
4335-
4336- PrinterInfo.defaultName
4337-
4338- Printer {
4339- error: false
4340- errorString: ""
4341- name: PrinterInfo.defaultName
4342-
4343- colorMode: ColorModes.greyscale
4344- copies: 2
4345-
4346- print(Document document) // async
4347-
4348- status: {Null,Rendering,SentToPrinter,Error}
4349- progress: 0.6 // progress of print
4350- }
4351-
4352- Document {
4353- error: false
4354- errorString: ""
4355- url: "/tmp/my.pdf"
4356- }
4357-
4358- */
4359-
4360- Page {
4361- id: page
4362+
4363+ onError: {
4364+ var errorString;
4365+
4366+ switch (errorType) {
4367+ case Document.ErrorDocumentInvalid:
4368+ errorString = i18n.tr("Document is invalid");
4369+ break;
4370+ case Document.ErrorNotFound:
4371+ errorString = i18n.tr("Document not found");
4372+ break;
4373+ case Document.ErrorNotPdf:
4374+ errorString = i18n.tr("Not a PDF document");
4375+ break;
4376+ default:
4377+ errorString = i18n.tr("An unknown error occurred");
4378+ break;
4379+ }
4380+
4381+ // Empty the Url so user cannot print
4382+ url = "";
4383+
4384+ PopupUtils.open(
4385+ Qt.resolvedUrl("components/AlertDialog.qml"),
4386+ pageStack.currentPage,
4387+ {
4388+ "text": errorString,
4389+ "title": i18n.tr("Error"),
4390+ }
4391+ )
4392+ }
4393+ }
4394+
4395+ property PrintingHelper printing: PrintingHelper {}
4396+ property Page printPage: null
4397+
4398+ PageStack {
4399+ id: pageStack
4400 anchors {
4401 fill: parent
4402 }
4403- width: mainView.width
4404-
4405- header: PageHeader {
4406- id: pageHeader
4407- leadingActionBar {
4408- actions: [
4409- Action {
4410- iconName: "back"
4411-
4412- onTriggered: Qt.quit()
4413- }
4414- ]
4415- }
4416-
4417- title: printer.pdfMode ? i18n.tr("Page Setup") : i18n.tr("Printer Options")
4418- }
4419-
4420- ScrollView {
4421- anchors {
4422- bottom: printRow.top
4423- left: parent.left
4424- right: parent.right
4425- top: page.header.bottom
4426- }
4427-
4428- Item {
4429- height: columnLayout.height + units.gu(2)
4430- width: mainView.width - units.gu(2)
4431- x: units.gu(1)
4432- y: x
4433-
4434- ColumnLayout {
4435- id: columnLayout
4436- spacing: units.gu(1)
4437- width: parent.width
4438-
4439- Rectangle {
4440- anchors {
4441- left: parent.left
4442- right: parent.right
4443- }
4444- color: "#EEE"
4445- implicitHeight: units.gu(25)
4446-
4447- RowLayout {
4448- anchors.fill: parent
4449-
4450- Button {
4451- enabled: previewImage.pageNumber > 0
4452- Layout.preferredWidth: units.gu(4)
4453- color: "#000"
4454- text: "<"
4455-
4456- onClicked: previewImage.pageNumber--
4457- }
4458-
4459- Item {
4460- Layout.fillWidth: true
4461- Layout.preferredHeight: units.gu(25)
4462-
4463- Image {
4464- id: previewImage
4465- anchors {
4466- fill: parent
4467- }
4468-
4469- asynchronous: true
4470- source: document.url.toString() !== "" ? "image://poppler/" + pageNumber + "/" + printer.colorMode + "/" + document.url : ""
4471- sourceSize {
4472- height: units.gu(25)
4473- width: previewImage.width
4474- }
4475-
4476- property int pageNumber: 0
4477- }
4478-
4479- ActivityIndicator {
4480- anchors {
4481- centerIn: parent
4482- }
4483- running: previewImage.status == Image.Loading
4484- }
4485- }
4486-
4487- Button {
4488- color: "#000"
4489- enabled: previewImage.pageNumber < document.count - 1
4490- Layout.preferredWidth: units.gu(4)
4491- text: ">"
4492-
4493- onClicked: previewImage.pageNumber++
4494- }
4495- }
4496- }
4497-
4498-
4499- SelectorRow {
4500- model: PrinterInfo.availablePrinterNames
4501- selectedIndex: model.indexOf(printer.name)
4502- text: i18n.tr("Printer")
4503-
4504- onSelectedIndexChanged: {
4505- printer.pdfMode = selectedIndex === model.length - 1
4506- printer.name = model[selectedIndex]
4507- }
4508- }
4509-
4510- RowLayout {
4511- Label {
4512- Layout.preferredWidth: units.gu(10)
4513- text: i18n.tr("Copies")
4514- }
4515-
4516- TextField {
4517- enabled: !printer.pdfMode
4518- inputMethodHints: Qt.ImhDigitsOnly
4519- Layout.fillWidth: true
4520- Layout.preferredWidth: units.gu(5)
4521- text: printer.copies
4522- validator: IntValidator {
4523- bottom: 1
4524- top: 999
4525- }
4526-
4527- // TODO: acceptableInput is False show hint
4528-
4529- onTextChanged: {
4530- if (acceptableInput) {
4531- printer.copies = Number(text);
4532- }
4533- }
4534- }
4535- }
4536-
4537- RowLayout {
4538- Item {
4539- Layout.preferredWidth: units.gu(10)
4540- }
4541-
4542- MouseArea {
4543- enabled: checkbox.enabled
4544- Layout.fillWidth: true
4545- Layout.preferredHeight: units.gu(3)
4546- Layout.preferredWidth: units.gu(10)
4547-
4548- onClicked: checkbox.checked = !checkbox.checked
4549-
4550- Row {
4551- anchors {
4552- fill: parent
4553- }
4554- spacing: units.gu(1)
4555-
4556- CheckBox {
4557- id: checkbox
4558- anchors {
4559- verticalCenter: parent.verticalCenter
4560- }
4561- checked: printer.duplex
4562- enabled: document.count > 1 && printer.duplexSupported
4563-
4564- onCheckedChanged: printer.duplex = checked
4565- }
4566-
4567- Label {
4568- enabled: document.count > 1
4569- height: parent.height
4570- text: i18n.tr("Two-Sided")
4571- verticalAlignment: Text.AlignVCenter
4572- }
4573- }
4574-
4575- }
4576- }
4577-
4578- SelectorRow {
4579- enabled: !printer.pdfMode
4580- model: [i18n.tr("Black & White"), i18n.tr("Color")]
4581- selectedIndex: modelValue.indexOf(printer.colorMode)
4582- text: i18n.tr("Color")
4583-
4584- property var modelValue: [Printer.GrayScale, Printer.Color]
4585-
4586- onSelectedIndexChanged: printer.colorMode = modelValue[selectedIndex]
4587- }
4588-
4589- SelectorRow {
4590- enabled: !printer.pdfMode
4591- model: [i18n.tr("Draft"), i18n.tr("Normal"), i18n.tr("Best"), i18n.tr("Photo")]
4592- selectedIndex: modelValue.indexOf(printer.quality)
4593- text: i18n.tr("Quality")
4594-
4595- property var modelValue: [Printer.Draft, Printer.Normal, Printer.Best, Printer.Photo]
4596-
4597- onSelectedIndexChanged: printer.quality = modelValue[selectedIndex]
4598- }
4599- }
4600- }
4601- }
4602-
4603- PrintRow {
4604- id: printRow
4605- anchors {
4606- bottom: parent.bottom
4607- left: parent.left
4608- leftMargin: units.gu(1)
4609- right: parent.right
4610- rightMargin: units.gu(1)
4611- }
4612- pdfMode: printer.pdfMode
4613- sheets: document.count
4614-
4615- onCancel: Qt.quit()
4616- onConfirm: printer.print(document); // TODO: check document is valid raise error if not?
4617+ }
4618+
4619+ Arguments {
4620+ id: args
4621+ Argument {
4622+ name: "url"
4623+ help: i18n.tr("URL of PDF to print")
4624+ required: false
4625+ valueNames: ["url"]
4626+ }
4627+ }
4628+
4629+ Connections {
4630+ target: ContentHub
4631+
4632+ onImportRequested: {
4633+ // FIXME: Only uses the first item given over content-hub
4634+ // do we need to support multiple items in the future?
4635+ if (transfer.items.length > 0) {
4636+ document.url = transfer.items[0].url;
4637+ }
4638+ }
4639+ }
4640+
4641+ Connections {
4642+ target: printPage
4643+
4644+ onCancel: Qt.quit()
4645+ onConfirm: {
4646+ if (printing.pdfMode) {
4647+ pageStack.push(Qt.resolvedUrl("pages/ContentPeerPickerPage.qml"), {"url": url});
4648+ } else {
4649+ printing.printerJob.printFile(url);
4650+ Qt.quit();
4651+ }
4652 }
4653 }
4654
4655 Component.onCompleted: {
4656-// document.url = Qt.resolvedUrl("/home/andy/Workspace/Work/Canonical/dump/2016-11-17T12:00:08");
4657- document.url = Qt.resolvedUrl("/home/andrew/Downloads/UbuntuPhone.pdf");
4658-// document.url = Qt.resolvedUrl("/home/andrew/Documents/test.pdf");
4659- console.debug("Printers:", PrinterInfo.availablePrinterNames);
4660+ printing.printerJob.landscape = document.orientation === Document.Landscape;
4661+ printing.printerJob.title = document.title || document.url.toString().split("/").pop();
4662+ printPage = pageStack.push(
4663+ Qt.resolvedUrl("pages/PrintPage.qml"),
4664+ {
4665+ "currentDocument": document,
4666+ "printing": printing,
4667+ }
4668+ );
4669+
4670+ if (args.values.url) {
4671+ document.url = Qt.resolvedUrl(args.values.url);
4672+ }
4673 }
4674 }
4675
4676
4677=== added file 'ubuntu-printing-app/components/AlertDialog.qml'
4678--- ubuntu-printing-app/components/AlertDialog.qml 1970-01-01 00:00:00 +0000
4679+++ ubuntu-printing-app/components/AlertDialog.qml 2017-02-08 21:32:20 +0000
4680@@ -0,0 +1,32 @@
4681+/*
4682+ * Copyright 2017 Canonical Ltd.
4683+ *
4684+ * This file is part of ubuntu-printing-app.
4685+ *
4686+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
4687+ * it under the terms of the GNU General Public License as published by
4688+ * the Free Software Foundation; version 3.
4689+ *
4690+ * ubuntu-printing-app is distributed in the hope that it will be useful,
4691+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4692+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4693+ * GNU General Public License for more details.
4694+ *
4695+ * You should have received a copy of the GNU General Public License
4696+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4697+ *
4698+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
4699+ */
4700+import QtQuick 2.4
4701+import Ubuntu.Components 1.3
4702+import Ubuntu.Components.Popups 1.3
4703+
4704+Dialog {
4705+ id: dialog
4706+
4707+ Button {
4708+ text: i18n.tr("OK")
4709+
4710+ onClicked: PopupUtils.close(dialog)
4711+ }
4712+}
4713
4714=== modified file 'ubuntu-printing-app/components/CMakeLists.txt'
4715--- ubuntu-printing-app/components/CMakeLists.txt 2016-12-13 23:08:52 +0000
4716+++ ubuntu-printing-app/components/CMakeLists.txt 2017-02-08 21:32:20 +0000
4717@@ -1,7 +1,12 @@
4718 set(COMPONENT_QML_JS_FILES
4719- ExpandableListItem.qml
4720+ AlertDialog.qml
4721+ CheckBoxRow.qml
4722+ LabelRow.qml
4723+ PreviewRow.qml
4724 PrintRow.qml
4725+ PrintingHelper.qml
4726 SelectorRow.qml
4727+ TextFieldRow.qml
4728 )
4729
4730 install(FILES ${COMPONENT_QML_JS_FILES} DESTINATION ${UBUNTU_PRINTING_APP_DATA_DIR}/components)
4731
4732=== added file 'ubuntu-printing-app/components/CheckBoxRow.qml'
4733--- ubuntu-printing-app/components/CheckBoxRow.qml 1970-01-01 00:00:00 +0000
4734+++ ubuntu-printing-app/components/CheckBoxRow.qml 2017-02-08 21:32:20 +0000
4735@@ -0,0 +1,76 @@
4736+/*
4737+ * Copyright 2016 Canonical Ltd.
4738+ *
4739+ * This file is part of ubuntu-printing-app.
4740+ *
4741+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
4742+ * it under the terms of the GNU General Public License as published by
4743+ * the Free Software Foundation; version 3.
4744+ *
4745+ * ubuntu-printing-app is distributed in the hope that it will be useful,
4746+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4747+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4748+ * GNU General Public License for more details.
4749+ *
4750+ * You should have received a copy of the GNU General Public License
4751+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4752+ *
4753+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
4754+ */
4755+import QtQuick 2.4
4756+import QtQuick.Layouts 1.1
4757+
4758+import Ubuntu.Components 1.3
4759+
4760+RowLayout {
4761+ anchors {
4762+ left: parent.left
4763+ leftMargin: units.gu(2)
4764+ right: parent.right
4765+ rightMargin: units.gu(2)
4766+ }
4767+ Layout.maximumWidth: width
4768+
4769+ property alias checked: checkbox.checked
4770+ property alias checkboxText: checkboxLabel.text
4771+ property alias enabled: checkbox.enabled
4772+ property alias text: label.text
4773+
4774+ Label {
4775+ id: label
4776+ Layout.preferredWidth: units.gu(10)
4777+ objectName: "label"
4778+ }
4779+
4780+ MouseArea {
4781+ enabled: checkbox.enabled
4782+ Layout.fillWidth: true
4783+ Layout.preferredHeight: units.gu(3)
4784+ Layout.preferredWidth: units.gu(10)
4785+
4786+ onClicked: checkbox.checked = !checkbox.checked
4787+
4788+ Row {
4789+ anchors {
4790+ fill: parent
4791+ }
4792+ spacing: units.gu(1)
4793+
4794+ CheckBox {
4795+ id: checkbox
4796+ anchors {
4797+ verticalCenter: parent.verticalCenter
4798+ }
4799+ objectName: "checkbox"
4800+ }
4801+
4802+ Label {
4803+ id: checkboxLabel
4804+ enabled: checkbox.enabled
4805+ height: parent.height
4806+ objectName: "checkboxLabel"
4807+ verticalAlignment: Text.AlignVCenter
4808+ }
4809+ }
4810+ }
4811+}
4812
4813=== removed file 'ubuntu-printing-app/components/ExpandableListItem.qml'
4814--- ubuntu-printing-app/components/ExpandableListItem.qml 2016-11-25 16:47:10 +0000
4815+++ ubuntu-printing-app/components/ExpandableListItem.qml 1970-01-01 00:00:00 +0000
4816@@ -1,82 +0,0 @@
4817-/*
4818- * Copyright (C) 2015-2016 Canonical Ltd
4819- *
4820- * This file is part of Ubuntu Weather App
4821- *
4822- * Ubuntu Weather App is free software: you can redistribute it and/or modify
4823- * it under the terms of the GNU General Public License version 3 as
4824- * published by the Free Software Foundation.
4825- *
4826- * Ubuntu Weather App is distributed in the hope that it will be useful,
4827- * but WITHOUT ANY WARRANTY; without even the implied warranty of
4828- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4829- * GNU General Public License for more details.
4830- *
4831- * You should have received a copy of the GNU General Public License
4832- * along with this program. If not, see <http://www.gnu.org/licenses/>.
4833- */
4834-
4835-import QtQuick 2.4
4836-import Ubuntu.Components 1.3
4837-
4838-/*
4839- Component which extends the SDK Expandable list item and provides a easy
4840- to use component where the title, subtitle and a listview can be displayed. It
4841- matches the design specification provided for clock.
4842-*/
4843-
4844-ListItem {
4845- id: expandableListItem
4846-
4847- // Public APIs
4848- property ListModel model
4849- property Component delegate
4850- property alias title: expandableHeader.title
4851- property alias subText: expandableHeader.subtitle
4852- property alias listViewHeight: expandableList.height
4853-
4854- highlightColor: "Transparent"
4855- height: expandableHeader.height + divider.height
4856- expansion.height: contentColumn.height
4857- onClicked: expansion.expanded = !expansion.expanded
4858-
4859- Column {
4860- id: contentColumn
4861-
4862- anchors {
4863- left: parent.left
4864- right: parent.right
4865- }
4866-
4867- ListItem {
4868- height: expandableHeader.height + divider.height
4869- ListItemLayout {
4870- id: expandableHeader
4871-
4872- Icon {
4873- id: arrow
4874-
4875- width: units.gu(2)
4876- height: width
4877- SlotsLayout.position: SlotsLayout.Trailing
4878- SlotsLayout.overrideVerticalPositioning: true
4879- anchors.verticalCenter: parent.verticalCenter
4880- name: "go-down"
4881- rotation: expandableListItem.expansion.expanded ? 180 : 0
4882-
4883- Behavior on rotation {
4884- UbuntuNumberAnimation {}
4885- }
4886- }
4887- }
4888- }
4889-
4890- ListView {
4891- id: expandableList
4892- width: parent.width
4893- interactive: false
4894- model: expandableListItem.model
4895- delegate: expandableListItem.delegate
4896- }
4897- }
4898-}
4899
4900=== added file 'ubuntu-printing-app/components/LabelRow.qml'
4901--- ubuntu-printing-app/components/LabelRow.qml 1970-01-01 00:00:00 +0000
4902+++ ubuntu-printing-app/components/LabelRow.qml 2017-02-08 21:32:20 +0000
4903@@ -0,0 +1,52 @@
4904+/*
4905+ * Copyright 2016 Canonical Ltd.
4906+ *
4907+ * This file is part of ubuntu-printing-app.
4908+ *
4909+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
4910+ * it under the terms of the GNU General Public License as published by
4911+ * the Free Software Foundation; version 3.
4912+ *
4913+ * ubuntu-printing-app is distributed in the hope that it will be useful,
4914+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4915+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4916+ * GNU General Public License for more details.
4917+ *
4918+ * You should have received a copy of the GNU General Public License
4919+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4920+ *
4921+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
4922+ */
4923+import QtQuick 2.4
4924+import QtQuick.Layouts 1.1
4925+
4926+import Ubuntu.Components 1.3
4927+
4928+RowLayout {
4929+ anchors {
4930+ left: parent.left
4931+ leftMargin: units.gu(2)
4932+ right: parent.right
4933+ rightMargin: units.gu(2)
4934+ }
4935+ Layout.maximumWidth: width
4936+
4937+ property alias enabled: secondaryLabel.enabled
4938+ property alias primaryText: primaryLabel.text
4939+ property alias secondaryText: secondaryLabel.text
4940+
4941+ Label {
4942+ id: primaryLabel
4943+ Layout.preferredWidth: units.gu(10)
4944+ objectName: "primary"
4945+ }
4946+
4947+ Label {
4948+ id: secondaryLabel
4949+ Layout.fillWidth: true
4950+ Layout.preferredHeight: units.gu(3)
4951+ Layout.preferredWidth: units.gu(10)
4952+ objectName: "secondary"
4953+ verticalAlignment: Text.AlignVCenter
4954+ }
4955+}
4956
4957=== added file 'ubuntu-printing-app/components/PreviewRow.qml'
4958--- ubuntu-printing-app/components/PreviewRow.qml 1970-01-01 00:00:00 +0000
4959+++ ubuntu-printing-app/components/PreviewRow.qml 2017-02-08 21:32:20 +0000
4960@@ -0,0 +1,142 @@
4961+/*
4962+ * Copyright 2016 Canonical Ltd.
4963+ *
4964+ * This file is part of ubuntu-printing-app.
4965+ *
4966+ * ubuntu-printing-app is free software; you can redistribute it and/or modify
4967+ * it under the terms of the GNU General Public License as published by
4968+ * the Free Software Foundation; version 3.
4969+ *
4970+ * ubuntu-printing-app is distributed in the hope that it will be useful,
4971+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4972+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4973+ * GNU General Public License for more details.
4974+ *
4975+ * You should have received a copy of the GNU General Public License
4976+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4977+ *
4978+ * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
4979+ */
4980+import QtQuick 2.4
4981+import Ubuntu.Components 1.3
4982+
4983+import UbuntuPrintingApp 1.0
4984+import Ubuntu.Settings.Printers 0.1
4985+
4986+Rectangle {
4987+ id: previewRow
4988+ anchors {
4989+ left: parent.left
4990+ right: parent.right
4991+ }
4992+ // Use foreground as this element is ontop of the background
4993+ color: theme.palette.normal.foreground
4994+ // Height is smallest of
4995+ // - calc'd height using aspect and width of image
4996+ // - 2/3 height of the view
4997+ implicitHeight: Math.min((view.width - units.gu(10)) / pageHelper.aspect, view.height / 1.5)
4998+
4999+ property Document document
5000+ property var printerJob
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: