Merge lp:~ahayzen/ubuntu-printing-app/page-range-validate-and-count into lp:ubuntu-printing-app

Proposed by Andrew Hayzen
Status: Approved
Approved by: Michael Sheldon
Approved revision: 73
Proposed branch: lp:~ahayzen/ubuntu-printing-app/page-range-validate-and-count
Merge into: lp:ubuntu-printing-app
Diff against target: 918 lines (+666/-36)
11 files modified
po/ubuntu-printing-app.pot (+25/-9)
ubuntu-printing-app/backend/CMakeLists.txt (+2/-1)
ubuntu-printing-app/backend/UbuntuPrintingApp/backend.cpp (+2/-0)
ubuntu-printing-app/backend/UbuntuPrintingApp/pagerangevalidator.cpp (+192/-0)
ubuntu-printing-app/backend/UbuntuPrintingApp/pagerangevalidator.h (+75/-0)
ubuntu-printing-app/components/LabelRow.qml (+2/-0)
ubuntu-printing-app/pages/PrintPage.qml (+53/-21)
ubuntu-printing-app/tests/qmltests/tst_LabelRow.qml (+8/-0)
ubuntu-printing-app/tests/qmltests/tst_PrintPage.qml (+152/-5)
ubuntu-printing-app/tests/unittests/backend/CMakeLists.txt (+4/-0)
ubuntu-printing-app/tests/unittests/backend/tst_pagerangevalidator.cpp (+151/-0)
To merge this branch: bzr merge lp:~ahayzen/ubuntu-printing-app/page-range-validate-and-count
Reviewer Review Type Date Requested Status
Michael Sheldon (community) Approve
Review via email: mp+321547@code.launchpad.net

Commit message

* Add validation to copies and page range fields with tests

Description of the change

* Add validation to copies and page range fields with tests

To post a comment you must log in.
Revision history for this message
Michael Sheldon (michael-sheldon) wrote :

Page ranges shouldn't be sorted, as the user may have a valid reason for wanting to specify their pages in a different order (e.g. "1, 5, 3" should print in that order), this is the current behaviour for existing print dialogs.

Also it'd be nice to support reversed ranges, so "5-1" would print 5, 4, 3, 2, 1 in that order. Or a more complicated example could be "3-1, 5, 4" should print 3, 2, 1, 5, 4.

review: Needs Fixing
Revision history for this message
Andrew Hayzen (ahayzen) wrote :

As discussed, cups doesn't seem to support overlapping ranges or descending [0]. So for now we are going to do de-duplication and ascending order. It seems that other apps such as documentviewer (gtk), must rendering an intermediate PDF which has the page order how they want.

0 - https://www.cups.org/doc/options.html#PAGERANGES

Revision history for this message
Andrew Hayzen (ahayzen) wrote :

Reported bug 1680048 for advanced page ranges. And now setting Qt.ImhPreferNumbers for the page range field.

Revision history for this message
Michael Sheldon (michael-sheldon) wrote :

Looks good :)

review: Approve

Unmerged revisions

73. By Andrew Hayzen

* Set Qt.ImhPreferNumbers for page-ranges text field

72. By Andrew Hayzen

* Remove unneeded TODO

71. By Andrew Hayzen

* Ensure NoError state is always set
* Update naming of error for 5-3

70. By Andrew Hayzen

* Rebase onto lp:ubuntu-printing-app

69. By Andrew Hayzen

* Add validation to copies field with tests

68. By Andrew Hayzen

