Merge lp:~ahayzen/ubuntu-printing-app/page-range-validate-and-count into lp:ubuntu-printing-app
- page-range-validate-and-count
- Merge into trunk
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 |
Related bugs: |
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
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.
Andrew Hayzen (ahayzen) wrote : | # |
Reported bug 1680048 for advanced page ranges. And now setting Qt.ImhPreferNumbers for the page range field.
Michael Sheldon (michael-sheldon) wrote : | # |
Looks good :)
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
1 | === modified file 'po/ubuntu-printing-app.pot' | |||
2 | --- po/ubuntu-printing-app.pot 2017-03-21 17:57:19 +0000 | |||
3 | +++ po/ubuntu-printing-app.pot 2017-04-05 12:09:01 +0000 | |||
4 | @@ -8,7 +8,7 @@ | |||
5 | 8 | msgstr "" | 8 | msgstr "" |
6 | 9 | "Project-Id-Version: PACKAGE VERSION\n" | 9 | "Project-Id-Version: PACKAGE VERSION\n" |
7 | 10 | "Report-Msgid-Bugs-To: \n" | 10 | "Report-Msgid-Bugs-To: \n" |
9 | 11 | "POT-Creation-Date: 2017-03-21 17:56+0000\n" | 11 | "POT-Creation-Date: 2017-04-05 12:51+0100\n" |
10 | 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
11 | 13 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | 13 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
12 | 14 | "Language-Team: LANGUAGE <LL@li.org>\n" | 14 | "Language-Team: LANGUAGE <LL@li.org>\n" |
13 | @@ -185,39 +185,55 @@ | |||
14 | 185 | msgid "Copies" | 185 | msgid "Copies" |
15 | 186 | msgstr "" | 186 | msgstr "" |
16 | 187 | 187 | ||
18 | 188 | #: ../ubuntu-printing-app/pages/PrintPage.qml:131 | 188 | #: ../ubuntu-printing-app/pages/PrintPage.qml:130 |
19 | 189 | msgid "All" | 189 | msgid "All" |
20 | 190 | msgstr "" | 190 | msgstr "" |
21 | 191 | 191 | ||
23 | 192 | #: ../ubuntu-printing-app/pages/PrintPage.qml:131 | 192 | #: ../ubuntu-printing-app/pages/PrintPage.qml:130 |
24 | 193 | msgid "Range" | 193 | msgid "Range" |
25 | 194 | msgstr "" | 194 | msgstr "" |
26 | 195 | 195 | ||
28 | 196 | #: ../ubuntu-printing-app/pages/PrintPage.qml:135 | 196 | #: ../ubuntu-printing-app/pages/PrintPage.qml:134 |
29 | 197 | msgid "Pages" | 197 | msgid "Pages" |
30 | 198 | msgstr "" | 198 | msgstr "" |
31 | 199 | 199 | ||
33 | 200 | #: ../ubuntu-printing-app/pages/PrintPage.qml:177 | 200 | #: ../ubuntu-printing-app/pages/PrintPage.qml:175 |
34 | 201 | msgid "eg 1-3,8" | 201 | msgid "eg 1-3,8" |
35 | 202 | msgstr "" | 202 | msgstr "" |
36 | 203 | 203 | ||
37 | 204 | #: ../ubuntu-printing-app/pages/PrintPage.qml:186 | 204 | #: ../ubuntu-printing-app/pages/PrintPage.qml:186 |
38 | 205 | msgid "No number given in range" | ||
39 | 206 | msgstr "" | ||
40 | 207 | |||
41 | 208 | #: ../ubuntu-printing-app/pages/PrintPage.qml:189 | ||
42 | 209 | msgid "Page is less than one" | ||
43 | 210 | msgstr "" | ||
44 | 211 | |||
45 | 212 | #: ../ubuntu-printing-app/pages/PrintPage.qml:192 | ||
46 | 213 | msgid "Page is higher than document page count" | ||
47 | 214 | msgstr "" | ||
48 | 215 | |||
49 | 216 | #: ../ubuntu-printing-app/pages/PrintPage.qml:195 | ||
50 | 217 | msgid "Second page cannot be lower than first" | ||
51 | 218 | msgstr "" | ||
52 | 219 | |||
53 | 220 | #: ../ubuntu-printing-app/pages/PrintPage.qml:211 | ||
54 | 205 | msgid "Two-sided" | 221 | msgid "Two-sided" |
55 | 206 | msgstr "" | 222 | msgstr "" |
56 | 207 | 223 | ||
58 | 208 | #: ../ubuntu-printing-app/pages/PrintPage.qml:207 | 224 | #: ../ubuntu-printing-app/pages/PrintPage.qml:232 |
59 | 209 | msgid "Color" | 225 | msgid "Color" |
60 | 210 | msgstr "" | 226 | msgstr "" |
61 | 211 | 227 | ||
63 | 212 | #: ../ubuntu-printing-app/pages/PrintPage.qml:228 | 228 | #: ../ubuntu-printing-app/pages/PrintPage.qml:253 |
64 | 213 | msgid "Quality" | 229 | msgid "Quality" |
65 | 214 | msgstr "" | 230 | msgstr "" |
66 | 215 | 231 | ||
68 | 216 | #: ../ubuntu-printing-app/pages/PrintPage.qml:246 | 232 | #: ../ubuntu-printing-app/pages/PrintPage.qml:271 |
69 | 217 | msgid "Collate" | 233 | msgid "Collate" |
70 | 218 | msgstr "" | 234 | msgstr "" |
71 | 219 | 235 | ||
73 | 220 | #: ../ubuntu-printing-app/pages/PrintPage.qml:266 | 236 | #: ../ubuntu-printing-app/pages/PrintPage.qml:291 |
74 | 221 | msgid "Reverse" | 237 | msgid "Reverse" |
75 | 222 | msgstr "" | 238 | msgstr "" |
76 | 223 | 239 | ||
77 | 224 | 240 | ||
78 | === modified file 'ubuntu-printing-app/backend/CMakeLists.txt' | |||
79 | --- ubuntu-printing-app/backend/CMakeLists.txt 2017-03-07 15:01:56 +0000 | |||
80 | +++ ubuntu-printing-app/backend/CMakeLists.txt 2017-04-05 12:09:01 +0000 | |||
81 | @@ -9,8 +9,9 @@ | |||
82 | 9 | UbuntuPrintingAppSRC | 9 | UbuntuPrintingAppSRC |
83 | 10 | UbuntuPrintingApp/backend.cpp | 10 | UbuntuPrintingApp/backend.cpp |
84 | 11 | UbuntuPrintingApp/document.cpp | 11 | UbuntuPrintingApp/document.cpp |
85 | 12 | UbuntuPrintingApp/pagehelper.cpp | ||
86 | 13 | UbuntuPrintingApp/pagerangevalidator.cpp | ||
87 | 12 | UbuntuPrintingApp/popplerimageprovider.cpp | 14 | UbuntuPrintingApp/popplerimageprovider.cpp |
88 | 13 | UbuntuPrintingApp/pagehelper.cpp | ||
89 | 14 | ) | 15 | ) |
90 | 15 | 16 | ||
91 | 16 | add_library(${LIBNAME} SHARED ${UbuntuPrintingAppSRC}) | 17 | add_library(${LIBNAME} SHARED ${UbuntuPrintingAppSRC}) |
92 | 17 | 18 | ||
93 | === modified file 'ubuntu-printing-app/backend/UbuntuPrintingApp/backend.cpp' | |||
94 | --- ubuntu-printing-app/backend/UbuntuPrintingApp/backend.cpp 2017-01-30 15:19:57 +0000 | |||
95 | +++ ubuntu-printing-app/backend/UbuntuPrintingApp/backend.cpp 2017-04-05 12:09:01 +0000 | |||
96 | @@ -23,6 +23,7 @@ | |||
97 | 23 | 23 | ||
98 | 24 | #include "document.h" | 24 | #include "document.h" |
99 | 25 | #include "pagehelper.h" | 25 | #include "pagehelper.h" |
100 | 26 | #include "pagerangevalidator.h" | ||
101 | 26 | #include "popplerimageprovider.h" | 27 | #include "popplerimageprovider.h" |
102 | 27 | 28 | ||
103 | 28 | void BackendPlugin::registerTypes(const char *uri) | 29 | void BackendPlugin::registerTypes(const char *uri) |
104 | @@ -31,6 +32,7 @@ | |||
105 | 31 | 32 | ||
106 | 32 | qmlRegisterType<Document>(uri, 1, 0, "Document"); | 33 | qmlRegisterType<Document>(uri, 1, 0, "Document"); |
107 | 33 | qmlRegisterType<PageHelper>(uri, 1, 0, "PageHelper"); | 34 | qmlRegisterType<PageHelper>(uri, 1, 0, "PageHelper"); |
108 | 35 | qmlRegisterType<PageRangeValidator>(uri, 1, 0, "PageRangeValidator"); | ||
109 | 34 | } | 36 | } |
110 | 35 | 37 | ||
111 | 36 | void BackendPlugin::initializeEngine(QQmlEngine *engine, const char *uri) | 38 | void BackendPlugin::initializeEngine(QQmlEngine *engine, const char *uri) |
112 | 37 | 39 | ||
113 | === added file 'ubuntu-printing-app/backend/UbuntuPrintingApp/pagerangevalidator.cpp' | |||
114 | --- ubuntu-printing-app/backend/UbuntuPrintingApp/pagerangevalidator.cpp 1970-01-01 00:00:00 +0000 | |||
115 | +++ ubuntu-printing-app/backend/UbuntuPrintingApp/pagerangevalidator.cpp 2017-04-05 12:09:01 +0000 | |||
116 | @@ -0,0 +1,192 @@ | |||
117 | 1 | /* | ||
118 | 2 | * Copyright 2017 Canonical Ltd. | ||
119 | 3 | * | ||
120 | 4 | * This file is part of ubuntu-printing-app. | ||
121 | 5 | * | ||
122 | 6 | * ubuntu-printing-app is free software; you can redistribute it and/or modify | ||
123 | 7 | * it under the terms of the GNU General Public License as published by | ||
124 | 8 | * the Free Software Foundation; version 3. | ||
125 | 9 | * | ||
126 | 10 | * ubuntu-printing-app is distributed in the hope that it will be useful, | ||
127 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
128 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
129 | 13 | * GNU General Public License for more details. | ||
130 | 14 | * | ||
131 | 15 | * You should have received a copy of the GNU General Public License | ||
132 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
133 | 17 | * | ||
134 | 18 | * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com> | ||
135 | 19 | */ | ||
136 | 20 | |||
137 | 21 | #include "pagerangevalidator.h" | ||
138 | 22 | |||
139 | 23 | #include <QtCore/QRegularExpressionMatch> | ||
140 | 24 | #include <QtCore/QList> | ||
141 | 25 | |||
142 | 26 | PageRangeValidator::PageRangeValidator(QObject *parent) | ||
143 | 27 | : QValidator(parent) | ||
144 | 28 | , m_count(0) | ||
145 | 29 | , m_document_count(0) | ||
146 | 30 | , m_error(PageRangeError::NoError) | ||
147 | 31 | , m_pages({}) | ||
148 | 32 | , m_validate_re(QStringLiteral("^(\\d+)?[-]?(\\d+)?([,](\\d+)?[-]?(\\d+)?)*$")) | ||
149 | 33 | , m_validate_values_re(QStringLiteral("^(\\d*)?[-]?(\\d*)?$")) | ||
150 | 34 | { | ||
151 | 35 | |||
152 | 36 | } | ||
153 | 37 | |||
154 | 38 | int PageRangeValidator::count() const | ||
155 | 39 | { | ||
156 | 40 | return m_count; | ||
157 | 41 | } | ||
158 | 42 | |||
159 | 43 | int PageRangeValidator::documentCount() const | ||
160 | 44 | { | ||
161 | 45 | return m_document_count; | ||
162 | 46 | } | ||
163 | 47 | |||
164 | 48 | PageRangeValidator::PageRangeError PageRangeValidator::error() const | ||
165 | 49 | { | ||
166 | 50 | return m_error; | ||
167 | 51 | } | ||
168 | 52 | |||
169 | 53 | QString PageRangeValidator::pages() const | ||
170 | 54 | { | ||
171 | 55 | // Convert the pages to a list of comma's for QML and cups | ||
172 | 56 | QStringList list; | ||
173 | 57 | |||
174 | 58 | // Get a list and sort while still int so that 10 > 2 | ||
175 | 59 | QList<int> pages = m_pages.toList(); | ||
176 | 60 | qSort(pages); | ||
177 | 61 | |||
178 | 62 | Q_FOREACH(int page, pages) { | ||
179 | 63 | list << QString::number(page); | ||
180 | 64 | } | ||
181 | 65 | |||
182 | 66 | return list.join(","); | ||
183 | 67 | } | ||
184 | 68 | |||
185 | 69 | void PageRangeValidator::setCount(const int count) | ||
186 | 70 | { | ||
187 | 71 | if (m_count != count) { | ||
188 | 72 | m_count = count; | ||
189 | 73 | |||
190 | 74 | Q_EMIT countChanged(m_count); | ||
191 | 75 | } | ||
192 | 76 | } | ||
193 | 77 | |||
194 | 78 | void PageRangeValidator::setDocumentCount(const int documentCount) | ||
195 | 79 | { | ||
196 | 80 | if (m_document_count != documentCount) { | ||
197 | 81 | m_document_count = documentCount; | ||
198 | 82 | |||
199 | 83 | Q_EMIT documentCountChanged(m_document_count); | ||
200 | 84 | } | ||
201 | 85 | } | ||
202 | 86 | |||
203 | 87 | void PageRangeValidator::setError(const PageRangeValidator::PageRangeError error) | ||
204 | 88 | { | ||
205 | 89 | if (m_error != error) { | ||
206 | 90 | m_error = error; | ||
207 | 91 | |||
208 | 92 | Q_EMIT errorChanged(m_error); | ||
209 | 93 | } | ||
210 | 94 | } | ||
211 | 95 | |||
212 | 96 | void PageRangeValidator::setPages(const QSet<int> pages) | ||
213 | 97 | { | ||
214 | 98 | if (m_pages != pages) { | ||
215 | 99 | m_pages = pages; | ||
216 | 100 | |||
217 | 101 | setCount(m_pages.count()); | ||
218 | 102 | |||
219 | 103 | Q_EMIT pagesChanged(this->pages()); | ||
220 | 104 | } | ||
221 | 105 | } | ||
222 | 106 | |||
223 | 107 | QValidator::State PageRangeValidator::validate(QString &input, int &pos) const | ||
224 | 108 | { | ||
225 | 109 | Q_UNUSED(pos); | ||
226 | 110 | |||
227 | 111 | // TODO: maybe use partial match for 1-3-5? | ||
228 | 112 | // QRegularExpression::PartialPreferCompleteMatch | ||
229 | 113 | // QValidator::State::Intermediate | ||
230 | 114 | // however then it allows 1,------ | ||
231 | 115 | QRegularExpressionMatch match = m_validate_re.match(input, 0); | ||
232 | 116 | |||
233 | 117 | if (match.hasMatch()) { | ||
234 | 118 | return QValidator::State::Acceptable; | ||
235 | 119 | } else { | ||
236 | 120 | return QValidator::State::Invalid; | ||
237 | 121 | } | ||
238 | 122 | } | ||
239 | 123 | |||
240 | 124 | bool PageRangeValidator::validateValues(QString input) | ||
241 | 125 | { | ||
242 | 126 | bool valid = true; | ||
243 | 127 | |||
244 | 128 | // If the given value is empty then set the whole range | ||
245 | 129 | if (input.isEmpty()) { | ||
246 | 130 | setPages({}); | ||
247 | 131 | setCount(documentCount()); | ||
248 | 132 | |||
249 | 133 | return valid; | ||
250 | 134 | } | ||
251 | 135 | |||
252 | 136 | QSet<int> pages; | ||
253 | 137 | setError(PageRangeError::NoError); | ||
254 | 138 | |||
255 | 139 | Q_FOREACH(QString part, input.split(",")) { | ||
256 | 140 | QRegularExpressionMatch matches = m_validate_values_re.match(part); | ||
257 | 141 | |||
258 | 142 | QString low = matches.captured(1); | ||
259 | 143 | QString high = matches.captured(2); | ||
260 | 144 | |||
261 | 145 | if (low.isEmpty() && high.isEmpty()) { | ||
262 | 146 | setError(PageRangeError::NoPageInRange); | ||
263 | 147 | valid = false; | ||
264 | 148 | break; | ||
265 | 149 | } else if (high.isEmpty()) { | ||
266 | 150 | if (part.contains("-")) { | ||
267 | 151 | // 1- add the range from the lower until the document count | ||
268 | 152 | high = QString::number(documentCount()); | ||
269 | 153 | } else { | ||
270 | 154 | // 1 Add the given page | ||
271 | 155 | high = low; | ||
272 | 156 | } | ||
273 | 157 | } else if (low.isEmpty()) { | ||
274 | 158 | // -3 add the range up to the higher number | ||
275 | 159 | low = QString::number(1); | ||
276 | 160 | } else { | ||
277 | 161 | // high and low set, we don't need todo anything | ||
278 | 162 | } | ||
279 | 163 | |||
280 | 164 | // Convert to ints | ||
281 | 165 | int lower = low.toInt(); | ||
282 | 166 | int higher = high.toInt(); | ||
283 | 167 | |||
284 | 168 | // Validate the numbers | ||
285 | 169 | if (lower < 1 || higher < 1) { | ||
286 | 170 | setError(PageRangeError::PageLessThanOne); | ||
287 | 171 | valid = false; | ||
288 | 172 | break; | ||
289 | 173 | } else if (lower > documentCount() || higher > documentCount()) { | ||
290 | 174 | setError(PageRangeError::PageHigherThanDocument); | ||
291 | 175 | valid = false; | ||
292 | 176 | break; | ||
293 | 177 | } else if (lower > higher) { | ||
294 | 178 | setError(PageRangeError::PageLowGreaterThanHigh); | ||
295 | 179 | valid = false; | ||
296 | 180 | break; | ||
297 | 181 | } else { | ||
298 | 182 | // Valid so lets push given pages numbers | ||
299 | 183 | for (int i=lower; i <= higher; i++) { | ||
300 | 184 | pages.insert(i); | ||
301 | 185 | } | ||
302 | 186 | } | ||
303 | 187 | } | ||
304 | 188 | |||
305 | 189 | setPages(pages); | ||
306 | 190 | |||
307 | 191 | return valid; | ||
308 | 192 | } | ||
309 | 0 | 193 | ||
310 | === added file 'ubuntu-printing-app/backend/UbuntuPrintingApp/pagerangevalidator.h' | |||
311 | --- ubuntu-printing-app/backend/UbuntuPrintingApp/pagerangevalidator.h 1970-01-01 00:00:00 +0000 | |||
312 | +++ ubuntu-printing-app/backend/UbuntuPrintingApp/pagerangevalidator.h 2017-04-05 12:09:01 +0000 | |||
313 | @@ -0,0 +1,75 @@ | |||
314 | 1 | /* | ||
315 | 2 | * Copyright 2017 Canonical Ltd. | ||
316 | 3 | * | ||
317 | 4 | * This file is part of ubuntu-printing-app. | ||
318 | 5 | * | ||
319 | 6 | * ubuntu-printing-app is free software; you can redistribute it and/or modify | ||
320 | 7 | * it under the terms of the GNU General Public License as published by | ||
321 | 8 | * the Free Software Foundation; version 3. | ||
322 | 9 | * | ||
323 | 10 | * ubuntu-printing-app is distributed in the hope that it will be useful, | ||
324 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
325 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
326 | 13 | * GNU General Public License for more details. | ||
327 | 14 | * | ||
328 | 15 | * You should have received a copy of the GNU General Public License | ||
329 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
330 | 17 | * | ||
331 | 18 | * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com> | ||
332 | 19 | */ | ||
333 | 20 | #ifndef PAGERANGEVALIDATOR_H | ||
334 | 21 | #define PAGERANGEVALIDATOR_H | ||
335 | 22 | |||
336 | 23 | #include <QtCore/QRegularExpression> | ||
337 | 24 | #include <QtCore/QSet> | ||
338 | 25 | #include <QtGui/QValidator> | ||
339 | 26 | |||
340 | 27 | class PageRangeValidator : public QValidator | ||
341 | 28 | { | ||
342 | 29 | Q_OBJECT | ||
343 | 30 | |||
344 | 31 | Q_PROPERTY(int count READ count NOTIFY countChanged) | ||
345 | 32 | Q_PROPERTY(int documentCount READ documentCount WRITE setDocumentCount NOTIFY documentCountChanged) | ||
346 | 33 | Q_PROPERTY(PageRangeError error READ error NOTIFY errorChanged) | ||
347 | 34 | Q_PROPERTY(QString pages READ pages NOTIFY pagesChanged) | ||
348 | 35 | public: | ||
349 | 36 | PageRangeValidator(QObject *parent=Q_NULLPTR); | ||
350 | 37 | |||
351 | 38 | enum PageRangeError { | ||
352 | 39 | NoError, | ||
353 | 40 | NoPageInRange, | ||
354 | 41 | PageLessThanOne, | ||
355 | 42 | PageHigherThanDocument, | ||
356 | 43 | PageLowGreaterThanHigh, | ||
357 | 44 | }; | ||
358 | 45 | Q_ENUM(PageRangeError) | ||
359 | 46 | |||
360 | 47 | int count() const; | ||
361 | 48 | int documentCount() const; | ||
362 | 49 | PageRangeError error() const; | ||
363 | 50 | QString pages() const; | ||
364 | 51 | virtual QValidator::State validate(QString &input, int &pos) const override; | ||
365 | 52 | |||
366 | 53 | Q_INVOKABLE bool validateValues(QString input); | ||
367 | 54 | Q_SIGNALS: | ||
368 | 55 | void countChanged(int count); | ||
369 | 56 | void documentCountChanged(int documentCount); | ||
370 | 57 | void errorChanged(PageRangeError error); | ||
371 | 58 | void pagesChanged(QString pages); | ||
372 | 59 | public Q_SLOTS: | ||
373 | 60 | void setDocumentCount(const int documentCount); | ||
374 | 61 | private Q_SLOTS: | ||
375 | 62 | void setCount(const int count); | ||
376 | 63 | void setPages(const QSet<int> pages); | ||
377 | 64 | void setError(const PageRangeError error); | ||
378 | 65 | private: | ||
379 | 66 | int m_count; | ||
380 | 67 | int m_document_count; | ||
381 | 68 | PageRangeError m_error; | ||
382 | 69 | QSet<int> m_pages; | ||
383 | 70 | QRegularExpression m_validate_re; | ||
384 | 71 | QRegularExpression m_validate_values_re; | ||
385 | 72 | }; | ||
386 | 73 | |||
387 | 74 | |||
388 | 75 | #endif // PAGERANGEVALIDATOR_H | ||
389 | 0 | 76 | ||
390 | === modified file 'ubuntu-printing-app/components/LabelRow.qml' | |||
391 | --- ubuntu-printing-app/components/LabelRow.qml 2017-03-07 13:46:02 +0000 | |||
392 | +++ ubuntu-printing-app/components/LabelRow.qml 2017-04-05 12:09:01 +0000 | |||
393 | @@ -26,6 +26,7 @@ | |||
394 | 26 | property alias enabled: secondaryLabel.enabled | 26 | property alias enabled: secondaryLabel.enabled |
395 | 27 | property alias primaryText: primaryLabel.text | 27 | property alias primaryText: primaryLabel.text |
396 | 28 | property alias secondaryText: secondaryLabel.text | 28 | property alias secondaryText: secondaryLabel.text |
397 | 29 | property alias secondaryColor: secondaryLabel.color | ||
398 | 29 | 30 | ||
399 | 30 | Label { | 31 | Label { |
400 | 31 | id: primaryLabel | 32 | id: primaryLabel |
401 | @@ -40,5 +41,6 @@ | |||
402 | 40 | Layout.preferredWidth: units.gu(10) | 41 | Layout.preferredWidth: units.gu(10) |
403 | 41 | objectName: "secondary" | 42 | objectName: "secondary" |
404 | 42 | verticalAlignment: Text.AlignVCenter | 43 | verticalAlignment: Text.AlignVCenter |
405 | 44 | wrapMode: Text.WrapAtWordBoundaryOrAnywhere | ||
406 | 43 | } | 45 | } |
407 | 44 | } | 46 | } |
408 | 45 | 47 | ||
409 | === modified file 'ubuntu-printing-app/pages/PrintPage.qml' | |||
410 | --- ubuntu-printing-app/pages/PrintPage.qml 2017-03-21 18:00:19 +0000 | |||
411 | +++ ubuntu-printing-app/pages/PrintPage.qml 2017-04-05 12:09:01 +0000 | |||
412 | @@ -105,9 +105,8 @@ | |||
413 | 105 | inputMethodHints: Qt.ImhDigitsOnly | 105 | inputMethodHints: Qt.ImhDigitsOnly |
414 | 106 | objectName: "copiesTextField" | 106 | objectName: "copiesTextField" |
415 | 107 | text: i18n.tr("Copies") | 107 | text: i18n.tr("Copies") |
419 | 108 | validator: IntValidator { | 108 | validator: RegExpValidator { |
420 | 109 | bottom: 1 | 109 | regExp: /^[1-9](\d)*$/ |
418 | 110 | top: 999 | ||
421 | 111 | } | 110 | } |
422 | 112 | value: printing.printerJob.copies | 111 | value: printing.printerJob.copies |
423 | 113 | 112 | ||
424 | @@ -151,23 +150,23 @@ | |||
425 | 151 | TextFieldRow { | 150 | TextFieldRow { |
426 | 152 | id: pageRangeTextField | 151 | id: pageRangeTextField |
427 | 153 | enabled: printing.isLoaded && !printing.pdfMode | 152 | enabled: printing.isLoaded && !printing.pdfMode |
428 | 153 | inputMethodHints: Qt.ImhPreferNumbers | ||
429 | 154 | objectName: "pageRangeTextField" | 154 | objectName: "pageRangeTextField" |
432 | 155 | validator: RegExpValidator { | 155 | validator: PageRangeValidator { |
433 | 156 | // regExp: "" // TODO: validate to only 0-9||9-0||0 , | 156 | documentCount: document.count |
434 | 157 | |||
435 | 158 | // validate() is const, so bind a secondary validateValues | ||
436 | 159 | // which checks the values in the range are valid | ||
437 | 160 | // and sets the count/pages | ||
438 | 161 | readonly property bool validValues: validateValues(pageRangeTextField.value) | ||
439 | 157 | } | 162 | } |
440 | 158 | visible: pageRangeSelector.selectedValue === PrinterEnum.PageRange | 163 | visible: pageRangeSelector.selectedValue === PrinterEnum.PageRange |
441 | 159 | 164 | ||
442 | 160 | onValueChanged: { | ||
443 | 161 | if (printing.printerJob.printRange !== value) { | ||
444 | 162 | printing.printerJob.printRange = value | ||
445 | 163 | } | ||
446 | 164 | } | ||
447 | 165 | |||
448 | 166 | Binding { | 165 | Binding { |
453 | 167 | target: pageRangeTextField | 166 | target: printing.printerJob |
454 | 168 | property: "value" | 167 | property: "printRange" |
455 | 169 | when: printing.printerJob && pageRangeTextField.enabled | 168 | when: printing.printerJob && pageRangeTextField.enabled && pageRangeTextField.validator.validValues |
456 | 170 | value: printing.printerJob.printRange | 169 | value: pageRangeTextField.validator.pages |
457 | 171 | } | 170 | } |
458 | 172 | } | 171 | } |
459 | 173 | 172 | ||
460 | @@ -178,6 +177,33 @@ | |||
461 | 178 | visible: pageRangeSelector.selectedValue === PrinterEnum.PageRange | 177 | visible: pageRangeSelector.selectedValue === PrinterEnum.PageRange |
462 | 179 | } | 178 | } |
463 | 180 | 179 | ||
464 | 180 | LabelRow { | ||
465 | 181 | enabled: printing.isLoaded && !printing.pdfMode | ||
466 | 182 | objectName: "pageRangeErrorStrLabel" | ||
467 | 183 | secondaryColor: theme.palette.normal.negative | ||
468 | 184 | secondaryText: { | ||
469 | 185 | switch (pageRangeTextField.validator.error) { | ||
470 | 186 | case PageRangeValidator.NoPageInRange: | ||
471 | 187 | i18n.tr("No number given in range") | ||
472 | 188 | break; | ||
473 | 189 | case PageRangeValidator.PageLessThanOne: | ||
474 | 190 | i18n.tr("Page is less than one") | ||
475 | 191 | break; | ||
476 | 192 | case PageRangeValidator.PageHigherThanDocument: | ||
477 | 193 | i18n.tr("Page is higher than document page count") | ||
478 | 194 | break; | ||
479 | 195 | case PageRangeValidator.PageLowGreaterThanHigh: | ||
480 | 196 | i18n.tr("Second page cannot be lower than first") | ||
481 | 197 | break; | ||
482 | 198 | default: | ||
483 | 199 | case PageRangeValidator.NoError: | ||
484 | 200 | "" | ||
485 | 201 | break; | ||
486 | 202 | } | ||
487 | 203 | } | ||
488 | 204 | visible: pageRangeSelector.selectedValue === PrinterEnum.PageRange && !pageRangeTextField.validator.validValues | ||
489 | 205 | } | ||
490 | 206 | |||
491 | 181 | SelectorRow { | 207 | SelectorRow { |
492 | 182 | id: duplexSelector | 208 | id: duplexSelector |
493 | 183 | enabled: printing.isEditable && currentDocument.count > 1 && printing.printer.supportedDuplexModes.length > 1 | 209 | enabled: printing.isEditable && currentDocument.count > 1 && printing.printer.supportedDuplexModes.length > 1 |
494 | @@ -297,16 +323,22 @@ | |||
495 | 297 | right: parent.right | 323 | right: parent.right |
496 | 298 | rightMargin: units.gu(1) | 324 | rightMargin: units.gu(1) |
497 | 299 | } | 325 | } |
499 | 300 | canPrint: printing.isLoaded | 326 | canPrint: { |
500 | 327 | if (printing.pdfMode) { | ||
501 | 328 | printing.isLoaded | ||
502 | 329 | } else if (printing.printerJob.printRangeMode === PrinterEnum.PageRange) { | ||
503 | 330 | // If the page range is set, then check it is valid | ||
504 | 331 | printing.isLoaded && copiesSelector.acceptableInput && pageRangeTextField.validator.validValues | ||
505 | 332 | } else { | ||
506 | 333 | printing.isLoaded && copiesSelector.acceptableInput | ||
507 | 334 | } | ||
508 | 335 | } | ||
509 | 301 | objectName: "printRow" | 336 | objectName: "printRow" |
510 | 302 | pdfMode: printing.pdfMode | 337 | pdfMode: printing.pdfMode |
511 | 303 | // TODO: This should count the range not all pages | ||
512 | 304 | // roundUp((pageCount * copies) / duplex) | ||
513 | 305 | sheets: { | 338 | sheets: { |
516 | 306 | // If range is selected and a value exists, then set the sheets to zero | 339 | // If the page range is set then use it |
515 | 307 | // for now. Which results in not showing the number sheets | ||
517 | 308 | if (printing.printerJob.printRangeMode === PrinterEnum.PageRange && printing.printerJob.printRange.length > 0) { | 340 | if (printing.printerJob.printRangeMode === PrinterEnum.PageRange && printing.printerJob.printRange.length > 0) { |
519 | 309 | 0 | 341 | Math.ceil((pageRangeTextField.validator.count * printing.printerJob.copies) / (printing.printerJob.isTwoSided ? 2 : 1)) |
520 | 310 | } else { | 342 | } else { |
521 | 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)) |
522 | 312 | } | 344 | } |
523 | 313 | 345 | ||
524 | === modified file 'ubuntu-printing-app/tests/qmltests/tst_LabelRow.qml' | |||
525 | --- ubuntu-printing-app/tests/qmltests/tst_LabelRow.qml 2017-03-17 12:34:49 +0000 | |||
526 | +++ ubuntu-printing-app/tests/qmltests/tst_LabelRow.qml 2017-04-05 12:09:01 +0000 | |||
527 | @@ -36,11 +36,13 @@ | |||
528 | 36 | 36 | ||
529 | 37 | readonly property bool dataEnabled: true | 37 | readonly property bool dataEnabled: true |
530 | 38 | readonly property string dataPrimaryText: "Primary" | 38 | readonly property string dataPrimaryText: "Primary" |
531 | 39 | readonly property string dataSecondaryColor: "#ff0000" | ||
532 | 39 | readonly property string dataSecondaryText: "Secondary" | 40 | readonly property string dataSecondaryText: "Secondary" |
533 | 40 | 41 | ||
534 | 41 | function init() { | 42 | function init() { |
535 | 42 | labelRow.enabled = dataEnabled; | 43 | labelRow.enabled = dataEnabled; |
536 | 43 | labelRow.primaryText = dataPrimaryText; | 44 | labelRow.primaryText = dataPrimaryText; |
537 | 45 | labelRow.secondaryColor = dataSecondaryColor; | ||
538 | 44 | labelRow.secondaryText = dataSecondaryText; | 46 | labelRow.secondaryText = dataSecondaryText; |
539 | 45 | 47 | ||
540 | 46 | waitForRendering(labelRow); | 48 | waitForRendering(labelRow); |
541 | @@ -69,5 +71,11 @@ | |||
542 | 69 | var secondary = findChild(labelRow, "secondary"); | 71 | var secondary = findChild(labelRow, "secondary"); |
543 | 70 | compare(secondary.text, dataSecondaryText); | 72 | compare(secondary.text, dataSecondaryText); |
544 | 71 | } | 73 | } |
545 | 74 | |||
546 | 75 | function test_secondaryColor() { | ||
547 | 76 | // Check secondary color is correct | ||
548 | 77 | var secondary = findChild(labelRow, "secondary"); | ||
549 | 78 | compare(secondary.color, dataSecondaryColor); | ||
550 | 79 | } | ||
551 | 72 | } | 80 | } |
552 | 73 | } | 81 | } |
553 | 74 | 82 | ||
554 | === modified file 'ubuntu-printing-app/tests/qmltests/tst_PrintPage.qml' | |||
555 | --- ubuntu-printing-app/tests/qmltests/tst_PrintPage.qml 2017-03-21 17:57:19 +0000 | |||
556 | +++ ubuntu-printing-app/tests/qmltests/tst_PrintPage.qml 2017-04-05 12:09:01 +0000 | |||
557 | @@ -119,11 +119,15 @@ | |||
558 | 119 | 119 | ||
559 | 120 | mockPrinting.printerJob.collate = true; | 120 | mockPrinting.printerJob.collate = true; |
560 | 121 | mockPrinting.printerJob.copies = 1; | 121 | mockPrinting.printerJob.copies = 1; |
561 | 122 | mockPrinting.printerJob.isTwoSided = false; | ||
562 | 122 | mockPrinting.printerJob.printRangeMode = PrinterEnum.AllPages; | 123 | mockPrinting.printerJob.printRangeMode = PrinterEnum.AllPages; |
563 | 123 | mockPrinting.printerJob.reverse = false; | 124 | mockPrinting.printerJob.reverse = false; |
564 | 124 | 125 | ||
565 | 125 | mockPrinting.printerSelectedIndex = 0; | 126 | mockPrinting.printerSelectedIndex = 0; |
566 | 126 | 127 | ||
567 | 128 | var printRange = findChild(printPage, "pageRangeTextField"); | ||
568 | 129 | printRange.value = ""; | ||
569 | 130 | |||
570 | 127 | cancelSpy.clear(); | 131 | cancelSpy.clear(); |
571 | 128 | confirmSpy.clear(); | 132 | confirmSpy.clear(); |
572 | 129 | 133 | ||
573 | @@ -261,6 +265,24 @@ | |||
574 | 261 | compare(mockPrinting.printerJob.copies, 2); | 265 | compare(mockPrinting.printerJob.copies, 2); |
575 | 262 | } | 266 | } |
576 | 263 | 267 | ||
577 | 268 | function test_copiesKeyClickZero() { | ||
578 | 269 | // Check copies starting value is correct | ||
579 | 270 | var copies = findChild(printPage, "copiesTextField"); | ||
580 | 271 | compare(copies.value, "1"); | ||
581 | 272 | |||
582 | 273 | // Click on the textField | ||
583 | 274 | mouseClick(copies); | ||
584 | 275 | |||
585 | 276 | // Clear the current text and try to enter "01" | ||
586 | 277 | keyClick(Qt.Key_Backspace); | ||
587 | 278 | keyClick(Qt.Key_0); | ||
588 | 279 | keyClick(Qt.Key_1); | ||
589 | 280 | |||
590 | 281 | // Check that "1" is set to the backend | ||
591 | 282 | tryCompare(copies, "value", "1", timeout, "Copies value did not change"); | ||
592 | 283 | compare(mockPrinting.printerJob.copies, 1); | ||
593 | 284 | } | ||
594 | 285 | |||
595 | 264 | function test_duplex() { | 286 | function test_duplex() { |
596 | 265 | var duplex = findChild(printPage, "duplexSelector"); | 287 | var duplex = findChild(printPage, "duplexSelector"); |
597 | 266 | 288 | ||
598 | @@ -406,6 +428,73 @@ | |||
599 | 406 | } | 428 | } |
600 | 407 | } | 429 | } |
601 | 408 | 430 | ||
602 | 431 | function test_printRange() { | ||
603 | 432 | document.url = Qt.resolvedUrl("../resources/pdf/mixed_portrait.pdf"); | ||
604 | 433 | |||
605 | 434 | // Change to PageRange mode | ||
606 | 435 | mockPrinting.printerJob.printRangeMode = PrinterEnum.PageRange; | ||
607 | 436 | |||
608 | 437 | var printRange = findChild(printPage, "pageRangeTextField"); | ||
609 | 438 | var printRangeError = findChild(printPage, "pageRangeErrorStrLabel"); | ||
610 | 439 | var printRow = findChild(printPage, "printRow"); | ||
611 | 440 | |||
612 | 441 | // Test that a range sets printRange in printerJob | ||
613 | 442 | |||
614 | 443 | // Click on the textField | ||
615 | 444 | mouseClick(printRange); | ||
616 | 445 | |||
617 | 446 | // Clear the current text and enter "2" | ||
618 | 447 | keyClick(Qt.Key_Backspace); | ||
619 | 448 | keyClick(Qt.Key_2); | ||
620 | 449 | |||
621 | 450 | compare(mockPrinting.printerJob.printRange, "2"); | ||
622 | 451 | compare(printRangeError.visible, false); | ||
623 | 452 | compare(printRangeError.secondaryText, ""); | ||
624 | 453 | compare(printRow.canPrint, true); | ||
625 | 454 | |||
626 | 455 | |||
627 | 456 | // Test that a invalid range shows the error and disables button | ||
628 | 457 | |||
629 | 458 | // Click on the textField | ||
630 | 459 | mouseClick(printRange); | ||
631 | 460 | |||
632 | 461 | // Clear the current text and enter "," | ||
633 | 462 | keyClick(Qt.Key_Backspace); | ||
634 | 463 | keyClick(Qt.Key_Comma); | ||
635 | 464 | |||
636 | 465 | compare(printRangeError.visible, true); | ||
637 | 466 | compare(printRangeError.secondaryText, i18n.tr("No number given in range")); | ||
638 | 467 | compare(printRow.canPrint, false); | ||
639 | 468 | |||
640 | 469 | // Clear the current text and enter "0" | ||
641 | 470 | keyClick(Qt.Key_Backspace); | ||
642 | 471 | keyClick(Qt.Key_0); | ||
643 | 472 | |||
644 | 473 | compare(printRangeError.visible, true); | ||
645 | 474 | compare(printRangeError.secondaryText, i18n.tr("Page is less than one")); | ||
646 | 475 | compare(printRow.canPrint, false); | ||
647 | 476 | |||
648 | 477 | // Clear the current text and enter "10" | ||
649 | 478 | keyClick(Qt.Key_Backspace); | ||
650 | 479 | keyClick(Qt.Key_1); | ||
651 | 480 | keyClick(Qt.Key_0); | ||
652 | 481 | |||
653 | 482 | compare(printRangeError.visible, true); | ||
654 | 483 | compare(printRangeError.secondaryText, i18n.tr("Page is higher than document page count")); | ||
655 | 484 | compare(printRow.canPrint, false); | ||
656 | 485 | |||
657 | 486 | // Clear the current text and enter "2-1" | ||
658 | 487 | keyClick(Qt.Key_Backspace); | ||
659 | 488 | keyClick(Qt.Key_Backspace); | ||
660 | 489 | keyClick(Qt.Key_2); | ||
661 | 490 | keyClick(Qt.Key_Minus); | ||
662 | 491 | keyClick(Qt.Key_1); | ||
663 | 492 | |||
664 | 493 | compare(printRangeError.visible, true); | ||
665 | 494 | compare(printRangeError.secondaryText, i18n.tr("Page low is greater than high")); | ||
666 | 495 | compare(printRow.canPrint, false); | ||
667 | 496 | } | ||
668 | 497 | |||
669 | 409 | function test_printRangeMode() { | 498 | function test_printRangeMode() { |
670 | 410 | var printRangeMode = findChild(printPage, "pageRangeSelector"); | 499 | var printRangeMode = findChild(printPage, "pageRangeSelector"); |
671 | 411 | var printRange = findChild(printPage, "pageRangeTextField"); | 500 | var printRange = findChild(printPage, "pageRangeTextField"); |
672 | @@ -503,12 +592,70 @@ | |||
673 | 503 | mockPrinting.printerJob.isTwoSided = true; | 592 | mockPrinting.printerJob.isTwoSided = true; |
674 | 504 | 593 | ||
675 | 505 | compare(printRow.sheets, 2); | 594 | compare(printRow.sheets, 2); |
679 | 506 | 595 | } | |
680 | 507 | // Enable page ranges, this results in zero sheets | 596 | |
681 | 508 | mockPrinting.printerJob.printRange = "-3,5-7,9-"; | 597 | function test_sheets_range() { |
682 | 598 | var printRow = findChild(printPage, "printRow"); | ||
683 | 599 | var printRange = findChild(printPage, "pageRangeTextField"); | ||
684 | 600 | |||
685 | 601 | // has 3 pages | ||
686 | 602 | document.url = Qt.resolvedUrl("../resources/pdf/mixed_portrait.pdf"); | ||
687 | 603 | |||
688 | 604 | compare(document.count, 3); | ||
689 | 605 | compare(mockPrinting.printerJob.copies, 1); | ||
690 | 606 | compare(mockPrinting.printerJob.isTwoSided, false); | ||
691 | 607 | compare(printRow.sheets, 3); | ||
692 | 608 | |||
693 | 609 | // Set range to 1 check than sheets is correct | ||
694 | 509 | mockPrinting.printerJob.printRangeMode = PrinterEnum.PageRange; | 610 | mockPrinting.printerJob.printRangeMode = PrinterEnum.PageRange; |
697 | 510 | 611 | printRange.value = "1"; | |
698 | 511 | compare(printRow.sheets, 0); | 612 | |
699 | 613 | compare(printRow.sheets, 1); | ||
700 | 614 | |||
701 | 615 | // Enable twoSided, we should get 0.5 rounded to 1 sheet | ||
702 | 616 | mockPrinting.printerJob.isTwoSided = true; | ||
703 | 617 | |||
704 | 618 | compare(mockPrinting.printerJob.isTwoSided, true); | ||
705 | 619 | compare(printRow.sheets, 1); | ||
706 | 620 | |||
707 | 621 | // Enable two copies, we should get 2 copies with duplex, so 1 sheet | ||
708 | 622 | mockPrinting.printerJob.copies = 2; | ||
709 | 623 | |||
710 | 624 | compare(mockPrinting.printerJob.copies, 2); | ||
711 | 625 | compare(printRow.sheets, 1); | ||
712 | 626 | |||
713 | 627 | // Disable two sided, so 2 copies and 2 sheets | ||
714 | 628 | mockPrinting.printerJob.isTwoSided = false; | ||
715 | 629 | |||
716 | 630 | compare(mockPrinting.printerJob.isTwoSided, false); | ||
717 | 631 | compare(printRow.sheets, 2); | ||
718 | 632 | |||
719 | 633 | |||
720 | 634 | // Set the range to 2 sheets | ||
721 | 635 | printRange.value = "1,2"; | ||
722 | 636 | |||
723 | 637 | mockPrinting.printerJob.copies = 1; | ||
724 | 638 | mockPrinting.printerJob.isTwoSided = false; | ||
725 | 639 | |||
726 | 640 | compare(printRow.sheets, 2); | ||
727 | 641 | |||
728 | 642 | // Enable twoSided, we should get 2 pages on 1 sheet | ||
729 | 643 | mockPrinting.printerJob.isTwoSided = true; | ||
730 | 644 | |||
731 | 645 | compare(mockPrinting.printerJob.isTwoSided, true); | ||
732 | 646 | compare(printRow.sheets, 1); | ||
733 | 647 | |||
734 | 648 | // Enable two copies, we should get 2 copies with duplex, so 2 sheet | ||
735 | 649 | mockPrinting.printerJob.copies = 2; | ||
736 | 650 | |||
737 | 651 | compare(mockPrinting.printerJob.copies, 2); | ||
738 | 652 | compare(printRow.sheets, 2); | ||
739 | 653 | |||
740 | 654 | // Disable two sided, so 2 copies and 4 sheets | ||
741 | 655 | mockPrinting.printerJob.isTwoSided = false; | ||
742 | 656 | |||
743 | 657 | compare(mockPrinting.printerJob.isTwoSided, false); | ||
744 | 658 | compare(printRow.sheets, 4); | ||
745 | 512 | } | 659 | } |
746 | 513 | } | 660 | } |
747 | 514 | } | 661 | } |
748 | 515 | 662 | ||
749 | === modified file 'ubuntu-printing-app/tests/unittests/backend/CMakeLists.txt' | |||
750 | --- ubuntu-printing-app/tests/unittests/backend/CMakeLists.txt 2017-03-15 11:57:40 +0000 | |||
751 | +++ ubuntu-printing-app/tests/unittests/backend/CMakeLists.txt 2017-04-05 12:09:01 +0000 | |||
752 | @@ -14,6 +14,10 @@ | |||
753 | 14 | target_link_libraries(testPageHelper UbuntuPrintingAppbackend Qt5::Test Qt5::Gui) | 14 | target_link_libraries(testPageHelper UbuntuPrintingAppbackend Qt5::Test Qt5::Gui) |
754 | 15 | add_test(tst_pagehelper testPageHelper) | 15 | add_test(tst_pagehelper testPageHelper) |
755 | 16 | 16 | ||
756 | 17 | add_executable(testPageRangeValidator tst_pagerangevalidator.cpp ${PDF_TEST_FILES}) | ||
757 | 18 | target_link_libraries(testPageRangeValidator UbuntuPrintingAppbackend Qt5::Test Qt5::Gui) | ||
758 | 19 | add_test(tst_pagerangevalidator testPageRangeValidator) | ||
759 | 20 | |||
760 | 17 | add_executable(testPopplerImageProvider tst_popplerimageprovider.cpp ${PDF_TEST_FILES}) | 21 | add_executable(testPopplerImageProvider tst_popplerimageprovider.cpp ${PDF_TEST_FILES}) |
761 | 18 | target_link_libraries(testPopplerImageProvider UbuntuPrintingAppbackend Qt5::Test Qt5::Gui) | 22 | target_link_libraries(testPopplerImageProvider UbuntuPrintingAppbackend Qt5::Test Qt5::Gui) |
762 | 19 | add_test(tst_popplerimageprovider testPopplerImageProvider) | 23 | add_test(tst_popplerimageprovider testPopplerImageProvider) |
763 | 20 | 24 | ||
764 | === added file 'ubuntu-printing-app/tests/unittests/backend/tst_pagerangevalidator.cpp' | |||
765 | --- ubuntu-printing-app/tests/unittests/backend/tst_pagerangevalidator.cpp 1970-01-01 00:00:00 +0000 | |||
766 | +++ ubuntu-printing-app/tests/unittests/backend/tst_pagerangevalidator.cpp 2017-04-05 12:09:01 +0000 | |||
767 | @@ -0,0 +1,151 @@ | |||
768 | 1 | /* | ||
769 | 2 | * Copyright 2017 Canonical Ltd. | ||
770 | 3 | * | ||
771 | 4 | * This file is part of ubuntu-printing-app. | ||
772 | 5 | * | ||
773 | 6 | * ubuntu-printing-app is free software; you can redistribute it and/or modify | ||
774 | 7 | * it under the terms of the GNU General Public License as published by | ||
775 | 8 | * the Free Software Foundation; version 3. | ||
776 | 9 | * | ||
777 | 10 | * ubuntu-printing-app is distributed in the hope that it will be useful, | ||
778 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
779 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
780 | 13 | * GNU General Public License for more details. | ||
781 | 14 | * | ||
782 | 15 | * You should have received a copy of the GNU General Public License | ||
783 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
784 | 17 | * | ||
785 | 18 | * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com> | ||
786 | 19 | */ | ||
787 | 20 | |||
788 | 21 | #include <QObject> | ||
789 | 22 | #include <QSignalSpy> | ||
790 | 23 | #include <QTest> | ||
791 | 24 | |||
792 | 25 | #include "UbuntuPrintingApp/pagerangevalidator.h" | ||
793 | 26 | |||
794 | 27 | class TestPageRangeValidator : public QObject | ||
795 | 28 | { | ||
796 | 29 | Q_OBJECT | ||
797 | 30 | private Q_SLOTS: | ||
798 | 31 | void init() | ||
799 | 32 | { | ||
800 | 33 | m_validator = new PageRangeValidator(); | ||
801 | 34 | } | ||
802 | 35 | void cleanup() | ||
803 | 36 | { | ||
804 | 37 | QSignalSpy destroyedSpy(m_validator, SIGNAL(destroyed(QObject*))); | ||
805 | 38 | m_validator->deleteLater(); | ||
806 | 39 | QTRY_COMPARE(destroyedSpy.count(), 1); | ||
807 | 40 | } | ||
808 | 41 | |||
809 | 42 | // Check that the initial values are correct | ||
810 | 43 | void testInit() | ||
811 | 44 | { | ||
812 | 45 | QCOMPARE(m_validator->count(), 0); | ||
813 | 46 | QCOMPARE(m_validator->documentCount(), 0); | ||
814 | 47 | QCOMPARE(m_validator->error(), PageRangeValidator::PageRangeError::NoError); | ||
815 | 48 | QCOMPARE(m_validator->pages(), QStringLiteral("")); | ||
816 | 49 | } | ||
817 | 50 | |||
818 | 51 | // Check that the document count can be set | ||
819 | 52 | void testDocumentCount() | ||
820 | 53 | { | ||
821 | 54 | QSignalSpy documentCountSpy(m_validator, SIGNAL(documentCountChanged(int))); | ||
822 | 55 | m_validator->setDocumentCount(10); | ||
823 | 56 | |||
824 | 57 | QTRY_COMPARE(documentCountSpy.count(), 1); | ||
825 | 58 | QCOMPARE(m_validator->documentCount(), 10); | ||
826 | 59 | } | ||
827 | 60 | |||
828 | 61 | void testValidate_data() | ||
829 | 62 | { | ||
830 | 63 | QTest::addColumn<QString>("input"); | ||
831 | 64 | QTest::addColumn<bool>("result"); | ||
832 | 65 | |||
833 | 66 | // Good values | ||
834 | 67 | QTest::newRow("empty") << "" << true; | ||
835 | 68 | QTest::newRow("single value") << "2" << true; | ||
836 | 69 | QTest::newRow("multiple values") << "2,3,4" << true; | ||
837 | 70 | QTest::newRow("no lower") << "-2" << true; | ||
838 | 71 | QTest::newRow("no upper") << "2-" << true; | ||
839 | 72 | QTest::newRow("single range") << "2-3" << true; | ||
840 | 73 | QTest::newRow("range and value") << "2-3,6" << true; | ||
841 | 74 | QTest::newRow("multiple ranges") << "2-3,6-7" << true; | ||
842 | 75 | QTest::newRow("overlapping ranges") << "2-8,6-10" << true; | ||
843 | 76 | QTest::newRow("dash") << "-" << true; | ||
844 | 77 | QTest::newRow("comma") << "," << true; | ||
845 | 78 | QTest::newRow("double comma") << ",," << true; | ||
846 | 79 | |||
847 | 80 | // Bad values | ||
848 | 81 | QTest::newRow("no comma multi range") << "1-2-3" << false; | ||
849 | 82 | QTest::newRow("double dash") << "--" << false; | ||
850 | 83 | QTest::newRow("double dash range") << "2--3" << false; | ||
851 | 84 | QTest::newRow("letter") << "a" << false; | ||
852 | 85 | } | ||
853 | 86 | |||
854 | 87 | void testValidate() | ||
855 | 88 | { | ||
856 | 89 | QFETCH(QString, input); | ||
857 | 90 | QFETCH(bool, result); | ||
858 | 91 | |||
859 | 92 | int pos = 0; | ||
860 | 93 | |||
861 | 94 | QCOMPARE(m_validator->validate(input, pos), result ? QValidator::State::Acceptable : QValidator::State::Invalid); | ||
862 | 95 | } | ||
863 | 96 | |||
864 | 97 | void testValidateValues_data() | ||
865 | 98 | { | ||
866 | 99 | QTest::addColumn<QString>("input"); | ||
867 | 100 | QTest::addColumn<bool>("result"); | ||
868 | 101 | QTest::addColumn<int>("count"); | ||
869 | 102 | QTest::addColumn<QString>("pages"); | ||
870 | 103 | QTest::addColumn<PageRangeValidator::PageRangeError>("error"); | ||
871 | 104 | |||
872 | 105 | // Good values | ||
873 | 106 | QTest::newRow("empty") << "" << true << 10 << "" << PageRangeValidator::NoError; | ||
874 | 107 | QTest::newRow("single value") << "2" << true << 1 << "2" << PageRangeValidator::NoError; | ||
875 | 108 | QTest::newRow("multiple values") << "2,3,4" << true << 3 << "2,3,4" << PageRangeValidator::NoError; | ||
876 | 109 | QTest::newRow("multiple values sort") << "4,3,2" << true << 3 << "2,3,4" << PageRangeValidator::NoError; | ||
877 | 110 | QTest::newRow("no lower") << "-5" << true << 5 << "1,2,3,4,5" << PageRangeValidator::NoError; | ||
878 | 111 | QTest::newRow("no upper") << "5-" << true << 6 << "5,6,7,8,9,10" << PageRangeValidator::NoError; | ||
879 | 112 | QTest::newRow("single range") << "2-3" << true << 2 << "2,3" << PageRangeValidator::NoError; | ||
880 | 113 | QTest::newRow("range and value") << "2-3,6" << true << 3 << "2,3,6" << PageRangeValidator::NoError; | ||
881 | 114 | QTest::newRow("multiple ranges") << "2-3,6-7" << true << 4 << "2,3,6,7" << PageRangeValidator::NoError; | ||
882 | 115 | QTest::newRow("overlapping ranges") << "2-5,3-6" << true << 5 << "2,3,4,5,6" << PageRangeValidator::NoError; | ||
883 | 116 | |||
884 | 117 | // Values that pass validate() but fail range checks | ||
885 | 118 | QTest::newRow("dash") << "-" << false << 0 << "" << PageRangeValidator::NoPageInRange; | ||
886 | 119 | QTest::newRow("comma") << "," << false << 0 << "" << PageRangeValidator::NoPageInRange; | ||
887 | 120 | QTest::newRow("double comma") << ",," << false << 0 << "" << PageRangeValidator::NoPageInRange; | ||
888 | 121 | |||
889 | 122 | // Values that fail range checks | ||
890 | 123 | QTest::newRow("low less than 1") << "0-" << false << 0 << "" << PageRangeValidator::PageLessThanOne; | ||
891 | 124 | QTest::newRow("high less than 1") << "-0" << false << 0 << "" << PageRangeValidator::PageLessThanOne; | ||
892 | 125 | QTest::newRow("low higher than doc count") << "50-" << false << 0 << "" << PageRangeValidator::PageHigherThanDocument; | ||
893 | 126 | QTest::newRow("high higher than doc count") << "-50" << false << 0 << "" << PageRangeValidator::PageHigherThanDocument; | ||
894 | 127 | QTest::newRow("low higher than high") << "5-3" << false << 0 << "" << PageRangeValidator::PageLowGreaterThanHigh; | ||
895 | 128 | } | ||
896 | 129 | |||
897 | 130 | void testValidateValues() | ||
898 | 131 | { | ||
899 | 132 | QFETCH(QString, input); | ||
900 | 133 | QFETCH(bool, result); | ||
901 | 134 | QFETCH(int, count); | ||
902 | 135 | QFETCH(QString, pages); | ||
903 | 136 | QFETCH(PageRangeValidator::PageRangeError, error); | ||
904 | 137 | |||
905 | 138 | m_validator->setDocumentCount(10); | ||
906 | 139 | |||
907 | 140 | QCOMPARE(m_validator->validateValues(input), result); | ||
908 | 141 | QCOMPARE(m_validator->count(), count); | ||
909 | 142 | QCOMPARE(m_validator->pages(), pages); | ||
910 | 143 | QCOMPARE(m_validator->error(), error); | ||
911 | 144 | } | ||
912 | 145 | |||
913 | 146 | private: | ||
914 | 147 | PageRangeValidator *m_validator; | ||
915 | 148 | }; | ||
916 | 149 | |||
917 | 150 | QTEST_GUILESS_MAIN(TestPageRangeValidator) | ||
918 | 151 | #include "tst_pagerangevalidator.moc" |
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.