* Add page range validation and counting with tests

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'po/ubuntu-printing-app.pot'
--- po/ubuntu-printing-app.pot 2017-03-21 17:57:19 +0000
+++ po/ubuntu-printing-app.pot 2017-04-05 12:09:01 +0000
@@ -8,7 +8,7 @@
8msgstr ""8msgstr ""
9"Project-Id-Version: PACKAGE VERSION\n"9"Project-Id-Version: PACKAGE VERSION\n"
10"Report-Msgid-Bugs-To: \n"10"Report-Msgid-Bugs-To: \n"
11"POT-Creation-Date: 2017-03-21 17:56+0000\n"11"POT-Creation-Date: 2017-04-05 12:51+0100\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"14"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -185,39 +185,55 @@
185msgid "Copies"185msgid "Copies"
186msgstr ""186msgstr ""
187187
188#: ../ubuntu-printing-app/pages/PrintPage.qml:131188#: ../ubuntu-printing-app/pages/PrintPage.qml:130
189msgid "All"189msgid "All"
190msgstr ""190msgstr ""
191191
192#: ../ubuntu-printing-app/pages/PrintPage.qml:131192#: ../ubuntu-printing-app/pages/PrintPage.qml:130
193msgid "Range"193msgid "Range"
194msgstr ""194msgstr ""
195195
196#: ../ubuntu-printing-app/pages/PrintPage.qml:135196#: ../ubuntu-printing-app/pages/PrintPage.qml:134
197msgid "Pages"197msgid "Pages"
198msgstr ""198msgstr ""
199199
200#: ../ubuntu-printing-app/pages/PrintPage.qml:177200#: ../ubuntu-printing-app/pages/PrintPage.qml:175
201msgid "eg 1-3,8"201msgid "eg 1-3,8"
202msgstr ""202msgstr ""
203203
204#: ../ubuntu-printing-app/pages/PrintPage.qml:186204#: ../ubuntu-printing-app/pages/PrintPage.qml:186
205msgid "No number given in range"
206msgstr ""
207
208#: ../ubuntu-printing-app/pages/PrintPage.qml:189
209msgid "Page is less than one"
210msgstr ""
211
212#: ../ubuntu-printing-app/pages/PrintPage.qml:192
213msgid "Page is higher than document page count"
214msgstr ""
215
216#: ../ubuntu-printing-app/pages/PrintPage.qml:195
217msgid "Second page cannot be lower than first"
218msgstr ""
219
220#: ../ubuntu-printing-app/pages/PrintPage.qml:211
205msgid "Two-sided"221msgid "Two-sided"
206msgstr ""222msgstr ""
207223
208#: ../ubuntu-printing-app/pages/PrintPage.qml:207224#: ../ubuntu-printing-app/pages/PrintPage.qml:232
209msgid "Color"225msgid "Color"
210msgstr ""226msgstr ""
211227
212#: ../ubuntu-printing-app/pages/PrintPage.qml:228228#: ../ubuntu-printing-app/pages/PrintPage.qml:253
213msgid "Quality"229msgid "Quality"
214msgstr ""230msgstr ""
215231
216#: ../ubuntu-printing-app/pages/PrintPage.qml:246232#: ../ubuntu-printing-app/pages/PrintPage.qml:271
217msgid "Collate"233msgid "Collate"
218msgstr ""234msgstr ""
219235
220#: ../ubuntu-printing-app/pages/PrintPage.qml:266236#: ../ubuntu-printing-app/pages/PrintPage.qml:291
221msgid "Reverse"237msgid "Reverse"
222msgstr ""238msgstr ""
223239
224240
=== modified file 'ubuntu-printing-app/backend/CMakeLists.txt'
--- ubuntu-printing-app/backend/CMakeLists.txt 2017-03-07 15:01:56 +0000
+++ ubuntu-printing-app/backend/CMakeLists.txt 2017-04-05 12:09:01 +0000
@@ -9,8 +9,9 @@
9 UbuntuPrintingAppSRC9 UbuntuPrintingAppSRC
10 UbuntuPrintingApp/backend.cpp10 UbuntuPrintingApp/backend.cpp
11 UbuntuPrintingApp/document.cpp11 UbuntuPrintingApp/document.cpp
12 UbuntuPrintingApp/pagehelper.cpp
13 UbuntuPrintingApp/pagerangevalidator.cpp
12 UbuntuPrintingApp/popplerimageprovider.cpp14 UbuntuPrintingApp/popplerimageprovider.cpp
13 UbuntuPrintingApp/pagehelper.cpp
14)15)
1516
16add_library(${LIBNAME} SHARED ${UbuntuPrintingAppSRC})17add_library(${LIBNAME} SHARED ${UbuntuPrintingAppSRC})
1718
=== modified file 'ubuntu-printing-app/backend/UbuntuPrintingApp/backend.cpp'
--- ubuntu-printing-app/backend/UbuntuPrintingApp/backend.cpp 2017-01-30 15:19:57 +0000
+++ ubuntu-printing-app/backend/UbuntuPrintingApp/backend.cpp 2017-04-05 12:09:01 +0000
@@ -23,6 +23,7 @@
2323
24#include "document.h"24#include "document.h"
25#include "pagehelper.h"25#include "pagehelper.h"
26#include "pagerangevalidator.h"
26#include "popplerimageprovider.h"27#include "popplerimageprovider.h"
2728
28void BackendPlugin::registerTypes(const char *uri)29void BackendPlugin::registerTypes(const char *uri)
@@ -31,6 +32,7 @@
3132
32 qmlRegisterType<Document>(uri, 1, 0, "Document");33 qmlRegisterType<Document>(uri, 1, 0, "Document");
33 qmlRegisterType<PageHelper>(uri, 1, 0, "PageHelper");34 qmlRegisterType<PageHelper>(uri, 1, 0, "PageHelper");
35 qmlRegisterType<PageRangeValidator>(uri, 1, 0, "PageRangeValidator");
34}36}
3537
36void BackendPlugin::initializeEngine(QQmlEngine *engine, const char *uri)38void BackendPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
3739
=== added file 'ubuntu-printing-app/backend/UbuntuPrintingApp/pagerangevalidator.cpp'
--- ubuntu-printing-app/backend/UbuntuPrintingApp/pagerangevalidator.cpp 1970-01-01 00:00:00 +0000
+++ ubuntu-printing-app/backend/UbuntuPrintingApp/pagerangevalidator.cpp 2017-04-05 12:09:01 +0000
@@ -0,0 +1,192 @@
1/*
2 * Copyright 2017 Canonical Ltd.
3 *
4 * This file is part of ubuntu-printing-app.
5 *
6 * ubuntu-printing-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * ubuntu-printing-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
19 */
20
21#include "pagerangevalidator.h"
22
23#include <QtCore/QRegularExpressionMatch>
24#include <QtCore/QList>
25
26PageRangeValidator::PageRangeValidator(QObject *parent)
27 : QValidator(parent)
28 , m_count(0)
29 , m_document_count(0)
30 , m_error(PageRangeError::NoError)
31 , m_pages({})
32 , m_validate_re(QStringLiteral("^(\\d+)?[-]?(\\d+)?([,](\\d+)?[-]?(\\d+)?)*$"))
33 , m_validate_values_re(QStringLiteral("^(\\d*)?[-]?(\\d*)?$"))
34{
35
36}
37
38int PageRangeValidator::count() const
39{
40 return m_count;
41}
42
43int PageRangeValidator::documentCount() const
44{
45 return m_document_count;
46}
47
48PageRangeValidator::PageRangeError PageRangeValidator::error() const
49{
50 return m_error;
51}
52
53QString PageRangeValidator::pages() const
54{
55 // Convert the pages to a list of comma's for QML and cups
56 QStringList list;
57
58 // Get a list and sort while still int so that 10 > 2
59 QList<int> pages = m_pages.toList();
60 qSort(pages);
61
62 Q_FOREACH(int page, pages) {
63 list << QString::number(page);
64 }
65
66 return list.join(",");
67}
68
69void PageRangeValidator::setCount(const int count)
70{
71 if (m_count != count) {
72 m_count = count;
73
74 Q_EMIT countChanged(m_count);
75 }
76}
77
78void PageRangeValidator::setDocumentCount(const int documentCount)
79{
80 if (m_document_count != documentCount) {
81 m_document_count = documentCount;
82
83 Q_EMIT documentCountChanged(m_document_count);
84 }
85}
86
87void PageRangeValidator::setError(const PageRangeValidator::PageRangeError error)
88{
89 if (m_error != error) {
90 m_error = error;
91
92 Q_EMIT errorChanged(m_error);
93 }
94}
95
96void PageRangeValidator::setPages(const QSet<int> pages)
97{
98 if (m_pages != pages) {
99 m_pages = pages;
100
101 setCount(m_pages.count());
102
103 Q_EMIT pagesChanged(this->pages());
104 }
105}
106
107QValidator::State PageRangeValidator::validate(QString &input, int &pos) const
108{
109 Q_UNUSED(pos);
110
111 // TODO: maybe use partial match for 1-3-5?
112 // QRegularExpression::PartialPreferCompleteMatch
113 // QValidator::State::Intermediate
114 // however then it allows 1,------
115 QRegularExpressionMatch match = m_validate_re.match(input, 0);
116
117 if (match.hasMatch()) {
118 return QValidator::State::Acceptable;
119 } else {
120 return QValidator::State::Invalid;
121 }
122}
123
124bool PageRangeValidator::validateValues(QString input)
125{
126 bool valid = true;
127
128 // If the given value is empty then set the whole range
129 if (input.isEmpty()) {
130 setPages({});
131 setCount(documentCount());
132
133 return valid;
134 }
135
136 QSet<int> pages;
137 setError(PageRangeError::NoError);
138
139 Q_FOREACH(QString part, input.split(",")) {
140 QRegularExpressionMatch matches = m_validate_values_re.match(part);
141
142 QString low = matches.captured(1);
143 QString high = matches.captured(2);
144
145 if (low.isEmpty() && high.isEmpty()) {
146 setError(PageRangeError::NoPageInRange);
147 valid = false;
148 break;
149 } else if (high.isEmpty()) {
150 if (part.contains("-")) {
151 // 1- add the range from the lower until the document count
152 high = QString::number(documentCount());
153 } else {
154 // 1 Add the given page
155 high = low;
156 }
157 } else if (low.isEmpty()) {
158 // -3 add the range up to the higher number
159 low = QString::number(1);
160 } else {
161 // high and low set, we don't need todo anything
162 }
163
164 // Convert to ints
165 int lower = low.toInt();
166 int higher = high.toInt();
167
168 // Validate the numbers
169 if (lower < 1 || higher < 1) {
170 setError(PageRangeError::PageLessThanOne);
171 valid = false;
172 break;
173 } else if (lower > documentCount() || higher > documentCount()) {
174 setError(PageRangeError::PageHigherThanDocument);
175 valid = false;
176 break;
177 } else if (lower > higher) {
178 setError(PageRangeError::PageLowGreaterThanHigh);
179 valid = false;
180 break;
181 } else {
182 // Valid so lets push given pages numbers
183 for (int i=lower; i <= higher; i++) {
184 pages.insert(i);
185 }
186 }
187 }
188
189 setPages(pages);
190
191 return valid;
192}
0193
=== added file 'ubuntu-printing-app/backend/UbuntuPrintingApp/pagerangevalidator.h'
--- ubuntu-printing-app/backend/UbuntuPrintingApp/pagerangevalidator.h 1970-01-01 00:00:00 +0000
+++ ubuntu-printing-app/backend/UbuntuPrintingApp/pagerangevalidator.h 2017-04-05 12:09:01 +0000
@@ -0,0 +1,75 @@
1/*
2 * Copyright 2017 Canonical Ltd.
3 *
4 * This file is part of ubuntu-printing-app.
5 *
6 * ubuntu-printing-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * ubuntu-printing-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
19 */
20#ifndef PAGERANGEVALIDATOR_H
21#define PAGERANGEVALIDATOR_H
22
23#include <QtCore/QRegularExpression>
24#include <QtCore/QSet>
25#include <QtGui/QValidator>
26
27class PageRangeValidator : public QValidator
28{
29 Q_OBJECT
30
31 Q_PROPERTY(int count READ count NOTIFY countChanged)
32 Q_PROPERTY(int documentCount READ documentCount WRITE setDocumentCount NOTIFY documentCountChanged)
33 Q_PROPERTY(PageRangeError error READ error NOTIFY errorChanged)
34 Q_PROPERTY(QString pages READ pages NOTIFY pagesChanged)
35public:
36 PageRangeValidator(QObject *parent=Q_NULLPTR);
37
38 enum PageRangeError {
39 NoError,
40 NoPageInRange,
41 PageLessThanOne,
42 PageHigherThanDocument,
43 PageLowGreaterThanHigh,
44 };
45 Q_ENUM(PageRangeError)
46
47 int count() const;
48 int documentCount() const;
49 PageRangeError error() const;
50 QString pages() const;
51 virtual QValidator::State validate(QString &input, int &pos) const override;
52
53 Q_INVOKABLE bool validateValues(QString input);
54Q_SIGNALS:
55 void countChanged(int count);
56 void documentCountChanged(int documentCount);
57 void errorChanged(PageRangeError error);
58 void pagesChanged(QString pages);
59public Q_SLOTS:
60 void setDocumentCount(const int documentCount);
61private Q_SLOTS:
62 void setCount(const int count);
63 void setPages(const QSet<int> pages);
64 void setError(const PageRangeError error);
65private:
66 int m_count;
67 int m_document_count;
68 PageRangeError m_error;
69 QSet<int> m_pages;
70 QRegularExpression m_validate_re;
71 QRegularExpression m_validate_values_re;
72};
73
74
75#endif // PAGERANGEVALIDATOR_H
076
=== modified file 'ubuntu-printing-app/components/LabelRow.qml'
--- ubuntu-printing-app/components/LabelRow.qml 2017-03-07 13:46:02 +0000
+++ ubuntu-printing-app/components/LabelRow.qml 2017-04-05 12:09:01 +0000
@@ -26,6 +26,7 @@
26 property alias enabled: secondaryLabel.enabled26 property alias enabled: secondaryLabel.enabled
27 property alias primaryText: primaryLabel.text27 property alias primaryText: primaryLabel.text
28 property alias secondaryText: secondaryLabel.text28 property alias secondaryText: secondaryLabel.text
29 property alias secondaryColor: secondaryLabel.color
2930
30 Label {31 Label {
31 id: primaryLabel32 id: primaryLabel
@@ -40,5 +41,6 @@
40 Layout.preferredWidth: units.gu(10)41 Layout.preferredWidth: units.gu(10)
41 objectName: "secondary"42 objectName: "secondary"
42 verticalAlignment: Text.AlignVCenter43 verticalAlignment: Text.AlignVCenter
44 wrapMode: Text.WrapAtWordBoundaryOrAnywhere
43 }45 }
44}46}
4547
=== modified file 'ubuntu-printing-app/pages/PrintPage.qml'
--- ubuntu-printing-app/pages/PrintPage.qml 2017-03-21 18:00:19 +0000
+++ ubuntu-printing-app/pages/PrintPage.qml 2017-04-05 12:09:01 +0000
@@ -105,9 +105,8 @@
105 inputMethodHints: Qt.ImhDigitsOnly105 inputMethodHints: Qt.ImhDigitsOnly
106 objectName: "copiesTextField"106 objectName: "copiesTextField"
107 text: i18n.tr("Copies")107 text: i18n.tr("Copies")
108 validator: IntValidator {108 validator: RegExpValidator {
109 bottom: 1109 regExp: /^[1-9](\d)*$/
110 top: 999
111 }110 }
112 value: printing.printerJob.copies111 value: printing.printerJob.copies
113112
@@ -151,23 +150,23 @@
151 TextFieldRow {150 TextFieldRow {
152 id: pageRangeTextField151 id: pageRangeTextField
153 enabled: printing.isLoaded && !printing.pdfMode152 enabled: printing.isLoaded && !printing.pdfMode
153 inputMethodHints: Qt.ImhPreferNumbers
154 objectName: "pageRangeTextField"154 objectName: "pageRangeTextField"
155 validator: RegExpValidator {155 validator: PageRangeValidator {
156// regExp: "" // TODO: validate to only 0-9||9-0||0 ,156 documentCount: document.count
157
158 // validate() is const, so bind a secondary validateValues
159 // which checks the values in the range are valid
160 // and sets the count/pages
161 readonly property bool validValues: validateValues(pageRangeTextField.value)
157 }162 }
158 visible: pageRangeSelector.selectedValue === PrinterEnum.PageRange163 visible: pageRangeSelector.selectedValue === PrinterEnum.PageRange
159164
160 onValueChanged: {
161 if (printing.printerJob.printRange !== value) {
162 printing.printerJob.printRange = value
163 }
164 }
165
166 Binding {165 Binding {
167 target: pageRangeTextField166 target: printing.printerJob
168 property: "value"167 property: "printRange"
169 when: printing.printerJob && pageRangeTextField.enabled168 when: printing.printerJob && pageRangeTextField.enabled && pageRangeTextField.validator.validValues
170 value: printing.printerJob.printRange169 value: pageRangeTextField.validator.pages
171 }170 }
172 }171 }
173172
@@ -178,6 +177,33 @@
178 visible: pageRangeSelector.selectedValue === PrinterEnum.PageRange177 visible: pageRangeSelector.selectedValue === PrinterEnum.PageRange
179 }178 }
180179
180 LabelRow {
181 enabled: printing.isLoaded && !printing.pdfMode
182 objectName: "pageRangeErrorStrLabel"
183 secondaryColor: theme.palette.normal.negative
184 secondaryText: {
185 switch (pageRangeTextField.validator.error) {
186 case PageRangeValidator.NoPageInRange:
187 i18n.tr("No number given in range")
188 break;
189 case PageRangeValidator.PageLessThanOne:
190 i18n.tr("Page is less than one")
191 break;
192 case PageRangeValidator.PageHigherThanDocument:
193 i18n.tr("Page is higher than document page count")
194 break;
195 case PageRangeValidator.PageLowGreaterThanHigh:
196 i18n.tr("Second page cannot be lower than first")
197 break;
198 default:
199 case PageRangeValidator.NoError:
200 ""
201 break;
202 }
203 }
204 visible: pageRangeSelector.selectedValue === PrinterEnum.PageRange && !pageRangeTextField.validator.validValues
205 }
206
181 SelectorRow {207 SelectorRow {
182 id: duplexSelector208 id: duplexSelector
183 enabled: printing.isEditable && currentDocument.count > 1 && printing.printer.supportedDuplexModes.length > 1209 enabled: printing.isEditable && currentDocument.count > 1 && printing.printer.supportedDuplexModes.length > 1
@@ -297,16 +323,22 @@
297 right: parent.right323 right: parent.right
298 rightMargin: units.gu(1)324 rightMargin: units.gu(1)
299 }325 }
300 canPrint: printing.isLoaded326 canPrint: {
327 if (printing.pdfMode) {
328 printing.isLoaded
329 } else if (printing.printerJob.printRangeMode === PrinterEnum.PageRange) {
330 // If the page range is set, then check it is valid
331 printing.isLoaded && copiesSelector.acceptableInput && pageRangeTextField.validator.validValues
332 } else {
333 printing.isLoaded && copiesSelector.acceptableInput
334 }
335 }
301 objectName: "printRow"336 objectName: "printRow"
302 pdfMode: printing.pdfMode337 pdfMode: printing.pdfMode
303 // TODO: This should count the range not all pages
304 // roundUp((pageCount * copies) / duplex)
305 sheets: {338 sheets: {
306 // If range is selected and a value exists, then set the sheets to zero339 // If the page range is set then use it
307 // for now. Which results in not showing the number sheets
308 if (printing.printerJob.printRangeMode === PrinterEnum.PageRange && printing.printerJob.printRange.length > 0) {340 if (printing.printerJob.printRangeMode === PrinterEnum.PageRange && printing.printerJob.printRange.length > 0) {
309 0341 Math.ceil((pageRangeTextField.validator.count * printing.printerJob.copies) / (printing.printerJob.isTwoSided ? 2 : 1))
310 } else {342 } else {
311 Math.ceil((document.count * printing.printerJob.copies) / (printing.printerJob.isTwoSided ? 2 : 1))343 Math.ceil((document.count * printing.printerJob.copies) / (printing.printerJob.isTwoSided ? 2 : 1))
312 }344 }
313345
=== modified file 'ubuntu-printing-app/tests/qmltests/tst_LabelRow.qml'
--- ubuntu-printing-app/tests/qmltests/tst_LabelRow.qml 2017-03-17 12:34:49 +0000
+++ ubuntu-printing-app/tests/qmltests/tst_LabelRow.qml 2017-04-05 12:09:01 +0000
@@ -36,11 +36,13 @@
3636
37 readonly property bool dataEnabled: true37 readonly property bool dataEnabled: true
38 readonly property string dataPrimaryText: "Primary"38 readonly property string dataPrimaryText: "Primary"
39 readonly property string dataSecondaryColor: "#ff0000"
39 readonly property string dataSecondaryText: "Secondary"40 readonly property string dataSecondaryText: "Secondary"
4041
41 function init() {42 function init() {
42 labelRow.enabled = dataEnabled;43 labelRow.enabled = dataEnabled;
43 labelRow.primaryText = dataPrimaryText;44 labelRow.primaryText = dataPrimaryText;
45 labelRow.secondaryColor = dataSecondaryColor;
44 labelRow.secondaryText = dataSecondaryText;46 labelRow.secondaryText = dataSecondaryText;
4547
46 waitForRendering(labelRow);48 waitForRendering(labelRow);
@@ -69,5 +71,11 @@
69 var secondary = findChild(labelRow, "secondary");71 var secondary = findChild(labelRow, "secondary");
70 compare(secondary.text, dataSecondaryText);72 compare(secondary.text, dataSecondaryText);
71 }73 }
74
75 function test_secondaryColor() {
76 // Check secondary color is correct
77 var secondary = findChild(labelRow, "secondary");
78 compare(secondary.color, dataSecondaryColor);
79 }
72 }80 }
73}81}
7482
=== modified file 'ubuntu-printing-app/tests/qmltests/tst_PrintPage.qml'
--- ubuntu-printing-app/tests/qmltests/tst_PrintPage.qml 2017-03-21 17:57:19 +0000
+++ ubuntu-printing-app/tests/qmltests/tst_PrintPage.qml 2017-04-05 12:09:01 +0000
@@ -119,11 +119,15 @@
119119
120 mockPrinting.printerJob.collate = true;120 mockPrinting.printerJob.collate = true;
121 mockPrinting.printerJob.copies = 1;121 mockPrinting.printerJob.copies = 1;
122 mockPrinting.printerJob.isTwoSided = false;
122 mockPrinting.printerJob.printRangeMode = PrinterEnum.AllPages;123 mockPrinting.printerJob.printRangeMode = PrinterEnum.AllPages;
123 mockPrinting.printerJob.reverse = false;124 mockPrinting.printerJob.reverse = false;
124125
125 mockPrinting.printerSelectedIndex = 0;126 mockPrinting.printerSelectedIndex = 0;
126127
128 var printRange = findChild(printPage, "pageRangeTextField");
129 printRange.value = "";
130
127 cancelSpy.clear();131 cancelSpy.clear();
128 confirmSpy.clear();132 confirmSpy.clear();
129133
@@ -261,6 +265,24 @@
261 compare(mockPrinting.printerJob.copies, 2);265 compare(mockPrinting.printerJob.copies, 2);
262 }266 }
263267
268 function test_copiesKeyClickZero() {
269 // Check copies starting value is correct
270 var copies = findChild(printPage, "copiesTextField");
271 compare(copies.value, "1");
272
273 // Click on the textField
274 mouseClick(copies);
275
276 // Clear the current text and try to enter "01"
277 keyClick(Qt.Key_Backspace);
278 keyClick(Qt.Key_0);
279 keyClick(Qt.Key_1);
280
281 // Check that "1" is set to the backend
282 tryCompare(copies, "value", "1", timeout, "Copies value did not change");
283 compare(mockPrinting.printerJob.copies, 1);
284 }
285
264 function test_duplex() {286 function test_duplex() {
265 var duplex = findChild(printPage, "duplexSelector");287 var duplex = findChild(printPage, "duplexSelector");
266288
@@ -406,6 +428,73 @@
406 }428 }
407 }429 }
408430
431 function test_printRange() {
432 document.url = Qt.resolvedUrl("../resources/pdf/mixed_portrait.pdf");
433
434 // Change to PageRange mode
435 mockPrinting.printerJob.printRangeMode = PrinterEnum.PageRange;
436
437 var printRange = findChild(printPage, "pageRangeTextField");
438 var printRangeError = findChild(printPage, "pageRangeErrorStrLabel");
439 var printRow = findChild(printPage, "printRow");
440
441 // Test that a range sets printRange in printerJob
442
443 // Click on the textField
444 mouseClick(printRange);
445
446 // Clear the current text and enter "2"
447 keyClick(Qt.Key_Backspace);
448 keyClick(Qt.Key_2);
449
450 compare(mockPrinting.printerJob.printRange, "2");
451 compare(printRangeError.visible, false);
452 compare(printRangeError.secondaryText, "");
453 compare(printRow.canPrint, true);
454
455
456 // Test that a invalid range shows the error and disables button
457
458 // Click on the textField
459 mouseClick(printRange);
460
461 // Clear the current text and enter ","
462 keyClick(Qt.Key_Backspace);
463 keyClick(Qt.Key_Comma);
464
465 compare(printRangeError.visible, true);
466 compare(printRangeError.secondaryText, i18n.tr("No number given in range"));
467 compare(printRow.canPrint, false);
468
469 // Clear the current text and enter "0"
470 keyClick(Qt.Key_Backspace);
471 keyClick(Qt.Key_0);
472
473 compare(printRangeError.visible, true);
474 compare(printRangeError.secondaryText, i18n.tr("Page is less than one"));
475 compare(printRow.canPrint, false);
476
477 // Clear the current text and enter "10"
478 keyClick(Qt.Key_Backspace);
479 keyClick(Qt.Key_1);
480 keyClick(Qt.Key_0);
481
482 compare(printRangeError.visible, true);
483 compare(printRangeError.secondaryText, i18n.tr("Page is higher than document page count"));
484 compare(printRow.canPrint, false);
485
486 // Clear the current text and enter "2-1"
487 keyClick(Qt.Key_Backspace);
488 keyClick(Qt.Key_Backspace);
489 keyClick(Qt.Key_2);
490 keyClick(Qt.Key_Minus);
491 keyClick(Qt.Key_1);
492
493 compare(printRangeError.visible, true);
494 compare(printRangeError.secondaryText, i18n.tr("Page low is greater than high"));
495 compare(printRow.canPrint, false);
496 }
497
409 function test_printRangeMode() {498 function test_printRangeMode() {
410 var printRangeMode = findChild(printPage, "pageRangeSelector");499 var printRangeMode = findChild(printPage, "pageRangeSelector");
411 var printRange = findChild(printPage, "pageRangeTextField");500 var printRange = findChild(printPage, "pageRangeTextField");
@@ -503,12 +592,70 @@
503 mockPrinting.printerJob.isTwoSided = true;592 mockPrinting.printerJob.isTwoSided = true;
504593
505 compare(printRow.sheets, 2);594 compare(printRow.sheets, 2);
506595 }
507 // Enable page ranges, this results in zero sheets596
508 mockPrinting.printerJob.printRange = "-3,5-7,9-";597 function test_sheets_range() {
598 var printRow = findChild(printPage, "printRow");
599 var printRange = findChild(printPage, "pageRangeTextField");
600
601 // has 3 pages
602 document.url = Qt.resolvedUrl("../resources/pdf/mixed_portrait.pdf");
603
604 compare(document.count, 3);
605 compare(mockPrinting.printerJob.copies, 1);
606 compare(mockPrinting.printerJob.isTwoSided, false);
607 compare(printRow.sheets, 3);
608
609 // Set range to 1 check than sheets is correct
509 mockPrinting.printerJob.printRangeMode = PrinterEnum.PageRange;610 mockPrinting.printerJob.printRangeMode = PrinterEnum.PageRange;
510611 printRange.value = "1";
511 compare(printRow.sheets, 0);612
613 compare(printRow.sheets, 1);
614
615 // Enable twoSided, we should get 0.5 rounded to 1 sheet
616 mockPrinting.printerJob.isTwoSided = true;
617
618 compare(mockPrinting.printerJob.isTwoSided, true);
619 compare(printRow.sheets, 1);
620
621 // Enable two copies, we should get 2 copies with duplex, so 1 sheet
622 mockPrinting.printerJob.copies = 2;
623
624 compare(mockPrinting.printerJob.copies, 2);
625 compare(printRow.sheets, 1);
626
627 // Disable two sided, so 2 copies and 2 sheets
628 mockPrinting.printerJob.isTwoSided = false;
629
630 compare(mockPrinting.printerJob.isTwoSided, false);
631 compare(printRow.sheets, 2);
632
633
634 // Set the range to 2 sheets
635 printRange.value = "1,2";
636
637 mockPrinting.printerJob.copies = 1;
638 mockPrinting.printerJob.isTwoSided = false;
639
640 compare(printRow.sheets, 2);
641
642 // Enable twoSided, we should get 2 pages on 1 sheet
643 mockPrinting.printerJob.isTwoSided = true;
644
645 compare(mockPrinting.printerJob.isTwoSided, true);
646 compare(printRow.sheets, 1);
647
648 // Enable two copies, we should get 2 copies with duplex, so 2 sheet
649 mockPrinting.printerJob.copies = 2;
650
651 compare(mockPrinting.printerJob.copies, 2);
652 compare(printRow.sheets, 2);
653
654 // Disable two sided, so 2 copies and 4 sheets
655 mockPrinting.printerJob.isTwoSided = false;
656
657 compare(mockPrinting.printerJob.isTwoSided, false);
658 compare(printRow.sheets, 4);
512 }659 }
513 }660 }
514}661}
515662
=== modified file 'ubuntu-printing-app/tests/unittests/backend/CMakeLists.txt'
--- ubuntu-printing-app/tests/unittests/backend/CMakeLists.txt 2017-03-15 11:57:40 +0000
+++ ubuntu-printing-app/tests/unittests/backend/CMakeLists.txt 2017-04-05 12:09:01 +0000
@@ -14,6 +14,10 @@
14target_link_libraries(testPageHelper UbuntuPrintingAppbackend Qt5::Test Qt5::Gui)14target_link_libraries(testPageHelper UbuntuPrintingAppbackend Qt5::Test Qt5::Gui)
15add_test(tst_pagehelper testPageHelper)15add_test(tst_pagehelper testPageHelper)
1616
17add_executable(testPageRangeValidator tst_pagerangevalidator.cpp ${PDF_TEST_FILES})
18target_link_libraries(testPageRangeValidator UbuntuPrintingAppbackend Qt5::Test Qt5::Gui)
19add_test(tst_pagerangevalidator testPageRangeValidator)
20
17add_executable(testPopplerImageProvider tst_popplerimageprovider.cpp ${PDF_TEST_FILES})21add_executable(testPopplerImageProvider tst_popplerimageprovider.cpp ${PDF_TEST_FILES})
18target_link_libraries(testPopplerImageProvider UbuntuPrintingAppbackend Qt5::Test Qt5::Gui)22target_link_libraries(testPopplerImageProvider UbuntuPrintingAppbackend Qt5::Test Qt5::Gui)
19add_test(tst_popplerimageprovider testPopplerImageProvider)23add_test(tst_popplerimageprovider testPopplerImageProvider)
2024
=== added file 'ubuntu-printing-app/tests/unittests/backend/tst_pagerangevalidator.cpp'
--- ubuntu-printing-app/tests/unittests/backend/tst_pagerangevalidator.cpp 1970-01-01 00:00:00 +0000
+++ ubuntu-printing-app/tests/unittests/backend/tst_pagerangevalidator.cpp 2017-04-05 12:09:01 +0000
@@ -0,0 +1,151 @@
1/*
2 * Copyright 2017 Canonical Ltd.
3 *
4 * This file is part of ubuntu-printing-app.
5 *
6 * ubuntu-printing-app is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * ubuntu-printing-app is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com>
19 */
20
21#include <QObject>
22#include <QSignalSpy>
23#include <QTest>
24
25#include "UbuntuPrintingApp/pagerangevalidator.h"
26
27class TestPageRangeValidator : public QObject
28{
29 Q_OBJECT
30private Q_SLOTS:
31 void init()
32 {
33 m_validator = new PageRangeValidator();
34 }
35 void cleanup()
36 {
37 QSignalSpy destroyedSpy(m_validator, SIGNAL(destroyed(QObject*)));
38 m_validator->deleteLater();
39 QTRY_COMPARE(destroyedSpy.count(), 1);
40 }
41
42 // Check that the initial values are correct
43 void testInit()
44 {
45 QCOMPARE(m_validator->count(), 0);
46 QCOMPARE(m_validator->documentCount(), 0);
47 QCOMPARE(m_validator->error(), PageRangeValidator::PageRangeError::NoError);
48 QCOMPARE(m_validator->pages(), QStringLiteral(""));
49 }
50
51 // Check that the document count can be set
52 void testDocumentCount()
53 {
54 QSignalSpy documentCountSpy(m_validator, SIGNAL(documentCountChanged(int)));
55 m_validator->setDocumentCount(10);
56
57 QTRY_COMPARE(documentCountSpy.count(), 1);
58 QCOMPARE(m_validator->documentCount(), 10);
59 }
60
61 void testValidate_data()
62 {
63 QTest::addColumn<QString>("input");
64 QTest::addColumn<bool>("result");
65
66 // Good values
67 QTest::newRow("empty") << "" << true;
68 QTest::newRow("single value") << "2" << true;
69 QTest::newRow("multiple values") << "2,3,4" << true;
70 QTest::newRow("no lower") << "-2" << true;
71 QTest::newRow("no upper") << "2-" << true;
72 QTest::newRow("single range") << "2-3" << true;
73 QTest::newRow("range and value") << "2-3,6" << true;
74 QTest::newRow("multiple ranges") << "2-3,6-7" << true;
75 QTest::newRow("overlapping ranges") << "2-8,6-10" << true;
76 QTest::newRow("dash") << "-" << true;
77 QTest::newRow("comma") << "," << true;
78 QTest::newRow("double comma") << ",," << true;
79
80 // Bad values
81 QTest::newRow("no comma multi range") << "1-2-3" << false;
82 QTest::newRow("double dash") << "--" << false;
83 QTest::newRow("double dash range") << "2--3" << false;
84 QTest::newRow("letter") << "a" << false;
85 }
86
87 void testValidate()
88 {
89 QFETCH(QString, input);
90 QFETCH(bool, result);
91
92 int pos = 0;
93
94 QCOMPARE(m_validator->validate(input, pos), result ? QValidator::State::Acceptable : QValidator::State::Invalid);
95 }
96
97 void testValidateValues_data()
98 {
99 QTest::addColumn<QString>("input");
100 QTest::addColumn<bool>("result");
101 QTest::addColumn<int>("count");
102 QTest::addColumn<QString>("pages");
103 QTest::addColumn<PageRangeValidator::PageRangeError>("error");
104
105 // Good values
106 QTest::newRow("empty") << "" << true << 10 << "" << PageRangeValidator::NoError;
107 QTest::newRow("single value") << "2" << true << 1 << "2" << PageRangeValidator::NoError;
108 QTest::newRow("multiple values") << "2,3,4" << true << 3 << "2,3,4" << PageRangeValidator::NoError;
109 QTest::newRow("multiple values sort") << "4,3,2" << true << 3 << "2,3,4" << PageRangeValidator::NoError;
110 QTest::newRow("no lower") << "-5" << true << 5 << "1,2,3,4,5" << PageRangeValidator::NoError;
111 QTest::newRow("no upper") << "5-" << true << 6 << "5,6,7,8,9,10" << PageRangeValidator::NoError;
112 QTest::newRow("single range") << "2-3" << true << 2 << "2,3" << PageRangeValidator::NoError;
113 QTest::newRow("range and value") << "2-3,6" << true << 3 << "2,3,6" << PageRangeValidator::NoError;
114 QTest::newRow("multiple ranges") << "2-3,6-7" << true << 4 << "2,3,6,7" << PageRangeValidator::NoError;
115 QTest::newRow("overlapping ranges") << "2-5,3-6" << true << 5 << "2,3,4,5,6" << PageRangeValidator::NoError;
116
117 // Values that pass validate() but fail range checks
118 QTest::newRow("dash") << "-" << false << 0 << "" << PageRangeValidator::NoPageInRange;
119 QTest::newRow("comma") << "," << false << 0 << "" << PageRangeValidator::NoPageInRange;
120 QTest::newRow("double comma") << ",," << false << 0 << "" << PageRangeValidator::NoPageInRange;
121
122 // Values that fail range checks
123 QTest::newRow("low less than 1") << "0-" << false << 0 << "" << PageRangeValidator::PageLessThanOne;
124 QTest::newRow("high less than 1") << "-0" << false << 0 << "" << PageRangeValidator::PageLessThanOne;
125 QTest::newRow("low higher than doc count") << "50-" << false << 0 << "" << PageRangeValidator::PageHigherThanDocument;
126 QTest::newRow("high higher than doc count") << "-50" << false << 0 << "" << PageRangeValidator::PageHigherThanDocument;
127 QTest::newRow("low higher than high") << "5-3" << false << 0 << "" << PageRangeValidator::PageLowGreaterThanHigh;
128 }
129
130 void testValidateValues()
131 {
132 QFETCH(QString, input);
133 QFETCH(bool, result);
134 QFETCH(int, count);
135 QFETCH(QString, pages);
136 QFETCH(PageRangeValidator::PageRangeError, error);
137
138 m_validator->setDocumentCount(10);
139
140 QCOMPARE(m_validator->validateValues(input), result);
141 QCOMPARE(m_validator->count(), count);
142 QCOMPARE(m_validator->pages(), pages);
143 QCOMPARE(m_validator->error(), error);
144 }
145
146private:
147 PageRangeValidator *m_validator;
148};
149
150QTEST_GUILESS_MAIN(TestPageRangeValidator)
151#include "tst_pagerangevalidator.moc"

Subscribers

People subscribed via source and target branches

to all changes: