Merge lp:ubuntu-ui-extras/staging into lp:ubuntu-ui-extras
- staging
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Andrew Hayzen |
Approved revision: | no longer in the source branch. |
Merged at revision: | 131 |
Proposed branch: | lp:ubuntu-ui-extras/staging |
Merge into: | lp:ubuntu-ui-extras |
Diff against target: |
6506 lines (+3970/-590) 46 files modified
debian/changelog (+67/-0) modules/Ubuntu/Components/Extras/Example/PrinterQueue.qml (+0/-117) modules/Ubuntu/Components/Extras/Example/Printers.qml (+232/-75) modules/Ubuntu/Components/Extras/Printers/CMakeLists.txt (+4/-1) modules/Ubuntu/Components/Extras/Printers/backend/backend.cpp (+48/-0) modules/Ubuntu/Components/Extras/Printers/backend/backend.h (+13/-0) modules/Ubuntu/Components/Extras/Printers/backend/backend_cups.cpp (+225/-44) modules/Ubuntu/Components/Extras/Printers/backend/backend_cups.h (+25/-1) modules/Ubuntu/Components/Extras/Printers/backend/backend_pdf.cpp (+10/-0) modules/Ubuntu/Components/Extras/Printers/cups/devicesearcher.cpp (+70/-0) modules/Ubuntu/Components/Extras/Printers/cups/devicesearcher.h (+57/-0) modules/Ubuntu/Components/Extras/Printers/cups/ippclient.cpp (+163/-9) modules/Ubuntu/Components/Extras/Printers/cups/ippclient.h (+13/-1) modules/Ubuntu/Components/Extras/Printers/cups/jobloader.cpp (+50/-0) modules/Ubuntu/Components/Extras/Printers/cups/jobloader.h (+47/-0) modules/Ubuntu/Components/Extras/Printers/cups/printerloader.cpp (+3/-0) modules/Ubuntu/Components/Extras/Printers/enums.h (+23/-0) modules/Ubuntu/Components/Extras/Printers/models/devicemodel.cpp (+149/-0) modules/Ubuntu/Components/Extras/Printers/models/devicemodel.h (+78/-0) modules/Ubuntu/Components/Extras/Printers/models/jobmodel.cpp (+267/-126) modules/Ubuntu/Components/Extras/Printers/models/jobmodel.h (+53/-11) modules/Ubuntu/Components/Extras/Printers/models/printermodel.cpp (+70/-30) modules/Ubuntu/Components/Extras/Printers/models/printermodel.h (+13/-4) modules/Ubuntu/Components/Extras/Printers/plugin.cpp (+2/-0) modules/Ubuntu/Components/Extras/Printers/printer/printer.cpp (+150/-24) modules/Ubuntu/Components/Extras/Printers/printer/printer.h (+29/-3) modules/Ubuntu/Components/Extras/Printers/printer/printerjob.cpp (+108/-60) modules/Ubuntu/Components/Extras/Printers/printer/printerjob.h (+14/-11) modules/Ubuntu/Components/Extras/Printers/printer/signalratelimiter.cpp (+28/-6) modules/Ubuntu/Components/Extras/Printers/printer/signalratelimiter.h (+8/-6) modules/Ubuntu/Components/Extras/Printers/printers/printers.cpp (+152/-7) modules/Ubuntu/Components/Extras/Printers/printers/printers.h (+20/-0) modules/Ubuntu/Components/Extras/Printers/structs.h (+84/-0) po/ubuntu-ui-extras.pot (+26/-2) tests/unittests/Printers/CMakeLists.txt (+13/-3) tests/unittests/Printers/mockbackend.h (+127/-4) tests/unittests/Printers/tst_jobfilter.cpp (+4/-2) tests/unittests/Printers/tst_jobmodel.cpp (+446/-29) tests/unittests/Printers/tst_printer.cpp (+96/-0) tests/unittests/Printers/tst_printerdevice.cpp (+131/-0) tests/unittests/Printers/tst_printerdevicemodel.cpp (+162/-0) tests/unittests/Printers/tst_printerfilter.cpp (+30/-0) tests/unittests/Printers/tst_printerjob.cpp (+53/-0) tests/unittests/Printers/tst_printermodel.cpp (+489/-1) tests/unittests/Printers/tst_printers.cpp (+92/-7) tests/unittests/Printers/tst_signalratelimiter.cpp (+26/-6) |
To merge this branch: | bzr merge lp:ubuntu-ui-extras/staging |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andrew Hayzen (community) | Approve | ||
Jonas G. Drange (community) | Approve | ||
Review via email: mp+320797@code.launchpad.net |
Commit message
Description of the change
Please see the changelog entry for details.
Testing:
1. Build it
2. qmlscene -I <path/to/
3. Add a printer
4. Explore configured printers
5. Change configured printers
Andrew Hayzen (ahayzen) wrote : | # |
I approve all the changes made by Jonas, which is this whole branch minus my own changes.
- 131. By CI Train Bot Account
-
* Adds devices as an model on Printers, and re-instates remote printer model on Printers.
* makes sure the backend is refreshed on enable/disable
* If printerAdded is called ensure there is always a proxy printer
corrects thread affinity for printerloaded printers, as well as any qobject children it might have
* Remove PrinterQueue.qml example and add missing job methods to Printers.qml example, so we have only one example
* improves the deviceName by dropping the CMD (note that the full string remains accessible from device.id)
* Connect job-impressions-completed from cups to PrinterJob: :impressionsCom pleted( )
* In the job model listen to printerStateChanged as changes t job-impressions-completed causes that signal
* Improve the PrinterSignalHandler to limit the maximum wait time of unprocessed signals to four times the timeout
* Add unit test for SignalRateLimiter to check it does perform a flush
* Rename PrinterSignalHandler to SignalRateLimiter
* Add a JobLoader for loading a specific jobId for a printer and loading the extended attributes
* Move the loading of creationTime, completedTime, processingTime, size and user to extended attributes as signals don't give us those
* Add method for PrinterBackend for getting a specific job
* Split up JobModel::update so there is jobCreated, jobState and jobCompleted which then call addJob, removeJob and updateJob
* Improve Printer::updateFrom to not call loadAttributes as this results in a possible UI block
* Add missing comparisions for PrinterJob deepCompare and updateFrom
* Change PrinterJob::setPrinter to not call loadDefaults and instead explicitly call it
* Change Printers to trigger requestJobExtendedAttributes which triggers a background thread rather than doing in foreground
* exposes copies attribute on the printer
* includes cups/adminutils.h into which the cups device callback was moved in >= libcups2-dev 2.2.2
* allows browsing on local and remote printers
* Add filters for active, paused and queued
* Add sorting by creationTime and then falling back to id
* Change time related roles in JobModel to return QDateTime, not QString, so sorting doesn't break
* Update tests
* Change printerGetJobAttributes to use printer-uri and job-id (the same as holdJob and releaseJob
* Give printerGetJobAttributes printerName so we can ensure we get the correct job
* adds read/write of the shared property
* adds extended attribute fetching (IppClient::printerGetAttr ibutes)
* refactors attribute retrieval from cups
* implements deviceUri and lastMessage on Printer
* adds Printers.printTestPage
* Add tests for JobModel roles
* Add tests for make and location in Printer
* Fix JobModel color and quality roles to use fallback if no text
* Add tests for all roles in PrinterModel
* Remove PdfRole it is not used (IsPdfRole instead)
* Add holdJob and releaseJob methods to Printers
* Add HeldRole to JobModel
* Add tests for hold and releasing a job
* Update example to show how hold and release work
* Update StateRole to return just the state, not text
* Remove PrinterJob friends and make setters public as they aren't exposed to QML anyway
* adds make and location to printermodel and printer
* Pull of trunk
* Remove use of bitewise or as it fails in CI
* guards against excessive loading of printers and drivers
* adds loadPrinter method on Printers
* drops a lot of code that was not used, and some TODOS/FIXMES that aren't necessary
* Fix/add commented or empty tests
* Implement tests that had QSKIP
* removes empty brackets
* adds cmake extras, required by printer stuff
* Remove remaining fixme's
* Rename UbuntuSettingsComponentsPrinte rsPlugin to UbuntuComponent sExtrasPrinters Plugin
* Remove import Ubuntu.Settings. Components 0.1 from example qml imports
* Rename definition UBUNTUSETTINGSPRINTERS_ LIBRARY to UBUNTUCOMPONENT SEXTRASPRINTERS _LIBRARY
* Rename UbuntuSettingsPrintersQml to UbuntuComponent sExtrasPrinters Qml
* Rename translation domain to ubuntu-ui-extras
* Fix for printsupport being build-depends rather than depends
Preview Diff
1 | === modified file 'debian/changelog' | |||
2 | --- debian/changelog 2017-03-01 22:24:08 +0000 | |||
3 | +++ debian/changelog 2017-03-23 12:51:36 +0000 | |||
4 | @@ -1,3 +1,70 @@ | |||
5 | 1 | ubuntu-ui-extras (0.3+17.04.20170301.2-0ubuntu2) UNRELEASED; urgency=medium | ||
6 | 2 | |||
7 | 3 | [ Andrew Hayzen, Jonas G. Drange ] | ||
8 | 4 | * Adds devices as an model on Printers, and re-instates remote printer model on Printers. | ||
9 | 5 | * makes sure the backend is refreshed on enable/disable | ||
10 | 6 | * If printerAdded is called ensure there is always a proxy printer | ||
11 | 7 | corrects thread affinity for printerloaded printers, as well as any qobject children it might have | ||
12 | 8 | * Remove PrinterQueue.qml example and add missing job methods to Printers.qml example, so we have only one example | ||
13 | 9 | * improves the deviceName by dropping the CMD (note that the full string remains accessible from device.id) | ||
14 | 10 | * Connect job-impressions-completed from cups to PrinterJob::impressionsCompleted() | ||
15 | 11 | * In the job model listen to printerStateChanged as changes t job-impressions-completed causes that signal | ||
16 | 12 | * Improve the PrinterSignalHandler to limit the maximum wait time of unprocessed signals to four times the timeout | ||
17 | 13 | * Add unit test for SignalRateLimiter to check it does perform a flush | ||
18 | 14 | * Rename PrinterSignalHandler to SignalRateLimiter | ||
19 | 15 | * Add a JobLoader for loading a specific jobId for a printer and loading the extended attributes | ||
20 | 16 | * Move the loading of creationTime, completedTime, processingTime, size and user to extended attributes as signals don't give us those | ||
21 | 17 | * Add method for PrinterBackend for getting a specific job | ||
22 | 18 | * Split up JobModel::update so there is jobCreated, jobState and jobCompleted which then call addJob, removeJob and updateJob | ||
23 | 19 | * Improve Printer::updateFrom to not call loadAttributes as this results in a possible UI block | ||
24 | 20 | * Add missing comparisions for PrinterJob deepCompare and updateFrom | ||
25 | 21 | * Change PrinterJob::setPrinter to not call loadDefaults and instead explicitly call it | ||
26 | 22 | * Change Printers to trigger requestJobExtendedAttributes which triggers a background thread rather than doing in foreground | ||
27 | 23 | * exposes copies attribute on the printer | ||
28 | 24 | * includes cups/adminutils.h into which the cups device callback was moved in >= libcups2-dev 2.2.2 | ||
29 | 25 | * allows browsing on local and remote printers | ||
30 | 26 | * Add filters for active, paused and queued | ||
31 | 27 | * Add sorting by creationTime and then falling back to id | ||
32 | 28 | * Change time related roles in JobModel to return QDateTime, not QString, so sorting doesn't break | ||
33 | 29 | * Update tests | ||
34 | 30 | * Change printerGetJobAttributes to use printer-uri and job-id (the same as holdJob and releaseJob | ||
35 | 31 | * Give printerGetJobAttributes printerName so we can ensure we get the correct job | ||
36 | 32 | * adds read/write of the shared property | ||
37 | 33 | * adds extended attribute fetching (IppClient::printerGetAttributes) | ||
38 | 34 | * refactors attribute retrieval from cups | ||
39 | 35 | * implements deviceUri and lastMessage on Printer | ||
40 | 36 | * adds Printers.printTestPage | ||
41 | 37 | * Add tests for JobModel roles | ||
42 | 38 | * Add tests for make and location in Printer | ||
43 | 39 | * Fix JobModel color and quality roles to use fallback if no text | ||
44 | 40 | * Add tests for all roles in PrinterModel | ||
45 | 41 | * Remove PdfRole it is not used (IsPdfRole instead) | ||
46 | 42 | * Add holdJob and releaseJob methods to Printers | ||
47 | 43 | * Add HeldRole to JobModel | ||
48 | 44 | * Add tests for hold and releasing a job | ||
49 | 45 | * Update example to show how hold and release work | ||
50 | 46 | * Update StateRole to return just the state, not text | ||
51 | 47 | * Remove PrinterJob friends and make setters public as they aren't exposed to QML anyway | ||
52 | 48 | * adds make and location to printermodel and printer | ||
53 | 49 | * Pull of trunk | ||
54 | 50 | * Remove use of bitewise or as it fails in CI | ||
55 | 51 | * guards against excessive loading of printers and drivers | ||
56 | 52 | * adds loadPrinter method on Printers | ||
57 | 53 | * drops a lot of code that was not used, and some TODOS/FIXMES that aren't necessary | ||
58 | 54 | * Fix/add commented or empty tests | ||
59 | 55 | * Implement tests that had QSKIP | ||
60 | 56 | * removes empty brackets | ||
61 | 57 | * adds cmake extras, required by printer stuff | ||
62 | 58 | * Remove remaining fixme's | ||
63 | 59 | * Rename UbuntuSettingsComponentsPrintersPlugin to UbuntuComponentsExtrasPrintersPlugin | ||
64 | 60 | * Remove import Ubuntu.Settings.Components 0.1 from example qml imports | ||
65 | 61 | * Rename definition UBUNTUSETTINGSPRINTERS_LIBRARY to UBUNTUCOMPONENTSEXTRASPRINTERS_LIBRARY | ||
66 | 62 | * Rename UbuntuSettingsPrintersQml to UbuntuComponentsExtrasPrintersQml | ||
67 | 63 | * Rename translation domain to ubuntu-ui-extras | ||
68 | 64 | * Fix for printsupport being build-depends rather than depends | ||
69 | 65 | |||
70 | 66 | -- Jonas G. Drange <jonas.drange@canonical.com> Mon, 20 Mar 2017 21:04:05 +0100 | ||
71 | 67 | |||
72 | 1 | ubuntu-ui-extras (0.2+17.04.20170301.2-0ubuntu1) zesty; urgency=medium | 68 | ubuntu-ui-extras (0.2+17.04.20170301.2-0ubuntu1) zesty; urgency=medium |
73 | 2 | 69 | ||
74 | 3 | [ Andrew Hayzen, Jonas G. Drange ] | 70 | [ Andrew Hayzen, Jonas G. Drange ] |
75 | 4 | 71 | ||
76 | === removed file 'modules/Ubuntu/Components/Extras/Example/PrinterQueue.qml' | |||
77 | --- modules/Ubuntu/Components/Extras/Example/PrinterQueue.qml 2017-02-21 11:31:44 +0000 | |||
78 | +++ modules/Ubuntu/Components/Extras/Example/PrinterQueue.qml 1970-01-01 00:00:00 +0000 | |||
79 | @@ -1,117 +0,0 @@ | |||
80 | 1 | /* | ||
81 | 2 | * Copyright 2017 Canonical Ltd. | ||
82 | 3 | * | ||
83 | 4 | * This program is free software; you can redistribute it and/or modify | ||
84 | 5 | * it under the terms of the GNU Lesser General Public License as published by | ||
85 | 6 | * the Free Software Foundation; version 3. | ||
86 | 7 | * | ||
87 | 8 | * This program is distributed in the hope that it will be useful, | ||
88 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
89 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
90 | 11 | * GNU Lesser General Public License for more details. | ||
91 | 12 | * | ||
92 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
93 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
94 | 15 | * | ||
95 | 16 | * Authored by Jonas G. Drange <jonas.drange@canonical.com> | ||
96 | 17 | * Andrew Hayzen <andrew.hayzen@canonical.com> | ||
97 | 18 | */ | ||
98 | 19 | |||
99 | 20 | import QtQuick 2.4 | ||
100 | 21 | import QtQuick.Layouts 1.1 | ||
101 | 22 | import Ubuntu.Components 1.3 | ||
102 | 23 | import Ubuntu.Components.ListItems 1.3 as ListItems | ||
103 | 24 | import Ubuntu.Components.Extras.Printers 0.1 | ||
104 | 25 | |||
105 | 26 | MainView { | ||
106 | 27 | width: units.gu(50) | ||
107 | 28 | height: units.gu(90) | ||
108 | 29 | |||
109 | 30 | Component { | ||
110 | 31 | id: queuePage | ||
111 | 32 | |||
112 | 33 | Page { | ||
113 | 34 | header: PageHeader { | ||
114 | 35 | title: "Queue: " + printer.name | ||
115 | 36 | flickable: queueView | ||
116 | 37 | } | ||
117 | 38 | visible: false | ||
118 | 39 | |||
119 | 40 | property var printer | ||
120 | 41 | |||
121 | 42 | ListView { | ||
122 | 43 | id: queueView | ||
123 | 44 | anchors { | ||
124 | 45 | fill: parent | ||
125 | 46 | } | ||
126 | 47 | delegate: ListItem { | ||
127 | 48 | height: modelLayout.height + (divider.visible ? divider.height : 0) | ||
128 | 49 | ListItemLayout { | ||
129 | 50 | id: modelLayout | ||
130 | 51 | title.text: displayName | ||
131 | 52 | subtitle.text: "Job: " + model.id + " State: " + model.state | ||
132 | 53 | + " Color: " + model.colorModel + " CreationTime: " | ||
133 | 54 | + model.creationTime + " PageRange: " | ||
134 | 55 | + model.printRange + " Messages: " + model.messages; | ||
135 | 56 | subtitle.wrapMode: Text.WrapAtWordBoundaryOrAnywhere | ||
136 | 57 | subtitle.maximumLineCount: 3 | ||
137 | 58 | } | ||
138 | 59 | onClicked: { | ||
139 | 60 | console.debug("Cancel:", printer.name, model.id); | ||
140 | 61 | Printers.cancelJob(printer.name, model.id); | ||
141 | 62 | } | ||
142 | 63 | } | ||
143 | 64 | model: printer.jobs | ||
144 | 65 | |||
145 | 66 | Label { | ||
146 | 67 | anchors { | ||
147 | 68 | centerIn: parent | ||
148 | 69 | } | ||
149 | 70 | text: "Empty queue" | ||
150 | 71 | visible: queueView.count === 0 | ||
151 | 72 | } | ||
152 | 73 | } | ||
153 | 74 | } | ||
154 | 75 | } | ||
155 | 76 | |||
156 | 77 | PageStack { | ||
157 | 78 | id: pageStack | ||
158 | 79 | |||
159 | 80 | Page { | ||
160 | 81 | id: printersPage | ||
161 | 82 | header: PageHeader { | ||
162 | 83 | title: "Printers" | ||
163 | 84 | flickable: printerList | ||
164 | 85 | } | ||
165 | 86 | visible: false | ||
166 | 87 | |||
167 | 88 | ListView { | ||
168 | 89 | id: printerList | ||
169 | 90 | anchors { fill: parent } | ||
170 | 91 | model: Printers.allPrintersWithPdf | ||
171 | 92 | delegate: ListItem { | ||
172 | 93 | height: modelLayout.height + (divider.visible ? divider.height : 0) | ||
173 | 94 | ListItemLayout { | ||
174 | 95 | id: modelLayout | ||
175 | 96 | title.text: displayName | ||
176 | 97 | title.font.bold: model.default | ||
177 | 98 | subtitle.text: description | ||
178 | 99 | |||
179 | 100 | Icon { | ||
180 | 101 | id: icon | ||
181 | 102 | width: height | ||
182 | 103 | height: units.gu(2.5) | ||
183 | 104 | name: "printer-symbolic" | ||
184 | 105 | SlotsLayout.position: SlotsLayout.First | ||
185 | 106 | } | ||
186 | 107 | |||
187 | 108 | ProgressionSlot {} | ||
188 | 109 | } | ||
189 | 110 | onClicked: pageStack.push(queuePage, { printer: model }) | ||
190 | 111 | } | ||
191 | 112 | } | ||
192 | 113 | } | ||
193 | 114 | |||
194 | 115 | Component.onCompleted: push(printersPage) | ||
195 | 116 | } | ||
196 | 117 | } | ||
197 | 118 | 0 | ||
198 | === modified file 'modules/Ubuntu/Components/Extras/Example/Printers.qml' | |||
199 | --- modules/Ubuntu/Components/Extras/Example/Printers.qml 2017-02-21 11:31:44 +0000 | |||
200 | +++ modules/Ubuntu/Components/Extras/Example/Printers.qml 2017-03-23 12:51:36 +0000 | |||
201 | @@ -51,17 +51,17 @@ | |||
202 | 51 | } | 51 | } |
203 | 52 | } | 52 | } |
204 | 53 | 53 | ||
205 | 54 | Component.onCompleted: { | ||
206 | 55 | printer.description; | ||
207 | 56 | } | ||
208 | 57 | |||
209 | 58 | Flickable { | 54 | Flickable { |
210 | 59 | id: printerFlickable | 55 | id: printerFlickable |
211 | 60 | anchors.fill: parent | 56 | anchors.fill: parent |
213 | 61 | 57 | contentHeight: contentItem.childrenRect.height | |
214 | 62 | Loader { | 58 | Loader { |
215 | 63 | id: printerPageBitsLoader | 59 | id: printerPageBitsLoader |
217 | 64 | anchors.fill: parent | 60 | anchors { |
218 | 61 | left: parent.left | ||
219 | 62 | right: parent.right | ||
220 | 63 | } | ||
221 | 64 | |||
222 | 65 | sourceComponent: printer.isLoaded ? printerPageLoaded : printerPageNotYetLoaded | 65 | sourceComponent: printer.isLoaded ? printerPageLoaded : printerPageNotYetLoaded |
223 | 66 | } | 66 | } |
224 | 67 | } | 67 | } |
225 | @@ -70,7 +70,7 @@ | |||
226 | 70 | id: printerPageLoaded | 70 | id: printerPageLoaded |
227 | 71 | 71 | ||
228 | 72 | Column { | 72 | Column { |
230 | 73 | spacing: units.gu(2) | 73 | height: childrenRect.height + anchors.topMargin |
231 | 74 | anchors { | 74 | anchors { |
232 | 75 | top: parent.top | 75 | top: parent.top |
233 | 76 | topMargin: units.gu(2) | 76 | topMargin: units.gu(2) |
234 | @@ -91,6 +91,31 @@ | |||
235 | 91 | } | 91 | } |
236 | 92 | } | 92 | } |
237 | 93 | 93 | ||
238 | 94 | ListItems.SingleValue { | ||
239 | 95 | anchors { | ||
240 | 96 | left: parent.left | ||
241 | 97 | right: parent.right | ||
242 | 98 | } | ||
243 | 99 | text: "Status" | ||
244 | 100 | |||
245 | 101 | value: { | ||
246 | 102 | var state; | ||
247 | 103 | if (printer.state == PrinterEnum.IdleState) { | ||
248 | 104 | state = i18n.tr("Idle"); | ||
249 | 105 | } else if (printer.state == PrinterEnum.AbortedState) { | ||
250 | 106 | state = i18n.tr("Aborted"); | ||
251 | 107 | } else if (printer.state == PrinterEnum.ActiveState) { | ||
252 | 108 | state = i18n.tr("Active"); | ||
253 | 109 | } else if (printer.state == PrinterEnum.ErrorState) { | ||
254 | 110 | state = i18n.tr("Stopped"); | ||
255 | 111 | } | ||
256 | 112 | return "%1 — %2" | ||
257 | 113 | .arg(state) | ||
258 | 114 | .arg(printer.lastMessage ? | ||
259 | 115 | printer.lastMessage : i18n.tr("No messages")); | ||
260 | 116 | } | ||
261 | 117 | } | ||
262 | 118 | |||
263 | 94 | ListItems.Standard { | 119 | ListItems.Standard { |
264 | 95 | anchors { | 120 | anchors { |
265 | 96 | left: parent.left | 121 | left: parent.left |
266 | @@ -109,25 +134,30 @@ | |||
267 | 109 | left: parent.left | 134 | left: parent.left |
268 | 110 | right: parent.right | 135 | right: parent.right |
269 | 111 | } | 136 | } |
270 | 137 | text: "Shared" | ||
271 | 138 | |||
272 | 139 | control: Switch { | ||
273 | 140 | checked: printer.shared | ||
274 | 141 | onCheckedChanged: printer.shared = checked | ||
275 | 142 | } | ||
276 | 143 | } | ||
277 | 144 | |||
278 | 145 | ListItems.Standard { | ||
279 | 146 | anchors { | ||
280 | 147 | left: parent.left | ||
281 | 148 | right: parent.right | ||
282 | 149 | } | ||
283 | 112 | text: "Jobs" | 150 | text: "Jobs" |
284 | 113 | progression: true | 151 | progression: true |
285 | 114 | onClicked: pageStack.push(jobPage, { printer: printer }) | 152 | onClicked: pageStack.push(jobPage, { printer: printer }) |
286 | 115 | } | 153 | } |
287 | 116 | 154 | ||
289 | 117 | Label { | 155 | ListItems.Standard { |
290 | 118 | anchors { | 156 | anchors { |
291 | 119 | left: parent.left | 157 | left: parent.left |
292 | 120 | right: parent.right | 158 | right: parent.right |
293 | 121 | margins: units.gu(2) | ||
294 | 122 | } | 159 | } |
295 | 123 | text: "Description" | 160 | text: "Description" |
296 | 124 | } | ||
297 | 125 | |||
298 | 126 | ListItems.SingleControl { | ||
299 | 127 | anchors { | ||
300 | 128 | left: parent.left | ||
301 | 129 | right: parent.right | ||
302 | 130 | } | ||
303 | 131 | 161 | ||
304 | 132 | control: TextField { | 162 | control: TextField { |
305 | 133 | anchors { | 163 | anchors { |
306 | @@ -141,6 +171,27 @@ | |||
307 | 141 | } | 171 | } |
308 | 142 | } | 172 | } |
309 | 143 | 173 | ||
310 | 174 | ListItems.Standard { | ||
311 | 175 | anchors { | ||
312 | 176 | left: parent.left | ||
313 | 177 | right: parent.right | ||
314 | 178 | } | ||
315 | 179 | text: "Copies" | ||
316 | 180 | |||
317 | 181 | control: TextField { | ||
318 | 182 | id: copiesField | ||
319 | 183 | inputMethodHints: Qt.ImhDigitsOnly | ||
320 | 184 | text: printer.copies | ||
321 | 185 | validator: IntValidator { | ||
322 | 186 | bottom: 1 | ||
323 | 187 | top: 999 | ||
324 | 188 | } | ||
325 | 189 | width: units.gu(10) | ||
326 | 190 | onTextChanged: printer.copies = text | ||
327 | 191 | } | ||
328 | 192 | |||
329 | 193 | } | ||
330 | 194 | |||
331 | 144 | 195 | ||
332 | 145 | ListItems.ValueSelector { | 196 | ListItems.ValueSelector { |
333 | 146 | anchors { | 197 | anchors { |
334 | @@ -200,12 +251,70 @@ | |||
335 | 200 | selectedIndex = printer.printQuality | 251 | selectedIndex = printer.printQuality |
336 | 201 | } | 252 | } |
337 | 202 | } | 253 | } |
338 | 254 | |||
339 | 255 | ListItems.SingleControl { | ||
340 | 256 | anchors { | ||
341 | 257 | left: parent.left | ||
342 | 258 | right: parent.right | ||
343 | 259 | } | ||
344 | 260 | control: Button { | ||
345 | 261 | text: "Print test page" | ||
346 | 262 | onClicked: Printers.printTestPage(printer.name) | ||
347 | 263 | } | ||
348 | 264 | } | ||
349 | 265 | |||
350 | 266 | ListItems.SingleValue { | ||
351 | 267 | anchors { | ||
352 | 268 | left: parent.left | ||
353 | 269 | right: parent.right | ||
354 | 270 | } | ||
355 | 271 | text: "Device URI" | ||
356 | 272 | value: printer.deviceUri | ||
357 | 273 | } | ||
358 | 203 | } | 274 | } |
359 | 204 | } | 275 | } |
360 | 205 | } | 276 | } |
361 | 206 | } | 277 | } |
362 | 207 | 278 | ||
363 | 208 | Component { | 279 | Component { |
364 | 280 | id: jobDelegate | ||
365 | 281 | |||
366 | 282 | ListItem { | ||
367 | 283 | height: modelLayout.height + (divider.visible ? divider.height : 0) | ||
368 | 284 | trailingActions: ListItemActions { | ||
369 | 285 | actions: [ | ||
370 | 286 | Action { | ||
371 | 287 | iconName: model.held ? "media-playback-start" : "media-playback-pause" | ||
372 | 288 | text: model.held ? "Release" : "Hold" | ||
373 | 289 | |||
374 | 290 | onTriggered: { | ||
375 | 291 | if (model.held) { | ||
376 | 292 | Printers.releaseJob(model.printerName, model.id); | ||
377 | 293 | } else { | ||
378 | 294 | Printers.holdJob(model.printerName, model.id); | ||
379 | 295 | } | ||
380 | 296 | } | ||
381 | 297 | }, | ||
382 | 298 | Action { | ||
383 | 299 | iconName: "cancel" | ||
384 | 300 | text: "Cancel" | ||
385 | 301 | |||
386 | 302 | onTriggered: Printers.cancelJob(model.printerName, model.id); | ||
387 | 303 | } | ||
388 | 304 | ] | ||
389 | 305 | } | ||
390 | 306 | |||
391 | 307 | ListItemLayout { | ||
392 | 308 | id: modelLayout | ||
393 | 309 | title.text: displayName | ||
394 | 310 | subtitle.text: "Printing " + model.impressionsCompleted + " pages" + "\n" + model.printerName | ||
395 | 311 | subtitle.wrapMode: Text.WrapAtWordBoundaryOrAnywhere | ||
396 | 312 | subtitle.maximumLineCount: 3 | ||
397 | 313 | } | ||
398 | 314 | } | ||
399 | 315 | } | ||
400 | 316 | |||
401 | 317 | Component { | ||
402 | 209 | id: jobPage | 318 | id: jobPage |
403 | 210 | Page { | 319 | Page { |
404 | 211 | property var printer | 320 | property var printer |
405 | @@ -219,26 +328,11 @@ | |||
406 | 219 | id: jobList | 328 | id: jobList |
407 | 220 | anchors.fill: parent | 329 | anchors.fill: parent |
408 | 221 | model: printer.jobs | 330 | model: printer.jobs |
424 | 222 | delegate: ListItem { | 331 | delegate: jobDelegate |
410 | 223 | height: jobLayout.height + (divider.visible ? divider.height : 0) | ||
411 | 224 | ListItemLayout { | ||
412 | 225 | id: jobLayout | ||
413 | 226 | title.text: displayName | ||
414 | 227 | |||
415 | 228 | Icon { | ||
416 | 229 | id: icon | ||
417 | 230 | width: height | ||
418 | 231 | height: units.gu(2.5) | ||
419 | 232 | name: "stock_document" | ||
420 | 233 | SlotsLayout.position: SlotsLayout.First | ||
421 | 234 | } | ||
422 | 235 | } | ||
423 | 236 | } | ||
425 | 237 | } | 332 | } |
426 | 238 | } | 333 | } |
427 | 239 | } | 334 | } |
428 | 240 | 335 | ||
429 | 241 | |||
430 | 242 | Component { | 336 | Component { |
431 | 243 | id: allJobsPage | 337 | id: allJobsPage |
432 | 244 | Page { | 338 | Page { |
433 | @@ -252,21 +346,7 @@ | |||
434 | 252 | id: jobsList | 346 | id: jobsList |
435 | 253 | anchors.fill: parent | 347 | anchors.fill: parent |
436 | 254 | model: Printers.printJobs | 348 | model: Printers.printJobs |
452 | 255 | delegate: ListItem { | 349 | delegate: jobDelegate |
438 | 256 | height: jobsLayout.height + (divider.visible ? divider.height : 0) | ||
439 | 257 | ListItemLayout { | ||
440 | 258 | id: jobsLayout | ||
441 | 259 | title.text: displayName | ||
442 | 260 | |||
443 | 261 | Icon { | ||
444 | 262 | id: icon | ||
445 | 263 | width: height | ||
446 | 264 | height: units.gu(2.5) | ||
447 | 265 | name: "stock_document" | ||
448 | 266 | SlotsLayout.position: SlotsLayout.First | ||
449 | 267 | } | ||
450 | 268 | } | ||
451 | 269 | } | ||
453 | 270 | } | 350 | } |
454 | 271 | } | 351 | } |
455 | 272 | } | 352 | } |
456 | @@ -338,9 +418,18 @@ | |||
457 | 338 | 418 | ||
458 | 339 | ProgressionSlot {} | 419 | ProgressionSlot {} |
459 | 340 | } | 420 | } |
461 | 341 | onClicked: pageStack.push(printerPage, { printer: model }) | 421 | onClicked: { |
462 | 422 | Printers.loadPrinter(model.name); | ||
463 | 423 | pageStack.push(printerPage, { printer: model }); | ||
464 | 424 | } | ||
465 | 342 | } | 425 | } |
466 | 343 | } | 426 | } |
467 | 427 | |||
468 | 428 | Label { | ||
469 | 429 | anchors.centerIn: parent | ||
470 | 430 | visible: printerList.count === 0 | ||
471 | 431 | text: "No printers found" | ||
472 | 432 | } | ||
473 | 344 | } | 433 | } |
474 | 345 | } | 434 | } |
475 | 346 | 435 | ||
476 | @@ -423,9 +512,7 @@ | |||
477 | 423 | } | 512 | } |
478 | 424 | } | 513 | } |
479 | 425 | 514 | ||
483 | 426 | Component.onCompleted: { | 515 | Component.onCompleted: Printers.prepareToAddPrinter() |
481 | 427 | Printers.prepareToAddPrinter(); | ||
482 | 428 | } | ||
484 | 429 | 516 | ||
485 | 430 | Timer { | 517 | Timer { |
486 | 431 | id: okTimer | 518 | id: okTimer |
487 | @@ -436,14 +523,12 @@ | |||
488 | 436 | Flickable { | 523 | Flickable { |
489 | 437 | id: addPrinterFlickable | 524 | id: addPrinterFlickable |
490 | 438 | anchors.fill: parent | 525 | anchors.fill: parent |
491 | 526 | contentHeight: contentItem.childrenRect.height | ||
492 | 439 | 527 | ||
493 | 440 | Column { | 528 | Column { |
494 | 441 | id: addPrinterCol | 529 | id: addPrinterCol |
495 | 442 | property bool enabled: true | 530 | property bool enabled: true |
500 | 443 | anchors { | 531 | anchors { left: parent.left; right: parent.right } |
497 | 444 | left: parent.left | ||
498 | 445 | right: parent.right | ||
499 | 446 | } | ||
501 | 447 | 532 | ||
502 | 448 | Item { | 533 | Item { |
503 | 449 | id: errorMessageContainer | 534 | id: errorMessageContainer |
504 | @@ -476,10 +561,7 @@ | |||
505 | 476 | 561 | ||
506 | 477 | ListItems.ValueSelector { | 562 | ListItems.ValueSelector { |
507 | 478 | id: driverSelector | 563 | id: driverSelector |
512 | 479 | anchors { | 564 | anchors { left: parent.left; right: parent.right } |
509 | 480 | left: parent.left | ||
510 | 481 | right: parent.right | ||
511 | 482 | } | ||
513 | 483 | text: "Choose driver" | 565 | text: "Choose driver" |
514 | 484 | values: [ | 566 | values: [ |
515 | 485 | "Select printer from database", | 567 | "Select printer from database", |
516 | @@ -489,10 +571,7 @@ | |||
517 | 489 | } | 571 | } |
518 | 490 | 572 | ||
519 | 491 | ListItems.Standard { | 573 | ListItems.Standard { |
524 | 492 | anchors { | 574 | anchors { left: parent.left; right: parent.right } |
521 | 493 | left: parent.left | ||
522 | 494 | right: parent.right | ||
523 | 495 | } | ||
525 | 496 | text: "Filter drivers" | 575 | text: "Filter drivers" |
526 | 497 | control: TextField { | 576 | control: TextField { |
527 | 498 | id: driverFilter | 577 | id: driverFilter |
528 | @@ -559,10 +638,7 @@ | |||
529 | 559 | } | 638 | } |
530 | 560 | 639 | ||
531 | 561 | ListItems.Standard { | 640 | ListItems.Standard { |
536 | 562 | anchors { | 641 | anchors { left: parent.left; right: parent.right } |
533 | 563 | left: parent.left | ||
534 | 564 | right: parent.right | ||
535 | 565 | } | ||
537 | 566 | text: "Printer name" | 642 | text: "Printer name" |
538 | 567 | control: TextField { | 643 | control: TextField { |
539 | 568 | id: printerName | 644 | id: printerName |
540 | @@ -572,10 +648,7 @@ | |||
541 | 572 | } | 648 | } |
542 | 573 | 649 | ||
543 | 574 | ListItems.Standard { | 650 | ListItems.Standard { |
548 | 575 | anchors { | 651 | anchors { left: parent.left; right: parent.right } |
545 | 576 | left: parent.left | ||
546 | 577 | right: parent.right | ||
547 | 578 | } | ||
549 | 579 | text: "Description (optional)" | 652 | text: "Description (optional)" |
550 | 580 | control: TextField { | 653 | control: TextField { |
551 | 581 | id: printerDescription | 654 | id: printerDescription |
552 | @@ -585,10 +658,7 @@ | |||
553 | 585 | } | 658 | } |
554 | 586 | 659 | ||
555 | 587 | ListItems.Standard { | 660 | ListItems.Standard { |
560 | 588 | anchors { | 661 | anchors { left: parent.left; right: parent.right } |
557 | 589 | left: parent.left | ||
558 | 590 | right: parent.right | ||
559 | 591 | } | ||
561 | 592 | text: "Location (optional)" | 662 | text: "Location (optional)" |
562 | 593 | control: TextField { | 663 | control: TextField { |
563 | 594 | id: printerLocation | 664 | id: printerLocation |
564 | @@ -597,6 +667,93 @@ | |||
565 | 597 | enabled: parent.enabled | 667 | enabled: parent.enabled |
566 | 598 | } | 668 | } |
567 | 599 | } | 669 | } |
568 | 670 | |||
569 | 671 | Label { | ||
570 | 672 | id: remotePrintersLabel | ||
571 | 673 | anchors { | ||
572 | 674 | left: parent.left | ||
573 | 675 | right: parent.right | ||
574 | 676 | margins: units.gu(2) | ||
575 | 677 | top: addPrinterCol.bottom | ||
576 | 678 | } | ||
577 | 679 | text: "Other printers" | ||
578 | 680 | |||
579 | 681 | ActivityIndicator { | ||
580 | 682 | id: remotePrintersSearchIndicator | ||
581 | 683 | anchors { | ||
582 | 684 | right: parent.right | ||
583 | 685 | verticalCenter: parent.verticalCenter | ||
584 | 686 | } | ||
585 | 687 | property var target | ||
586 | 688 | Component.onCompleted: target = Printers.devices | ||
587 | 689 | running: target.searching | ||
588 | 690 | } | ||
589 | 691 | } | ||
590 | 692 | |||
591 | 693 | ListView { | ||
592 | 694 | id: remotePrintersList | ||
593 | 695 | anchors { | ||
594 | 696 | left: parent.left | ||
595 | 697 | right: parent.right | ||
596 | 698 | top: remotePrintersLabel.bottom | ||
597 | 699 | topMargin: units.gu(2) | ||
598 | 700 | } | ||
599 | 701 | height: contentItem.childrenRect.height | ||
600 | 702 | model: Printers.devices | ||
601 | 703 | delegate: ListItem { | ||
602 | 704 | height: modelLayout.height + (divider.visible ? divider.height : 0) | ||
603 | 705 | ListItemLayout { | ||
604 | 706 | id: modelLayout | ||
605 | 707 | title.text: displayName | ||
606 | 708 | subtitle.text: { | ||
607 | 709 | if (type == PrinterEnum.LPDType) return "LPD"; | ||
608 | 710 | if (type == PrinterEnum.IppSType) return "IppS"; | ||
609 | 711 | if (type == PrinterEnum.Ipp14Type) return "Ipp14"; | ||
610 | 712 | if (type == PrinterEnum.HttpType) return "Http"; | ||
611 | 713 | if (type == PrinterEnum.BehType) return "Beh"; | ||
612 | 714 | if (type == PrinterEnum.SocketType) return "Socket"; | ||
613 | 715 | if (type == PrinterEnum.HttpsType) return "Https"; | ||
614 | 716 | if (type == PrinterEnum.IppType) return "Ipp"; | ||
615 | 717 | if (type == PrinterEnum.HPType) return "HP"; | ||
616 | 718 | if (type == PrinterEnum.USBType) return "USB"; | ||
617 | 719 | if (type == PrinterEnum.HPFaxType) return "HPFax"; | ||
618 | 720 | if (type == PrinterEnum.DNSSDType) return "DNSSD"; | ||
619 | 721 | else return "Unknown protocol"; | ||
620 | 722 | } | ||
621 | 723 | |||
622 | 724 | Icon { | ||
623 | 725 | id: icon | ||
624 | 726 | width: height | ||
625 | 727 | height: units.gu(2.5) | ||
626 | 728 | name: "network-printer-symbolic" | ||
627 | 729 | SlotsLayout.position: SlotsLayout.First | ||
628 | 730 | } | ||
629 | 731 | |||
630 | 732 | Button { | ||
631 | 733 | text: "Select printer" | ||
632 | 734 | onClicked: { | ||
633 | 735 | var suggestedPrinterName = (" " + displayName).slice(1); | ||
634 | 736 | suggestedPrinterName = suggestedPrinterName.replace(/\ /g, "\-"); | ||
635 | 737 | printerUri.text = uri; | ||
636 | 738 | printerName.text = suggestedPrinterName; | ||
637 | 739 | printerDescription.text = info; | ||
638 | 740 | printerLocation.text = location; | ||
639 | 741 | } | ||
640 | 742 | } | ||
641 | 743 | } | ||
642 | 744 | } | ||
643 | 745 | } | ||
644 | 746 | |||
645 | 747 | Label { | ||
646 | 748 | anchors { | ||
647 | 749 | left: parent.left | ||
648 | 750 | right: parent.right | ||
649 | 751 | top: remotePrintersLabel.bottom | ||
650 | 752 | topMargin: units.gu(2) | ||
651 | 753 | } | ||
652 | 754 | text: "No other printers found" | ||
653 | 755 | visible: !remotePrintersSearchIndicator.running && remotePrintersList.count == 0 | ||
654 | 756 | } | ||
655 | 600 | } | 757 | } |
656 | 601 | } | 758 | } |
657 | 602 | } | 759 | } |
658 | 603 | 760 | ||
659 | === modified file 'modules/Ubuntu/Components/Extras/Printers/CMakeLists.txt' | |||
660 | --- modules/Ubuntu/Components/Extras/Printers/CMakeLists.txt 2017-02-21 16:55:36 +0000 | |||
661 | +++ modules/Ubuntu/Components/Extras/Printers/CMakeLists.txt 2017-03-23 12:51:36 +0000 | |||
662 | @@ -29,17 +29,20 @@ | |||
663 | 29 | backend/backend_cups.cpp | 29 | backend/backend_cups.cpp |
664 | 30 | backend/backend_pdf.cpp | 30 | backend/backend_pdf.cpp |
665 | 31 | 31 | ||
666 | 32 | cups/devicesearcher.cpp | ||
667 | 32 | cups/ippclient.cpp | 33 | cups/ippclient.cpp |
668 | 34 | cups/jobloader.cpp | ||
669 | 33 | cups/printerdriverloader.cpp | 35 | cups/printerdriverloader.cpp |
670 | 34 | cups/printerloader.cpp | 36 | cups/printerloader.cpp |
671 | 35 | 37 | ||
672 | 38 | models/devicemodel.cpp | ||
673 | 36 | models/drivermodel.cpp | 39 | models/drivermodel.cpp |
674 | 37 | models/jobmodel.cpp | 40 | models/jobmodel.cpp |
675 | 38 | models/printermodel.cpp | 41 | models/printermodel.cpp |
676 | 39 | 42 | ||
677 | 40 | printer/printer.cpp | 43 | printer/printer.cpp |
678 | 41 | printer/printerjob.cpp | 44 | printer/printerjob.cpp |
680 | 42 | printer/printersignalhandler.cpp | 45 | printer/signalratelimiter.cpp |
681 | 43 | printers/printers.cpp | 46 | printers/printers.cpp |
682 | 44 | 47 | ||
683 | 45 | enums.h | 48 | enums.h |
684 | 46 | 49 | ||
685 | === modified file 'modules/Ubuntu/Components/Extras/Printers/backend/backend.cpp' | |||
686 | --- modules/Ubuntu/Components/Extras/Printers/backend/backend.cpp 2017-02-23 14:04:26 +0000 | |||
687 | +++ modules/Ubuntu/Components/Extras/Printers/backend/backend.cpp 2017-03-23 12:51:36 +0000 | |||
688 | @@ -91,6 +91,22 @@ | |||
689 | 91 | return QString(); | 91 | return QString(); |
690 | 92 | } | 92 | } |
691 | 93 | 93 | ||
692 | 94 | QString PrinterBackend::printerSetCopies(const QString &name, | ||
693 | 95 | const int &copies) | ||
694 | 96 | { | ||
695 | 97 | Q_UNUSED(name); | ||
696 | 98 | Q_UNUSED(copies); | ||
697 | 99 | return QString(); | ||
698 | 100 | } | ||
699 | 101 | |||
700 | 102 | QString PrinterBackend::printerSetShared(const QString &name, | ||
701 | 103 | const bool shared) | ||
702 | 104 | { | ||
703 | 105 | Q_UNUSED(name); | ||
704 | 106 | Q_UNUSED(shared); | ||
705 | 107 | return QString(); | ||
706 | 108 | } | ||
707 | 109 | |||
708 | 94 | QString PrinterBackend::printerSetInfo(const QString &name, | 110 | QString PrinterBackend::printerSetInfo(const QString &name, |
709 | 95 | const QString &info) | 111 | const QString &info) |
710 | 96 | { | 112 | { |
711 | @@ -139,6 +155,18 @@ | |||
712 | 139 | Q_UNUSED(name); | 155 | Q_UNUSED(name); |
713 | 140 | } | 156 | } |
714 | 141 | 157 | ||
715 | 158 | void PrinterBackend::holdJob(const QString &name, const int jobId) | ||
716 | 159 | { | ||
717 | 160 | Q_UNUSED(jobId); | ||
718 | 161 | Q_UNUSED(name); | ||
719 | 162 | } | ||
720 | 163 | |||
721 | 164 | void PrinterBackend::releaseJob(const QString &name, const int jobId) | ||
722 | 165 | { | ||
723 | 166 | Q_UNUSED(jobId); | ||
724 | 167 | Q_UNUSED(name); | ||
725 | 168 | } | ||
726 | 169 | |||
727 | 142 | int PrinterBackend::printFileToDest(const QString &filepath, | 170 | int PrinterBackend::printFileToDest(const QString &filepath, |
728 | 143 | const QString &title, | 171 | const QString &title, |
729 | 144 | const cups_dest_t *dest) | 172 | const cups_dest_t *dest) |
730 | @@ -154,6 +182,14 @@ | |||
731 | 154 | return QList<QSharedPointer<PrinterJob>>{}; | 182 | return QList<QSharedPointer<PrinterJob>>{}; |
732 | 155 | } | 183 | } |
733 | 156 | 184 | ||
734 | 185 | QSharedPointer<PrinterJob> PrinterBackend::printerGetJob( | ||
735 | 186 | const QString &printerName, const int jobId) | ||
736 | 187 | { | ||
737 | 188 | Q_UNUSED(printerName); | ||
738 | 189 | Q_UNUSED(jobId); | ||
739 | 190 | return QSharedPointer<PrinterJob>(Q_NULLPTR); | ||
740 | 191 | } | ||
741 | 192 | |||
742 | 157 | QMap<QString, QVariant> PrinterBackend::printerGetJobAttributes( | 193 | QMap<QString, QVariant> PrinterBackend::printerGetJobAttributes( |
743 | 158 | const QString &name, const int jobId) | 194 | const QString &name, const int jobId) |
744 | 159 | { | 195 | { |
745 | @@ -182,6 +218,11 @@ | |||
746 | 182 | return QString(); | 218 | return QString(); |
747 | 183 | } | 219 | } |
748 | 184 | 220 | ||
749 | 221 | bool PrinterBackend::isRemote() const | ||
750 | 222 | { | ||
751 | 223 | return false; | ||
752 | 224 | } | ||
753 | 225 | |||
754 | 185 | PrinterEnum::State PrinterBackend::state() const | 226 | PrinterEnum::State PrinterBackend::state() const |
755 | 186 | { | 227 | { |
756 | 187 | return PrinterEnum::State::IdleState; | 228 | return PrinterEnum::State::IdleState; |
757 | @@ -248,6 +289,13 @@ | |||
758 | 248 | return QString(); | 289 | return QString(); |
759 | 249 | } | 290 | } |
760 | 250 | 291 | ||
761 | 292 | void PrinterBackend::requestJobExtendedAttributes( | ||
762 | 293 | QSharedPointer<Printer> printer, QSharedPointer<PrinterJob> job) | ||
763 | 294 | { | ||
764 | 295 | Q_UNUSED(printer); | ||
765 | 296 | Q_UNUSED(job); | ||
766 | 297 | } | ||
767 | 298 | |||
768 | 251 | void PrinterBackend::requestPrinterDrivers() | 299 | void PrinterBackend::requestPrinterDrivers() |
769 | 252 | { | 300 | { |
770 | 253 | } | 301 | } |
771 | 254 | 302 | ||
772 | === modified file 'modules/Ubuntu/Components/Extras/Printers/backend/backend.h' | |||
773 | --- modules/Ubuntu/Components/Extras/Printers/backend/backend.h 2017-02-23 14:04:26 +0000 | |||
774 | +++ modules/Ubuntu/Components/Extras/Printers/backend/backend.h 2017-03-23 12:51:36 +0000 | |||
775 | @@ -63,6 +63,9 @@ | |||
776 | 63 | const QString &name, | 63 | const QString &name, |
777 | 64 | const bool accept, | 64 | const bool accept, |
778 | 65 | const QString &reason = QString::null); | 65 | const QString &reason = QString::null); |
779 | 66 | virtual QString printerSetCopies(const QString &name, const int &copies); | ||
780 | 67 | virtual QString printerSetShared(const QString &name, | ||
781 | 68 | const bool shared); | ||
782 | 66 | virtual QString printerSetInfo(const QString &name, | 69 | virtual QString printerSetInfo(const QString &name, |
783 | 67 | const QString &info); | 70 | const QString &info); |
784 | 68 | virtual QString printerAddOption(const QString &name, | 71 | virtual QString printerAddOption(const QString &name, |
785 | @@ -77,10 +80,14 @@ | |||
786 | 77 | const PrinterJob *options); | 80 | const PrinterJob *options); |
787 | 78 | 81 | ||
788 | 79 | virtual void cancelJob(const QString &name, const int jobId); | 82 | virtual void cancelJob(const QString &name, const int jobId); |
789 | 83 | virtual void holdJob(const QString &name, const int jobId); | ||
790 | 84 | virtual void releaseJob(const QString &name, const int jobId); | ||
791 | 80 | virtual int printFileToDest(const QString &filepath, | 85 | virtual int printFileToDest(const QString &filepath, |
792 | 81 | const QString &title, | 86 | const QString &title, |
793 | 82 | const cups_dest_t *dest); | 87 | const cups_dest_t *dest); |
794 | 83 | virtual QList<QSharedPointer<PrinterJob>> printerGetJobs(); | 88 | virtual QList<QSharedPointer<PrinterJob>> printerGetJobs(); |
795 | 89 | virtual QSharedPointer<PrinterJob> printerGetJob(const QString &printerName, | ||
796 | 90 | const int jobId); | ||
797 | 84 | virtual QMap<QString, QVariant> printerGetJobAttributes( | 91 | virtual QMap<QString, QVariant> printerGetJobAttributes( |
798 | 85 | const QString &name, const int jobId); | 92 | const QString &name, const int jobId); |
799 | 86 | 93 | ||
800 | @@ -88,6 +95,7 @@ | |||
801 | 88 | virtual QString description() const; | 95 | virtual QString description() const; |
802 | 89 | virtual QString location() const; | 96 | virtual QString location() const; |
803 | 90 | virtual QString makeAndModel() const; | 97 | virtual QString makeAndModel() const; |
804 | 98 | virtual bool isRemote() const; | ||
805 | 91 | 99 | ||
806 | 92 | virtual PrinterEnum::State state() const; | 100 | virtual PrinterEnum::State state() const; |
807 | 93 | virtual QList<QPageSize> supportedPageSizes() const; | 101 | virtual QList<QPageSize> supportedPageSizes() const; |
808 | @@ -105,6 +113,8 @@ | |||
809 | 105 | virtual QSharedPointer<Printer> getPrinter(const QString &printerName); | 113 | virtual QSharedPointer<Printer> getPrinter(const QString &printerName); |
810 | 106 | virtual QString defaultPrinterName(); | 114 | virtual QString defaultPrinterName(); |
811 | 107 | 115 | ||
812 | 116 | virtual void requestJobExtendedAttributes(QSharedPointer<Printer> printer, | ||
813 | 117 | QSharedPointer<PrinterJob> job); | ||
814 | 108 | virtual void requestPrinterDrivers(); | 118 | virtual void requestPrinterDrivers(); |
815 | 109 | virtual void requestPrinter(const QString &printerName); | 119 | virtual void requestPrinter(const QString &printerName); |
816 | 110 | 120 | ||
817 | @@ -119,7 +129,10 @@ | |||
818 | 119 | void printerDriversLoaded(const QList<PrinterDriver> &drivers); | 129 | void printerDriversLoaded(const QList<PrinterDriver> &drivers); |
819 | 120 | void printerDriversFailedToLoad(const QString &errorMessage); | 130 | void printerDriversFailedToLoad(const QString &errorMessage); |
820 | 121 | 131 | ||
821 | 132 | void jobLoaded(QString, int, QMap<QString, QVariant>); | ||
822 | 122 | void printerLoaded(QSharedPointer<Printer> printers); | 133 | void printerLoaded(QSharedPointer<Printer> printers); |
823 | 134 | void deviceFound(const Device &device); | ||
824 | 135 | void deviceSearchFinished(); | ||
825 | 123 | 136 | ||
826 | 124 | void jobCompleted( | 137 | void jobCompleted( |
827 | 125 | const QString &text, | 138 | const QString &text, |
828 | 126 | 139 | ||
829 | === modified file 'modules/Ubuntu/Components/Extras/Printers/backend/backend_cups.cpp' | |||
830 | --- modules/Ubuntu/Components/Extras/Printers/backend/backend_cups.cpp 2017-02-24 12:53:34 +0000 | |||
831 | +++ modules/Ubuntu/Components/Extras/Printers/backend/backend_cups.cpp 2017-03-23 12:51:36 +0000 | |||
832 | @@ -15,6 +15,8 @@ | |||
833 | 15 | */ | 15 | */ |
834 | 16 | 16 | ||
835 | 17 | #include "backend/backend_cups.h" | 17 | #include "backend/backend_cups.h" |
836 | 18 | #include "cups/devicesearcher.h" | ||
837 | 19 | #include "cups/jobloader.h" | ||
838 | 18 | #include "cups/printerdriverloader.h" | 20 | #include "cups/printerdriverloader.h" |
839 | 19 | #include "cups/printerloader.h" | 21 | #include "cups/printerloader.h" |
840 | 20 | #include "utils.h" | 22 | #include "utils.h" |
841 | @@ -40,6 +42,10 @@ | |||
842 | 40 | , m_knownQualityOptions({ | 42 | , m_knownQualityOptions({ |
843 | 41 | "Quality", "PrintQuality", "HPPrintQuality", "StpQuality", | 43 | "Quality", "PrintQuality", "HPPrintQuality", "StpQuality", |
844 | 42 | "OutputMode",}) | 44 | "OutputMode",}) |
845 | 45 | , m_extendedAttributeNames({ | ||
846 | 46 | QStringLiteral("StateMessage"), QStringLiteral("DeviceUri"), | ||
847 | 47 | QStringLiteral("IsShared"), QStringLiteral("Copies"), | ||
848 | 48 | }) | ||
849 | 43 | , m_client(client) | 49 | , m_client(client) |
850 | 44 | , m_info(info) | 50 | , m_info(info) |
851 | 45 | , m_notifier(notifier) | 51 | , m_notifier(notifier) |
852 | @@ -178,6 +184,24 @@ | |||
853 | 178 | return QString(); | 184 | return QString(); |
854 | 179 | } | 185 | } |
855 | 180 | 186 | ||
856 | 187 | QString PrinterCupsBackend::printerSetCopies(const QString &name, | ||
857 | 188 | const int &copies) | ||
858 | 189 | { | ||
859 | 190 | if (!m_client->printerSetCopies(name, copies)) { | ||
860 | 191 | return m_client->getLastError(); | ||
861 | 192 | } | ||
862 | 193 | return QString(); | ||
863 | 194 | } | ||
864 | 195 | |||
865 | 196 | QString PrinterCupsBackend::printerSetShared(const QString &name, | ||
866 | 197 | const bool shared) | ||
867 | 198 | { | ||
868 | 199 | if (!m_client->printerSetShared(name, shared)) { | ||
869 | 200 | return m_client->getLastError(); | ||
870 | 201 | } | ||
871 | 202 | return QString(); | ||
872 | 203 | } | ||
873 | 204 | |||
874 | 181 | QString PrinterCupsBackend::printerSetInfo(const QString &name, | 205 | QString PrinterCupsBackend::printerSetInfo(const QString &name, |
875 | 182 | const QString &info) | 206 | const QString &info) |
876 | 183 | { | 207 | { |
877 | @@ -213,12 +237,27 @@ | |||
878 | 213 | cups_dest_t *dest = getDest(name); | 237 | cups_dest_t *dest = getDest(name); |
879 | 214 | ppd_file_t* ppd = getPpd(name); | 238 | ppd_file_t* ppd = getPpd(name); |
880 | 215 | 239 | ||
883 | 216 | if (!dest || !ppd) { | 240 | // Used to store extended attributes, which we should request maximum once. |
884 | 217 | return ret; | 241 | QMap<QString, QVariant> extendedAttributesResults; |
885 | 242 | |||
886 | 243 | /* Goes through known extended attributes. If one is being asked for, | ||
887 | 244 | ask for all of them right away. */ | ||
888 | 245 | Q_FOREACH(const QString &extendedOption, m_extendedAttributeNames) { | ||
889 | 246 | if (options.contains(extendedOption)) { | ||
890 | 247 | extendedAttributesResults = m_client->printerGetAttributes( | ||
891 | 248 | name, QStringList({ | ||
892 | 249 | QStringLiteral("device-uri"), | ||
893 | 250 | QStringLiteral("printer-uri-supported"), | ||
894 | 251 | QStringLiteral("printer-state-message"), | ||
895 | 252 | QStringLiteral("copies-default"), | ||
896 | 253 | }) | ||
897 | 254 | ); | ||
898 | 255 | break; | ||
899 | 256 | } | ||
900 | 218 | } | 257 | } |
901 | 219 | 258 | ||
902 | 220 | Q_FOREACH(const QString &option, options) { | 259 | Q_FOREACH(const QString &option, options) { |
904 | 221 | if (option == QStringLiteral("DefaultColorModel")) { | 260 | if (option == QStringLiteral("DefaultColorModel") && ppd) { |
905 | 222 | ColorModel model; | 261 | ColorModel model; |
906 | 223 | ppd_option_t *ppdColorModel = ppdFindOption(ppd, "ColorModel"); | 262 | ppd_option_t *ppdColorModel = ppdFindOption(ppd, "ColorModel"); |
907 | 224 | if (ppdColorModel) { | 263 | if (ppdColorModel) { |
908 | @@ -231,7 +270,7 @@ | |||
909 | 231 | } | 270 | } |
910 | 232 | } | 271 | } |
911 | 233 | ret[option] = QVariant::fromValue(model); | 272 | ret[option] = QVariant::fromValue(model); |
913 | 234 | } else if (option == QStringLiteral("DefaultPrintQuality")) { | 273 | } else if (option == QStringLiteral("DefaultPrintQuality") && ppd) { |
914 | 235 | PrintQuality quality; | 274 | PrintQuality quality; |
915 | 236 | Q_FOREACH(const QString opt, m_knownQualityOptions) { | 275 | Q_FOREACH(const QString opt, m_knownQualityOptions) { |
916 | 237 | ppd_option_t *ppdQuality = ppdFindOption(ppd, opt.toUtf8()); | 276 | ppd_option_t *ppdQuality = ppdFindOption(ppd, opt.toUtf8()); |
917 | @@ -245,7 +284,7 @@ | |||
918 | 245 | } | 284 | } |
919 | 246 | } | 285 | } |
920 | 247 | ret[option] = QVariant::fromValue(quality); | 286 | ret[option] = QVariant::fromValue(quality); |
922 | 248 | } else if (option == QStringLiteral("SupportedPrintQualities")) { | 287 | } else if (option == QStringLiteral("SupportedPrintQualities") && ppd) { |
923 | 249 | QList<PrintQuality> qualities; | 288 | QList<PrintQuality> qualities; |
924 | 250 | Q_FOREACH(const QString &opt, m_knownQualityOptions) { | 289 | Q_FOREACH(const QString &opt, m_knownQualityOptions) { |
925 | 251 | ppd_option_t *qualityOpt = ppdFindOption(ppd, opt.toUtf8()); | 290 | ppd_option_t *qualityOpt = ppdFindOption(ppd, opt.toUtf8()); |
926 | @@ -262,7 +301,7 @@ | |||
927 | 262 | } | 301 | } |
928 | 263 | } | 302 | } |
929 | 264 | ret[option] = QVariant::fromValue(qualities); | 303 | ret[option] = QVariant::fromValue(qualities); |
931 | 265 | } else if (option == QStringLiteral("SupportedColorModels")) { | 304 | } else if (option == QStringLiteral("SupportedColorModels") && ppd) { |
932 | 266 | QList<ColorModel> models; | 305 | QList<ColorModel> models; |
933 | 267 | ppd_option_t *colorModels = ppdFindOption(ppd, "ColorModel"); | 306 | ppd_option_t *colorModels = ppdFindOption(ppd, "ColorModel"); |
934 | 268 | if (colorModels) { | 307 | if (colorModels) { |
935 | @@ -277,19 +316,29 @@ | |||
936 | 277 | } | 316 | } |
937 | 278 | } | 317 | } |
938 | 279 | ret[option] = QVariant::fromValue(models); | 318 | ret[option] = QVariant::fromValue(models); |
940 | 280 | } else if (option == QStringLiteral("AcceptJobs")) { | 319 | } else if (option == QStringLiteral("AcceptJobs") && dest) { |
941 | 281 | // "true" if the destination is accepting new jobs, "false" if not. | 320 | // "true" if the destination is accepting new jobs, "false" if not. |
942 | 282 | QString res = cupsGetOption("printer-is-accepting-jobs", | 321 | QString res = cupsGetOption("printer-is-accepting-jobs", |
943 | 283 | dest->num_options, dest->options); | 322 | dest->num_options, dest->options); |
944 | 284 | ret[option] = res.contains("true"); | 323 | ret[option] = res.contains("true"); |
953 | 285 | } else { | 324 | } else if (option == QStringLiteral("StateReasons") && dest) { |
954 | 286 | ppd_option_t *val = ppdFindOption(ppd, option.toUtf8()); | 325 | ret[option] = cupsGetOption("printer-state-reasons", |
955 | 287 | 326 | dest->num_options, dest->options); | |
956 | 288 | if (val) { | 327 | } else if (option == QStringLiteral("StateMessage")) { |
957 | 289 | qWarning() << "asking for" << option << "returns" << val->text; | 328 | ret[option] = extendedAttributesResults["printer-state-message"]; |
958 | 290 | } else { | 329 | } else if (option == QStringLiteral("DeviceUri")) { |
959 | 291 | qWarning() << "option" << option << "yielded no option"; | 330 | auto res = extendedAttributesResults; |
960 | 292 | } | 331 | if (!res["printer-uri-supported"].toString().isEmpty()) { |
961 | 332 | ret[option] = res["printer-uri-supported"]; | ||
962 | 333 | } | ||
963 | 334 | if (!res["device-uri"].toString().isEmpty()) { | ||
964 | 335 | ret[option] = res["device-uri"]; | ||
965 | 336 | } | ||
966 | 337 | } else if (option == QStringLiteral("Copies")) { | ||
967 | 338 | ret[option] = extendedAttributesResults[QStringLiteral("copies-default")]; | ||
968 | 339 | } else if (option == QStringLiteral("Shared") && dest) { | ||
969 | 340 | ret[option] = cupsGetOption("printer-is-shared", | ||
970 | 341 | dest->num_options, dest->options); | ||
971 | 293 | } | 342 | } |
972 | 294 | } | 343 | } |
973 | 295 | return ret; | 344 | return ret; |
974 | @@ -306,10 +355,7 @@ | |||
975 | 306 | __CUPS_ADD_OPTION(dest, "Collate", "False"); | 355 | __CUPS_ADD_OPTION(dest, "Collate", "False"); |
976 | 307 | } | 356 | } |
977 | 308 | 357 | ||
982 | 309 | if (options->copies() > 1) { | 358 | __CUPS_ADD_OPTION(dest, "copies", QString::number(options->copies()).toLocal8Bit()); |
979 | 310 | __CUPS_ADD_OPTION(dest, "copies", QString::number(options->copies()).toLocal8Bit()); | ||
980 | 311 | } | ||
981 | 312 | |||
983 | 313 | __CUPS_ADD_OPTION(dest, "ColorModel", options->getColorModel().name.toLocal8Bit()); | 359 | __CUPS_ADD_OPTION(dest, "ColorModel", options->getColorModel().name.toLocal8Bit()); |
984 | 314 | __CUPS_ADD_OPTION(dest, "Duplex", Utils::duplexModeToPpdChoice(options->getDuplexMode()).toLocal8Bit()); | 360 | __CUPS_ADD_OPTION(dest, "Duplex", Utils::duplexModeToPpdChoice(options->getDuplexMode()).toLocal8Bit()); |
985 | 315 | 361 | ||
986 | @@ -347,6 +393,20 @@ | |||
987 | 347 | } | 393 | } |
988 | 348 | } | 394 | } |
989 | 349 | 395 | ||
990 | 396 | void PrinterCupsBackend::holdJob(const QString &name, const int jobId) | ||
991 | 397 | { | ||
992 | 398 | if (!m_client->printerHoldJob(name, jobId)) { | ||
993 | 399 | qWarning() << "Failed to hold job:" << jobId << "for" << name; | ||
994 | 400 | } | ||
995 | 401 | } | ||
996 | 402 | |||
997 | 403 | void PrinterCupsBackend::releaseJob(const QString &name, const int jobId) | ||
998 | 404 | { | ||
999 | 405 | if (!m_client->printerReleaseJob(name, jobId)) { | ||
1000 | 406 | qWarning() << "Failed to release job:" << jobId << "for" << name; | ||
1001 | 407 | } | ||
1002 | 408 | } | ||
1003 | 409 | |||
1004 | 350 | int PrinterCupsBackend::printFileToDest(const QString &filepath, | 410 | int PrinterCupsBackend::printFileToDest(const QString &filepath, |
1005 | 351 | const QString &title, | 411 | const QString &title, |
1006 | 352 | const cups_dest_t *dest) | 412 | const cups_dest_t *dest) |
1007 | @@ -385,7 +445,7 @@ | |||
1008 | 385 | const QString &name, const int jobId) | 445 | const QString &name, const int jobId) |
1009 | 386 | { | 446 | { |
1010 | 387 | Q_UNUSED(name); | 447 | Q_UNUSED(name); |
1012 | 388 | QMap<QString, QVariant> rawMap = m_client->printerGetJobAttributes(jobId); | 448 | QMap<QString, QVariant> rawMap = m_client->printerGetJobAttributes(name, jobId); |
1013 | 389 | QMap<QString, QVariant> map; | 449 | QMap<QString, QVariant> map; |
1014 | 390 | 450 | ||
1015 | 391 | // Filter attributes to know values | 451 | // Filter attributes to know values |
1016 | @@ -409,12 +469,34 @@ | |||
1017 | 409 | map.insert("ColorModel", QVariant("")); | 469 | map.insert("ColorModel", QVariant("")); |
1018 | 410 | } | 470 | } |
1019 | 411 | 471 | ||
1020 | 472 | if (__CUPS_ATTR_EXISTS(rawMap, "date-time-at-completed", QDateTime)) { | ||
1021 | 473 | map.insert("CompletedTime", rawMap.value("date-time-at-completed")); | ||
1022 | 474 | } else { | ||
1023 | 475 | map.insert("CompletedTime", QVariant(QDateTime())); | ||
1024 | 476 | } | ||
1025 | 477 | |||
1026 | 478 | if (__CUPS_ATTR_EXISTS(rawMap, "date-time-at-creation", QDateTime)) { | ||
1027 | 479 | map.insert("CreationTime", rawMap.value("date-time-at-creation")); | ||
1028 | 480 | } else { | ||
1029 | 481 | map.insert("CreationTime", QVariant(QDateTime())); | ||
1030 | 482 | } | ||
1031 | 483 | |||
1032 | 412 | if (__CUPS_ATTR_EXISTS(rawMap, "Duplex", QString)) { | 484 | if (__CUPS_ATTR_EXISTS(rawMap, "Duplex", QString)) { |
1033 | 413 | map.insert("Duplex", rawMap.value("Duplex")); | 485 | map.insert("Duplex", rawMap.value("Duplex")); |
1034 | 414 | } else { | 486 | } else { |
1035 | 415 | map.insert("Duplex", QVariant("")); | 487 | map.insert("Duplex", QVariant("")); |
1036 | 416 | } | 488 | } |
1037 | 417 | 489 | ||
1038 | 490 | // Try job-media-sheets-completed first as it should include duplex | ||
1039 | 491 | // if it doesn't exist fallback to job-impressions-completed | ||
1040 | 492 | if (__CUPS_ATTR_EXISTS(rawMap, "job-media-sheets-completed", int)) { | ||
1041 | 493 | map.insert("impressionsCompleted", rawMap.value("job-media-sheets-completed")); | ||
1042 | 494 | } else if (__CUPS_ATTR_EXISTS(rawMap, "job-impressions-completed", int)) { | ||
1043 | 495 | map.insert("impressionsCompleted", rawMap.value("job-impressions-completed")); | ||
1044 | 496 | } else { | ||
1045 | 497 | map.insert("impressionsCompleted", QVariant(0)); | ||
1046 | 498 | } | ||
1047 | 499 | |||
1048 | 418 | if (__CUPS_ATTR_EXISTS(rawMap, "landscape", bool)) { | 500 | if (__CUPS_ATTR_EXISTS(rawMap, "landscape", bool)) { |
1049 | 419 | map.insert("landscape", rawMap.value("landscape")); | 501 | map.insert("landscape", rawMap.value("landscape")); |
1050 | 420 | } else { | 502 | } else { |
1051 | @@ -434,6 +516,12 @@ | |||
1052 | 434 | map.insert("page-ranges", QVariant(QStringList())); | 516 | map.insert("page-ranges", QVariant(QStringList())); |
1053 | 435 | } | 517 | } |
1054 | 436 | 518 | ||
1055 | 519 | if (__CUPS_ATTR_EXISTS(rawMap, "date-time-at-processing", QDateTime)) { | ||
1056 | 520 | map.insert("ProcessingTime", rawMap.value("date-time-at-processing")); | ||
1057 | 521 | } else { | ||
1058 | 522 | map.insert("ProcessingTime", QVariant(QDateTime())); | ||
1059 | 523 | } | ||
1060 | 524 | |||
1061 | 437 | Q_FOREACH(QString qualityOption, m_knownQualityOptions) { | 525 | Q_FOREACH(QString qualityOption, m_knownQualityOptions) { |
1062 | 438 | if (rawMap.contains(qualityOption) | 526 | if (rawMap.contains(qualityOption) |
1063 | 439 | && rawMap.value(qualityOption).canConvert<QString>()) { | 527 | && rawMap.value(qualityOption).canConvert<QString>()) { |
1064 | @@ -451,6 +539,24 @@ | |||
1065 | 451 | map.insert("OutputOrder", "Normal"); | 539 | map.insert("OutputOrder", "Normal"); |
1066 | 452 | } | 540 | } |
1067 | 453 | 541 | ||
1068 | 542 | if (__CUPS_ATTR_EXISTS(rawMap, "job-k-octets", int)) { | ||
1069 | 543 | map.insert("Size", rawMap.value("job-k-octets")); | ||
1070 | 544 | } else { | ||
1071 | 545 | map.insert("Size", QVariant(0)); | ||
1072 | 546 | } | ||
1073 | 547 | |||
1074 | 548 | // If there is a state then get it, as there could have been a signal | ||
1075 | 549 | // flood. Which then means a forceJobRefresh is able to update the state | ||
1076 | 550 | if (__CUPS_ATTR_EXISTS(rawMap, "job-state", int)) { | ||
1077 | 551 | map.insert("State", rawMap.value("job-state").toInt()); | ||
1078 | 552 | } | ||
1079 | 553 | |||
1080 | 554 | if (__CUPS_ATTR_EXISTS(rawMap, "job-originating-user-name", QString)) { | ||
1081 | 555 | map.insert("User", rawMap.value("job-originating-user-name")); | ||
1082 | 556 | } else { | ||
1083 | 557 | map.insert("User", QVariant("")); | ||
1084 | 558 | } | ||
1085 | 559 | |||
1086 | 454 | // Generate a list of messages | 560 | // Generate a list of messages |
1087 | 455 | // TODO: for now just using job-printer-state-message, are there others? | 561 | // TODO: for now just using job-printer-state-message, are there others? |
1088 | 456 | QStringList messages; | 562 | QStringList messages; |
1089 | @@ -471,31 +577,13 @@ | |||
1090 | 471 | QList<QSharedPointer<PrinterJob>> list; | 577 | QList<QSharedPointer<PrinterJob>> list; |
1091 | 472 | 578 | ||
1092 | 473 | Q_FOREACH(auto job, jobs) { | 579 | Q_FOREACH(auto job, jobs) { |
1093 | 580 | // Note: extended attributes are not loaded here | ||
1094 | 581 | // they are loaded in JobLoader | ||
1095 | 474 | auto newJob = QSharedPointer<PrinterJob>( | 582 | auto newJob = QSharedPointer<PrinterJob>( |
1096 | 475 | new PrinterJob(QString::fromUtf8(job->dest), this, job->id) | 583 | new PrinterJob(QString::fromUtf8(job->dest), this, job->id) |
1097 | 476 | ); | 584 | ); |
1098 | 477 | |||
1099 | 478 | // Extract the times | ||
1100 | 479 | QDateTime completedTime; | ||
1101 | 480 | completedTime.setTimeZone(QTimeZone::systemTimeZone()); | ||
1102 | 481 | completedTime.setTime_t(job->completed_time); | ||
1103 | 482 | |||
1104 | 483 | QDateTime creationTime; | ||
1105 | 484 | creationTime.setTimeZone(QTimeZone::systemTimeZone()); | ||
1106 | 485 | creationTime.setTime_t(job->creation_time); | ||
1107 | 486 | |||
1108 | 487 | QDateTime processingTime; | ||
1109 | 488 | processingTime.setTimeZone(QTimeZone::systemTimeZone()); | ||
1110 | 489 | processingTime.setTime_t(job->processing_time); | ||
1111 | 490 | |||
1112 | 491 | // Load the information from the cups struct | ||
1113 | 492 | newJob->setCompletedTime(completedTime); | ||
1114 | 493 | newJob->setCreationTime(creationTime); | ||
1115 | 494 | newJob->setProcessingTime(processingTime); | ||
1116 | 495 | newJob->setSize(job->size); | ||
1117 | 496 | newJob->setState(static_cast<PrinterEnum::JobState>(job->state)); | 585 | newJob->setState(static_cast<PrinterEnum::JobState>(job->state)); |
1118 | 497 | newJob->setTitle(QString::fromLocal8Bit(job->title)); | 586 | newJob->setTitle(QString::fromLocal8Bit(job->title)); |
1119 | 498 | newJob->setUser(QString::fromLocal8Bit(job->user)); | ||
1120 | 499 | 587 | ||
1121 | 500 | list.append(newJob); | 588 | list.append(newJob); |
1122 | 501 | } | 589 | } |
1123 | @@ -505,6 +593,35 @@ | |||
1124 | 505 | return list; | 593 | return list; |
1125 | 506 | } | 594 | } |
1126 | 507 | 595 | ||
1127 | 596 | QSharedPointer<PrinterJob> PrinterCupsBackend::printerGetJob( | ||
1128 | 597 | const QString &printerName, const int jobId) | ||
1129 | 598 | { | ||
1130 | 599 | auto jobs = getCupsJobs(printerName); | ||
1131 | 600 | cups_job_t *cupsJob = Q_NULLPTR; | ||
1132 | 601 | QSharedPointer<PrinterJob> job(Q_NULLPTR); | ||
1133 | 602 | |||
1134 | 603 | for (int i=0; i < jobs.size(); i++) { | ||
1135 | 604 | if (jobs.at(i)->id == jobId) { | ||
1136 | 605 | cupsJob = jobs.at(i); | ||
1137 | 606 | break; | ||
1138 | 607 | } | ||
1139 | 608 | } | ||
1140 | 609 | |||
1141 | 610 | if (cupsJob) { | ||
1142 | 611 | job = QSharedPointer<PrinterJob>( | ||
1143 | 612 | new PrinterJob(QString::fromUtf8(cupsJob->dest), this, cupsJob->id) | ||
1144 | 613 | ); | ||
1145 | 614 | |||
1146 | 615 | job->setState(static_cast<PrinterEnum::JobState>(cupsJob->state)); | ||
1147 | 616 | job->setTitle(QString::fromLocal8Bit(cupsJob->title)); | ||
1148 | 617 | } | ||
1149 | 618 | |||
1150 | 619 | if (!jobs.size()) | ||
1151 | 620 | cupsFreeJobs(jobs.size(), jobs.first()); | ||
1152 | 621 | |||
1153 | 622 | return job; | ||
1154 | 623 | } | ||
1155 | 624 | |||
1156 | 508 | QString PrinterCupsBackend::printerName() const | 625 | QString PrinterCupsBackend::printerName() const |
1157 | 509 | { | 626 | { |
1158 | 510 | return m_printerName; | 627 | return m_printerName; |
1159 | @@ -525,6 +642,11 @@ | |||
1160 | 525 | return m_info.makeAndModel(); | 642 | return m_info.makeAndModel(); |
1161 | 526 | } | 643 | } |
1162 | 527 | 644 | ||
1163 | 645 | bool PrinterCupsBackend::isRemote() const | ||
1164 | 646 | { | ||
1165 | 647 | return m_info.isRemote(); | ||
1166 | 648 | } | ||
1167 | 649 | |||
1168 | 528 | PrinterEnum::State PrinterCupsBackend::state() const | 650 | PrinterEnum::State PrinterCupsBackend::state() const |
1169 | 529 | { | 651 | { |
1170 | 530 | switch (m_info.state()) { | 652 | switch (m_info.state()) { |
1171 | @@ -611,9 +733,35 @@ | |||
1172 | 611 | return QPrinterInfo::defaultPrinterName(); | 733 | return QPrinterInfo::defaultPrinterName(); |
1173 | 612 | } | 734 | } |
1174 | 613 | 735 | ||
1175 | 736 | void PrinterCupsBackend::requestJobExtendedAttributes( | ||
1176 | 737 | QSharedPointer<Printer> printer, QSharedPointer<PrinterJob> job) | ||
1177 | 738 | { | ||
1178 | 739 | QPair<QString, int> pair(printer->name(), job->jobId()); | ||
1179 | 740 | |||
1180 | 741 | if (m_activeJobRequests.contains(pair)) { | ||
1181 | 742 | return; | ||
1182 | 743 | } | ||
1183 | 744 | |||
1184 | 745 | auto thread = new QThread; | ||
1185 | 746 | auto loader = new JobLoader(this, printer->name(), job->jobId()); | ||
1186 | 747 | loader->moveToThread(thread); | ||
1187 | 748 | connect(thread, SIGNAL(started()), loader, SLOT(load())); | ||
1188 | 749 | connect(loader, SIGNAL(finished()), thread, SLOT(quit())); | ||
1189 | 750 | connect(loader, SIGNAL(finished()), loader, SLOT(deleteLater())); | ||
1190 | 751 | connect(loader, SIGNAL(loaded(QString, int, QMap<QString, QVariant>)), | ||
1191 | 752 | this, SIGNAL(jobLoaded(QString, int, QMap<QString, QVariant>))); | ||
1192 | 753 | connect(loader, SIGNAL(loaded(QString, int, QMap<QString, QVariant>)), | ||
1193 | 754 | this, SLOT(onJobLoaded(QString, int, QMap<QString, QVariant>))); | ||
1194 | 755 | connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); | ||
1195 | 756 | |||
1196 | 757 | m_activeJobRequests << pair; | ||
1197 | 758 | |||
1198 | 759 | thread->start(); | ||
1199 | 760 | } | ||
1200 | 761 | |||
1201 | 614 | void PrinterCupsBackend::requestPrinter(const QString &printerName) | 762 | void PrinterCupsBackend::requestPrinter(const QString &printerName) |
1202 | 615 | { | 763 | { |
1204 | 616 | if (m_activeRequests.contains(printerName)) { | 764 | if (m_activePrinterRequests.contains(printerName)) { |
1205 | 617 | return; | 765 | return; |
1206 | 618 | } | 766 | } |
1207 | 619 | 767 | ||
1208 | @@ -628,9 +776,10 @@ | |||
1209 | 628 | connect(loader, SIGNAL(loaded(QSharedPointer<Printer>)), | 776 | connect(loader, SIGNAL(loaded(QSharedPointer<Printer>)), |
1210 | 629 | this, SLOT(onPrinterLoaded(QSharedPointer<Printer>))); | 777 | this, SLOT(onPrinterLoaded(QSharedPointer<Printer>))); |
1211 | 630 | connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); | 778 | connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); |
1212 | 779 | |||
1213 | 780 | m_activePrinterRequests << printerName; | ||
1214 | 781 | |||
1215 | 631 | thread->start(); | 782 | thread->start(); |
1216 | 632 | |||
1217 | 633 | m_activeRequests << printerName; | ||
1218 | 634 | } | 783 | } |
1219 | 635 | 784 | ||
1220 | 636 | void PrinterCupsBackend::requestPrinterDrivers() | 785 | void PrinterCupsBackend::requestPrinterDrivers() |
1221 | @@ -647,6 +796,7 @@ | |||
1222 | 647 | connect(loader, SIGNAL(loaded(const QList<PrinterDriver>&)), | 796 | connect(loader, SIGNAL(loaded(const QList<PrinterDriver>&)), |
1223 | 648 | this, SIGNAL(printerDriversLoaded(const QList<PrinterDriver>&))); | 797 | this, SIGNAL(printerDriversLoaded(const QList<PrinterDriver>&))); |
1224 | 649 | connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); | 798 | connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); |
1225 | 799 | |||
1226 | 650 | thread->start(); | 800 | thread->start(); |
1227 | 651 | } | 801 | } |
1228 | 652 | 802 | ||
1229 | @@ -655,6 +805,22 @@ | |||
1230 | 655 | Q_EMIT requestPrinterDriverCancel(); | 805 | Q_EMIT requestPrinterDriverCancel(); |
1231 | 656 | } | 806 | } |
1232 | 657 | 807 | ||
1233 | 808 | void PrinterCupsBackend::searchForDevices() | ||
1234 | 809 | { | ||
1235 | 810 | |||
1236 | 811 | auto thread = new QThread; | ||
1237 | 812 | auto searcher = new DeviceSearcher(); | ||
1238 | 813 | searcher->moveToThread(thread); | ||
1239 | 814 | connect(thread, SIGNAL(started()), searcher, SLOT(load())); | ||
1240 | 815 | connect(searcher, SIGNAL(finished()), thread, SLOT(quit())); | ||
1241 | 816 | connect(searcher, SIGNAL(finished()), searcher, SLOT(deleteLater())); | ||
1242 | 817 | connect(searcher, SIGNAL(finished()), this, SIGNAL(deviceSearchFinished())); | ||
1243 | 818 | connect(searcher, SIGNAL(loaded(const Device&)), | ||
1244 | 819 | this, SIGNAL(deviceFound(const Device&))); | ||
1245 | 820 | connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); | ||
1246 | 821 | thread->start(); | ||
1247 | 822 | } | ||
1248 | 823 | |||
1249 | 658 | void PrinterCupsBackend::refresh() | 824 | void PrinterCupsBackend::refresh() |
1250 | 659 | { | 825 | { |
1251 | 660 | if (m_printerName.isEmpty()) { | 826 | if (m_printerName.isEmpty()) { |
1252 | @@ -716,7 +882,22 @@ | |||
1253 | 716 | } | 882 | } |
1254 | 717 | } | 883 | } |
1255 | 718 | 884 | ||
1256 | 885 | bool PrinterCupsBackend::isExtendedAttribute(const QString &attributeName) const | ||
1257 | 886 | { | ||
1258 | 887 | return m_extendedAttributeNames.contains(attributeName); | ||
1259 | 888 | } | ||
1260 | 889 | |||
1261 | 890 | void PrinterCupsBackend::onJobLoaded(QString printerName, int jobId, | ||
1262 | 891 | QMap<QString, QVariant> attributes) | ||
1263 | 892 | { | ||
1264 | 893 | Q_UNUSED(attributes); | ||
1265 | 894 | |||
1266 | 895 | QPair<QString, int> pair(printerName, jobId); | ||
1267 | 896 | m_activeJobRequests.remove(pair); | ||
1268 | 897 | } | ||
1269 | 898 | |||
1270 | 719 | void PrinterCupsBackend::onPrinterLoaded(QSharedPointer<Printer> printer) | 899 | void PrinterCupsBackend::onPrinterLoaded(QSharedPointer<Printer> printer) |
1271 | 720 | { | 900 | { |
1273 | 721 | m_activeRequests.remove(printer->name()); | 901 | m_activePrinterRequests.remove(printer->name()); |
1274 | 722 | } | 902 | } |
1275 | 903 | |||
1276 | 723 | 904 | ||
1277 | === modified file 'modules/Ubuntu/Components/Extras/Printers/backend/backend_cups.h' | |||
1278 | --- modules/Ubuntu/Components/Extras/Printers/backend/backend_cups.h 2017-02-24 12:53:34 +0000 | |||
1279 | +++ modules/Ubuntu/Components/Extras/Printers/backend/backend_cups.h 2017-03-23 12:51:36 +0000 | |||
1280 | @@ -55,6 +55,10 @@ | |||
1281 | 55 | const QString &name, | 55 | const QString &name, |
1282 | 56 | const bool accept, | 56 | const bool accept, |
1283 | 57 | const QString &reason = QString::null) override; | 57 | const QString &reason = QString::null) override; |
1284 | 58 | virtual QString printerSetCopies( | ||
1285 | 59 | const QString &name, const int &copies) override; | ||
1286 | 60 | virtual QString printerSetShared(const QString &name, | ||
1287 | 61 | const bool shared) override; | ||
1288 | 58 | virtual QString printerSetInfo(const QString &name, | 62 | virtual QString printerSetInfo(const QString &name, |
1289 | 59 | const QString &info) override; | 63 | const QString &info) override; |
1290 | 60 | virtual QString printerAddOption(const QString &name, | 64 | virtual QString printerAddOption(const QString &name, |
1291 | @@ -71,15 +75,20 @@ | |||
1292 | 71 | const PrinterJob *options) override; | 75 | const PrinterJob *options) override; |
1293 | 72 | 76 | ||
1294 | 73 | virtual void cancelJob(const QString &name, const int jobId) override; | 77 | virtual void cancelJob(const QString &name, const int jobId) override; |
1295 | 78 | virtual void holdJob(const QString &name, const int jobId) override; | ||
1296 | 79 | virtual void releaseJob(const QString &name, const int jobId) override; | ||
1297 | 74 | virtual int printFileToDest(const QString &filepath, | 80 | virtual int printFileToDest(const QString &filepath, |
1298 | 75 | const QString &title, | 81 | const QString &title, |
1299 | 76 | const cups_dest_t *dest) override; | 82 | const cups_dest_t *dest) override; |
1300 | 77 | virtual QList<QSharedPointer<PrinterJob>> printerGetJobs() override; | 83 | virtual QList<QSharedPointer<PrinterJob>> printerGetJobs() override; |
1301 | 84 | virtual QSharedPointer<PrinterJob> printerGetJob( | ||
1302 | 85 | const QString &printerName, const int jobId) override; | ||
1303 | 78 | 86 | ||
1304 | 79 | virtual QString printerName() const override; | 87 | virtual QString printerName() const override; |
1305 | 80 | virtual QString description() const override; | 88 | virtual QString description() const override; |
1306 | 81 | virtual QString location() const override; | 89 | virtual QString location() const override; |
1307 | 82 | virtual QString makeAndModel() const override; | 90 | virtual QString makeAndModel() const override; |
1308 | 91 | virtual bool isRemote() const override; | ||
1309 | 83 | 92 | ||
1310 | 84 | virtual PrinterEnum::State state() const override; | 93 | virtual PrinterEnum::State state() const override; |
1311 | 85 | virtual QList<QPageSize> supportedPageSizes() const override; | 94 | virtual QList<QPageSize> supportedPageSizes() const override; |
1312 | @@ -96,6 +105,10 @@ | |||
1313 | 96 | virtual QStringList availablePrinterNames() override; | 105 | virtual QStringList availablePrinterNames() override; |
1314 | 97 | virtual QSharedPointer<Printer> getPrinter(const QString &printerName) override; | 106 | virtual QSharedPointer<Printer> getPrinter(const QString &printerName) override; |
1315 | 98 | virtual QString defaultPrinterName() override; | 107 | virtual QString defaultPrinterName() override; |
1316 | 108 | |||
1317 | 109 | virtual void requestJobExtendedAttributes( | ||
1318 | 110 | QSharedPointer<Printer> printer, | ||
1319 | 111 | QSharedPointer<PrinterJob> job) override; | ||
1320 | 99 | virtual void requestPrinterDrivers() override; | 112 | virtual void requestPrinterDrivers() override; |
1321 | 100 | virtual void requestPrinter(const QString &printerName) override; | 113 | virtual void requestPrinter(const QString &printerName) override; |
1322 | 101 | virtual QMap<QString, QVariant> printerGetJobAttributes( | 114 | virtual QMap<QString, QVariant> printerGetJobAttributes( |
1323 | @@ -105,6 +118,11 @@ | |||
1324 | 105 | virtual void refresh() override; | 118 | virtual void refresh() override; |
1325 | 106 | void createSubscription(); | 119 | void createSubscription(); |
1326 | 107 | 120 | ||
1327 | 121 | /* Starts a search for devices. Devices are synonymous with network devices | ||
1328 | 122 | that may potentially be queues. This search will take at minimum 5 seconds, | ||
1329 | 123 | normally longer. */ | ||
1330 | 124 | void searchForDevices(); | ||
1331 | 125 | |||
1332 | 108 | Q_SIGNALS: | 126 | Q_SIGNALS: |
1333 | 109 | void cancelWorkers(); | 127 | void cancelWorkers(); |
1334 | 110 | void printerDriversLoaded(const QList<PrinterDriver> &drivers); | 128 | void printerDriversLoaded(const QList<PrinterDriver> &drivers); |
1335 | @@ -120,16 +138,22 @@ | |||
1336 | 120 | QString getPrinterInstance(const QString &name) const; | 138 | QString getPrinterInstance(const QString &name) const; |
1337 | 121 | cups_dest_t* getDest(const QString &name) const; | 139 | cups_dest_t* getDest(const QString &name) const; |
1338 | 122 | ppd_file_t* getPpd(const QString &name) const; | 140 | ppd_file_t* getPpd(const QString &name) const; |
1339 | 141 | bool isExtendedAttribute(const QString &attributeName) const; | ||
1340 | 142 | |||
1341 | 123 | const QStringList m_knownQualityOptions; | 143 | const QStringList m_knownQualityOptions; |
1342 | 144 | const QStringList m_extendedAttributeNames; | ||
1343 | 124 | IppClient *m_client; | 145 | IppClient *m_client; |
1344 | 125 | QPrinterInfo m_info; | 146 | QPrinterInfo m_info; |
1345 | 126 | OrgCupsCupsdNotifierInterface *m_notifier; | 147 | OrgCupsCupsdNotifierInterface *m_notifier; |
1346 | 127 | int m_cupsSubscriptionId; | 148 | int m_cupsSubscriptionId; |
1347 | 128 | mutable QMap<QString, cups_dest_t*> m_dests; // Printer name, dest. | 149 | mutable QMap<QString, cups_dest_t*> m_dests; // Printer name, dest. |
1348 | 129 | mutable QMap<QString, ppd_file_t*> m_ppds; // Printer name, ppd. | 150 | mutable QMap<QString, ppd_file_t*> m_ppds; // Printer name, ppd. |
1350 | 130 | QSet<QString> m_activeRequests; | 151 | QSet<QString> m_activePrinterRequests; |
1351 | 152 | QSet<QPair<QString, int>> m_activeJobRequests; | ||
1352 | 131 | 153 | ||
1353 | 132 | private Q_SLOTS: | 154 | private Q_SLOTS: |
1354 | 155 | void onJobLoaded(QString printerName, int jobId, | ||
1355 | 156 | QMap<QString, QVariant> attributes); | ||
1356 | 133 | void onPrinterLoaded(QSharedPointer<Printer> printer); | 157 | void onPrinterLoaded(QSharedPointer<Printer> printer); |
1357 | 134 | }; | 158 | }; |
1358 | 135 | 159 | ||
1359 | 136 | 160 | ||
1360 | === modified file 'modules/Ubuntu/Components/Extras/Printers/backend/backend_pdf.cpp' | |||
1361 | --- modules/Ubuntu/Components/Extras/Printers/backend/backend_pdf.cpp 2017-02-21 10:46:29 +0000 | |||
1362 | +++ modules/Ubuntu/Components/Extras/Printers/backend/backend_pdf.cpp 2017-03-23 12:51:36 +0000 | |||
1363 | @@ -59,6 +59,16 @@ | |||
1364 | 59 | ret[option] = QVariant::fromValue(models); | 59 | ret[option] = QVariant::fromValue(models); |
1365 | 60 | } else if (option == QLatin1String("AcceptJobs")) { | 60 | } else if (option == QLatin1String("AcceptJobs")) { |
1366 | 61 | ret[option] = true; | 61 | ret[option] = true; |
1367 | 62 | } else if (option == QLatin1String("StateReasons")) { | ||
1368 | 63 | ret[option] = QLatin1String(""); | ||
1369 | 64 | } else if (option == QLatin1String("StateMessage")) { | ||
1370 | 65 | ret[option] = QLatin1String(""); | ||
1371 | 66 | } else if (option == QLatin1String("DeviceUri")) { | ||
1372 | 67 | ret[option] = QLatin1String(""); | ||
1373 | 68 | } else if (option == QLatin1String("Copies")) { | ||
1374 | 69 | ret[option] = 0; | ||
1375 | 70 | } else if (option == QLatin1String("Shared")) { | ||
1376 | 71 | ret[option] = false; | ||
1377 | 62 | } else { | 72 | } else { |
1378 | 63 | throw std::invalid_argument("Invalid value for PDF printer: " + option.toStdString()); | 73 | throw std::invalid_argument("Invalid value for PDF printer: " + option.toStdString()); |
1379 | 64 | } | 74 | } |
1380 | 65 | 75 | ||
1381 | === added file 'modules/Ubuntu/Components/Extras/Printers/cups/devicesearcher.cpp' | |||
1382 | --- modules/Ubuntu/Components/Extras/Printers/cups/devicesearcher.cpp 1970-01-01 00:00:00 +0000 | |||
1383 | +++ modules/Ubuntu/Components/Extras/Printers/cups/devicesearcher.cpp 2017-03-23 12:51:36 +0000 | |||
1384 | @@ -0,0 +1,70 @@ | |||
1385 | 1 | /* | ||
1386 | 2 | * Copyright (C) 2017 Canonical, Ltd. | ||
1387 | 3 | * | ||
1388 | 4 | * This program is free software; you can redistribute it and/or modify | ||
1389 | 5 | * it under the terms of the GNU Lesser General Public License as published by | ||
1390 | 6 | * the Free Software Foundation; version 3. | ||
1391 | 7 | * | ||
1392 | 8 | * This program is distributed in the hope that it will be useful, | ||
1393 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1394 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1395 | 11 | * GNU Lesser General Public License for more details. | ||
1396 | 12 | * | ||
1397 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
1398 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1399 | 15 | */ | ||
1400 | 16 | |||
1401 | 17 | #include "cups/ippclient.h" | ||
1402 | 18 | #include "devicesearcher.h" | ||
1403 | 19 | |||
1404 | 20 | #include <QUrl> | ||
1405 | 21 | |||
1406 | 22 | DeviceSearcher::DeviceSearcher(IppClient *client, QObject *parent) | ||
1407 | 23 | : QObject(parent) | ||
1408 | 24 | , m_client(client) | ||
1409 | 25 | { | ||
1410 | 26 | } | ||
1411 | 27 | |||
1412 | 28 | DeviceSearcher::~DeviceSearcher() | ||
1413 | 29 | { | ||
1414 | 30 | delete m_client; | ||
1415 | 31 | } | ||
1416 | 32 | |||
1417 | 33 | void DeviceSearcher::load() | ||
1418 | 34 | { | ||
1419 | 35 | if (!m_client->getDevices(&DeviceSearcher::deviceCallBack, this)) { | ||
1420 | 36 | Q_EMIT failed(cupsLastErrorString()); | ||
1421 | 37 | } | ||
1422 | 38 | Q_EMIT finished(); | ||
1423 | 39 | } | ||
1424 | 40 | |||
1425 | 41 | void DeviceSearcher::deviceCallBack( | ||
1426 | 42 | const char *deviceClass, | ||
1427 | 43 | const char *deviceId, | ||
1428 | 44 | const char *deviceInfo, | ||
1429 | 45 | const char *deviceMakeAndModel, | ||
1430 | 46 | const char *deviceUri, | ||
1431 | 47 | const char *deviceLocation, | ||
1432 | 48 | void *context) | ||
1433 | 49 | { | ||
1434 | 50 | auto searcher = qobject_cast<DeviceSearcher*>(static_cast<QObject*>(context)); | ||
1435 | 51 | if (!searcher) { | ||
1436 | 52 | qWarning() << Q_FUNC_INFO << "context was not a DeviceSearcher."; | ||
1437 | 53 | return; | ||
1438 | 54 | } | ||
1439 | 55 | |||
1440 | 56 | Device d; | ||
1441 | 57 | d.cls = deviceClass; | ||
1442 | 58 | d.id = deviceId; | ||
1443 | 59 | d.info = deviceInfo; | ||
1444 | 60 | d.makeModel = deviceMakeAndModel; | ||
1445 | 61 | d.uri = deviceUri; | ||
1446 | 62 | d.location = deviceLocation; | ||
1447 | 63 | |||
1448 | 64 | searcher->deviceFound(d); | ||
1449 | 65 | } | ||
1450 | 66 | |||
1451 | 67 | void DeviceSearcher::deviceFound(const Device &device) | ||
1452 | 68 | { | ||
1453 | 69 | Q_EMIT loaded(device); | ||
1454 | 70 | } | ||
1455 | 0 | 71 | ||
1456 | === added file 'modules/Ubuntu/Components/Extras/Printers/cups/devicesearcher.h' | |||
1457 | --- modules/Ubuntu/Components/Extras/Printers/cups/devicesearcher.h 1970-01-01 00:00:00 +0000 | |||
1458 | +++ modules/Ubuntu/Components/Extras/Printers/cups/devicesearcher.h 2017-03-23 12:51:36 +0000 | |||
1459 | @@ -0,0 +1,57 @@ | |||
1460 | 1 | /* | ||
1461 | 2 | * Copyright (C) 2017 Canonical, Ltd. | ||
1462 | 3 | * | ||
1463 | 4 | * This program is free software; you can redistribute it and/or modify | ||
1464 | 5 | * it under the terms of the GNU Lesser General Public License as published by | ||
1465 | 6 | * the Free Software Foundation; version 3. | ||
1466 | 7 | * | ||
1467 | 8 | * This program is distributed in the hope that it will be useful, | ||
1468 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1469 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1470 | 11 | * GNU Lesser General Public License for more details. | ||
1471 | 12 | * | ||
1472 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
1473 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1474 | 15 | */ | ||
1475 | 16 | |||
1476 | 17 | #ifndef USC_PRINTERS_CUPS_DEVICESEARCHER_H | ||
1477 | 18 | #define USC_PRINTERS_CUPS_DEVICESEARCHER_H | ||
1478 | 19 | |||
1479 | 20 | #include "cups/ippclient.h" | ||
1480 | 21 | #include "structs.h" | ||
1481 | 22 | |||
1482 | 23 | #include <QObject> | ||
1483 | 24 | #include <QString> | ||
1484 | 25 | |||
1485 | 26 | /* Class representing a device search. It is a worker object due to the time | ||
1486 | 27 | such a search takes (minimum 10 seconds). */ | ||
1487 | 28 | class DeviceSearcher : public QObject | ||
1488 | 29 | { | ||
1489 | 30 | Q_OBJECT | ||
1490 | 31 | IppClient *m_client; | ||
1491 | 32 | public: | ||
1492 | 33 | explicit DeviceSearcher(IppClient *client = new IppClient, | ||
1493 | 34 | QObject *parent = Q_NULLPTR); | ||
1494 | 35 | ~DeviceSearcher(); | ||
1495 | 36 | |||
1496 | 37 | public Q_SLOTS: | ||
1497 | 38 | void load(); | ||
1498 | 39 | |||
1499 | 40 | private: | ||
1500 | 41 | static void deviceCallBack( | ||
1501 | 42 | const char *cls, | ||
1502 | 43 | const char *id, | ||
1503 | 44 | const char *info, | ||
1504 | 45 | const char *makeAndModel, | ||
1505 | 46 | const char *uri, | ||
1506 | 47 | const char *location, | ||
1507 | 48 | void *context); | ||
1508 | 49 | void deviceFound(const Device &device); | ||
1509 | 50 | |||
1510 | 51 | Q_SIGNALS: | ||
1511 | 52 | void loaded(const Device &device); | ||
1512 | 53 | void failed(const QString &errorMessage); | ||
1513 | 54 | void finished(); | ||
1514 | 55 | }; | ||
1515 | 56 | |||
1516 | 57 | #endif // USC_PRINTERS_CUPS_DEVICESEARCHER_H | ||
1517 | 0 | 58 | ||
1518 | === modified file 'modules/Ubuntu/Components/Extras/Printers/cups/ippclient.cpp' | |||
1519 | --- modules/Ubuntu/Components/Extras/Printers/cups/ippclient.cpp 2017-02-21 10:46:29 +0000 | |||
1520 | +++ modules/Ubuntu/Components/Extras/Printers/cups/ippclient.cpp 2017-03-23 12:51:36 +0000 | |||
1521 | @@ -25,6 +25,7 @@ | |||
1522 | 25 | 25 | ||
1523 | 26 | #include <QDebug> | 26 | #include <QDebug> |
1524 | 27 | #include <QDateTime> | 27 | #include <QDateTime> |
1525 | 28 | #include <QtAlgorithms> | ||
1526 | 28 | #include <QTimeZone> | 29 | #include <QTimeZone> |
1527 | 29 | #include <QUrl> | 30 | #include <QUrl> |
1528 | 30 | 31 | ||
1529 | @@ -173,6 +174,30 @@ | |||
1530 | 173 | return postRequest(request, ppdFileName.toUtf8(), CupsResourceAdmin); | 174 | return postRequest(request, ppdFileName.toUtf8(), CupsResourceAdmin); |
1531 | 174 | } | 175 | } |
1532 | 175 | 176 | ||
1533 | 177 | bool IppClient::printerHoldJob(const QString &printerName, const int jobId) | ||
1534 | 178 | { | ||
1535 | 179 | ipp_t *request = ippNewRequest(IPP_HOLD_JOB); | ||
1536 | 180 | addPrinterUri(request, printerName); | ||
1537 | 181 | addRequestingUsername(request, NULL); | ||
1538 | 182 | |||
1539 | 183 | ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, | ||
1540 | 184 | "job-id", jobId); | ||
1541 | 185 | |||
1542 | 186 | return sendRequest(request, CupsResourceJobs); | ||
1543 | 187 | } | ||
1544 | 188 | |||
1545 | 189 | bool IppClient::printerReleaseJob(const QString &printerName, const int jobId) | ||
1546 | 190 | { | ||
1547 | 191 | ipp_t *request = ippNewRequest(IPP_RELEASE_JOB); | ||
1548 | 192 | addPrinterUri(request, printerName); | ||
1549 | 193 | addRequestingUsername(request, NULL); | ||
1550 | 194 | |||
1551 | 195 | ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, | ||
1552 | 196 | "job-id", jobId); | ||
1553 | 197 | |||
1554 | 198 | return sendRequest(request, CupsResourceJobs); | ||
1555 | 199 | } | ||
1556 | 200 | |||
1557 | 176 | bool IppClient::printerSetDefault(const QString &printerName) | 201 | bool IppClient::printerSetDefault(const QString &printerName) |
1558 | 177 | { | 202 | { |
1559 | 178 | return sendNewSimpleRequest(CUPS_SET_DEFAULT, printerName.toUtf8(), | 203 | return sendNewSimpleRequest(CUPS_SET_DEFAULT, printerName.toUtf8(), |
1560 | @@ -225,9 +250,46 @@ | |||
1561 | 225 | } | 250 | } |
1562 | 226 | } | 251 | } |
1563 | 227 | 252 | ||
1564 | 253 | bool IppClient::printerSetCopies(const QString &printerName, const int &copies) | ||
1565 | 254 | { | ||
1566 | 255 | ipp_t *request; | ||
1567 | 256 | |||
1568 | 257 | if (!isPrinterNameValid(printerName)) { | ||
1569 | 258 | setInternalStatus(QString("%1 is not a valid printer name.").arg(printerName)); | ||
1570 | 259 | return false; | ||
1571 | 260 | } | ||
1572 | 261 | request = ippNewRequest(CUPS_ADD_MODIFY_PRINTER); | ||
1573 | 262 | addPrinterUri(request, printerName); | ||
1574 | 263 | addRequestingUsername(request, NULL); | ||
1575 | 264 | ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_INTEGER, | ||
1576 | 265 | "copies-default", copies); | ||
1577 | 266 | /* TODO: The request will fail if this was a printer class, and it should | ||
1578 | 267 | be retried. */ | ||
1579 | 268 | return sendRequest(request, CupsResourceAdmin); | ||
1580 | 269 | } | ||
1581 | 270 | |||
1582 | 271 | bool IppClient::printerSetShared(const QString &printerName, const bool shared) | ||
1583 | 272 | { | ||
1584 | 273 | ipp_t *request; | ||
1585 | 274 | |||
1586 | 275 | if (!isPrinterNameValid(printerName)) { | ||
1587 | 276 | setInternalStatus(QString("%1 is not a valid printer name.").arg(printerName)); | ||
1588 | 277 | return false; | ||
1589 | 278 | } | ||
1590 | 279 | |||
1591 | 280 | request = ippNewRequest(CUPS_ADD_MODIFY_PRINTER); | ||
1592 | 281 | addPrinterUri(request, printerName); | ||
1593 | 282 | addRequestingUsername(request, NULL); | ||
1594 | 283 | ippAddBoolean(request, IPP_TAG_OPERATION, | ||
1595 | 284 | "printer-is-shared", shared ? 1 : 0); | ||
1596 | 285 | /* TODO: The request will fail if this was a printer class, and it should | ||
1597 | 286 | be retried. */ | ||
1598 | 287 | |||
1599 | 288 | return sendRequest(request, CupsResourceAdmin); | ||
1600 | 289 | } | ||
1601 | 228 | 290 | ||
1602 | 229 | bool IppClient::printerClassSetInfo(const QString &name, | 291 | bool IppClient::printerClassSetInfo(const QString &name, |
1604 | 230 | const QString &info) | 292 | const QString &info) |
1605 | 231 | { | 293 | { |
1606 | 232 | if (!isPrinterNameValid(name)) { | 294 | if (!isPrinterNameValid(name)) { |
1607 | 233 | setInternalStatus(QString("%1 is not a valid printer name.").arg(name)); | 295 | setInternalStatus(QString("%1 is not a valid printer name.").arg(name)); |
1608 | @@ -336,18 +398,99 @@ | |||
1609 | 336 | return retval; | 398 | return retval; |
1610 | 337 | } | 399 | } |
1611 | 338 | 400 | ||
1613 | 339 | QMap<QString, QVariant> IppClient::printerGetJobAttributes(const int jobId) | 401 | QMap<QString, QVariant> IppClient::printerGetAttributes( |
1614 | 402 | const QString &printerName, const QStringList &attributes) | ||
1615 | 403 | { | ||
1616 | 404 | QMap<QString, QVariant> result; | ||
1617 | 405 | QList<QByteArray*> attrByteArrays; | ||
1618 | 406 | ipp_t *request; | ||
1619 | 407 | ipp_attribute_t *attr; | ||
1620 | 408 | |||
1621 | 409 | if (attributes.isEmpty()) { | ||
1622 | 410 | return result; | ||
1623 | 411 | } | ||
1624 | 412 | |||
1625 | 413 | int i; | ||
1626 | 414 | size_t n = attributes.size(); | ||
1627 | 415 | char **attrs; | ||
1628 | 416 | attrs = (char**) malloc ((n + 1) * sizeof (char *)); | ||
1629 | 417 | |||
1630 | 418 | /* This is some trickery to compensate for a lack of C array/pointer | ||
1631 | 419 | skills. The VLA attrs gets the underlying data structure of a QByterArray | ||
1632 | 420 | on the heap. When cups is done with it, and in the end of this method, | ||
1633 | 421 | the QByteArrays are deleted, and attrs is freed. */ | ||
1634 | 422 | for (i = 0; i < ((int) n); i++) { | ||
1635 | 423 | QByteArray *array = new QByteArray(attributes.value(i).toLocal8Bit()); | ||
1636 | 424 | attrByteArrays << array; | ||
1637 | 425 | attrs[i] = array->data(); | ||
1638 | 426 | } | ||
1639 | 427 | attrs[n] = NULL; | ||
1640 | 428 | |||
1641 | 429 | request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES); | ||
1642 | 430 | addPrinterUri(request, printerName); | ||
1643 | 431 | addRequestingUsername(request, QString()); | ||
1644 | 432 | ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, | ||
1645 | 433 | "requested-attributes", attributes.size(), NULL, attrs); | ||
1646 | 434 | auto resource = getResource(CupsResource::CupsResourceRoot); | ||
1647 | 435 | |||
1648 | 436 | ipp_t *reply; | ||
1649 | 437 | reply = cupsDoRequest(m_connection, request, resource.toUtf8()); | ||
1650 | 438 | |||
1651 | 439 | if (!isReplyOk(reply, false)) { | ||
1652 | 440 | qWarning() << Q_FUNC_INFO << "failed to get attributes" | ||
1653 | 441 | << attributes << "for printer" << printerName; | ||
1654 | 442 | } else { | ||
1655 | 443 | for (attr = ippFirstAttribute(reply); attr; attr = ippNextAttribute(reply)) { | ||
1656 | 444 | while (attr && ippGetGroupTag(attr) != IPP_TAG_PRINTER) | ||
1657 | 445 | attr = ippNextAttribute(reply); | ||
1658 | 446 | |||
1659 | 447 | if (!attr) | ||
1660 | 448 | break; | ||
1661 | 449 | |||
1662 | 450 | for (; attr && ippGetGroupTag(attr) == IPP_TAG_PRINTER; | ||
1663 | 451 | attr = ippNextAttribute(reply)) { | ||
1664 | 452 | |||
1665 | 453 | /* TODO: Here we need to take into account that the returned | ||
1666 | 454 | attributes could be lists and other things. */ | ||
1667 | 455 | result[ippGetName(attr)] = getAttributeValue(attr); | ||
1668 | 456 | |||
1669 | 457 | if (!attr) | ||
1670 | 458 | break; | ||
1671 | 459 | } | ||
1672 | 460 | } | ||
1673 | 461 | } | ||
1674 | 462 | |||
1675 | 463 | if (reply) | ||
1676 | 464 | ippDelete(reply); | ||
1677 | 465 | |||
1678 | 466 | qDeleteAll(attrByteArrays); | ||
1679 | 467 | free(attrs); | ||
1680 | 468 | |||
1681 | 469 | return result; | ||
1682 | 470 | } | ||
1683 | 471 | |||
1684 | 472 | QMap<QString, QVariant> IppClient::printerGetJobAttributes(const QString &printerName, | ||
1685 | 473 | const int jobId) | ||
1686 | 340 | { | 474 | { |
1687 | 341 | ipp_t *request; | 475 | ipp_t *request; |
1688 | 342 | QMap<QString, QVariant> map; | 476 | QMap<QString, QVariant> map; |
1689 | 343 | 477 | ||
1690 | 478 | // Try to get the lock, if we can't after 5 seconds then fail and return | ||
1691 | 479 | if (!m_thread_lock.tryLock(5000)) { | ||
1692 | 480 | qWarning() << "Unable to get lock for IppClient::printerGetJobAttributes." | ||
1693 | 481 | << "Unable to load attributes for job:" << jobId << " for " | ||
1694 | 482 | << printerName; | ||
1695 | 483 | return map; | ||
1696 | 484 | } | ||
1697 | 485 | |||
1698 | 344 | // Construct request | 486 | // Construct request |
1699 | 345 | request = ippNewRequest(IPP_GET_JOB_ATTRIBUTES); | 487 | request = ippNewRequest(IPP_GET_JOB_ATTRIBUTES); |
1705 | 346 | QString uri = QStringLiteral("ipp://localhost/jobs/") + QString::number(jobId); | 488 | |
1706 | 347 | qDebug() << "URI:" << uri; | 489 | addPrinterUri(request, printerName); |
1707 | 348 | 490 | addRequestingUsername(request, NULL); | |
1708 | 349 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri.toStdString().data()); | 491 | |
1709 | 350 | 492 | ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, | |
1710 | 493 | "job-id", jobId); | ||
1711 | 351 | 494 | ||
1712 | 352 | // Send request and construct reply | 495 | // Send request and construct reply |
1713 | 353 | ipp_t *reply; | 496 | ipp_t *reply; |
1714 | @@ -365,7 +508,8 @@ | |||
1715 | 365 | map.insert(ippGetName(attr), value); | 508 | map.insert(ippGetName(attr), value); |
1716 | 366 | } | 509 | } |
1717 | 367 | } else { | 510 | } else { |
1719 | 368 | qWarning() << "Not able to get attributes of job:" << jobId; | 511 | qWarning() << "Not able to get attributes of job:" << jobId << " for " |
1720 | 512 | << printerName; | ||
1721 | 369 | } | 513 | } |
1722 | 370 | 514 | ||
1723 | 371 | // Destruct the reply if valid | 515 | // Destruct the reply if valid |
1724 | @@ -373,6 +517,8 @@ | |||
1725 | 373 | ippDelete(reply); | 517 | ippDelete(reply); |
1726 | 374 | } | 518 | } |
1727 | 375 | 519 | ||
1728 | 520 | m_thread_lock.unlock(); | ||
1729 | 521 | |||
1730 | 376 | return map; | 522 | return map; |
1731 | 377 | } | 523 | } |
1732 | 378 | 524 | ||
1733 | @@ -972,8 +1118,8 @@ | |||
1734 | 972 | case IPP_TAG_DATE: { | 1118 | case IPP_TAG_DATE: { |
1735 | 973 | time_t time = ippDateToTime(ippGetDate(attr, index)); | 1119 | time_t time = ippDateToTime(ippGetDate(attr, index)); |
1736 | 974 | QDateTime datetime; | 1120 | QDateTime datetime; |
1737 | 975 | datetime.setTimeZone(QTimeZone::systemTimeZone()); | ||
1738 | 976 | datetime.setTime_t(time); | 1121 | datetime.setTime_t(time); |
1739 | 1122 | datetime.setTimeZone(QTimeZone::utc()); | ||
1740 | 977 | 1123 | ||
1741 | 978 | var = QVariant::fromValue<QDateTime>(datetime); | 1124 | var = QVariant::fromValue<QDateTime>(datetime); |
1742 | 979 | break; | 1125 | break; |
1743 | @@ -986,3 +1132,11 @@ | |||
1744 | 986 | 1132 | ||
1745 | 987 | return var; | 1133 | return var; |
1746 | 988 | } | 1134 | } |
1747 | 1135 | |||
1748 | 1136 | bool IppClient::getDevices(cups_device_cb_t callback, void *context) const | ||
1749 | 1137 | { | ||
1750 | 1138 | auto reply = cupsGetDevices(m_connection, CUPS_TIMEOUT_DEFAULT, | ||
1751 | 1139 | CUPS_INCLUDE_ALL, CUPS_EXCLUDE_NONE, callback, | ||
1752 | 1140 | context); | ||
1753 | 1141 | return reply == IPP_OK; | ||
1754 | 1142 | } | ||
1755 | 989 | 1143 | ||
1756 | === modified file 'modules/Ubuntu/Components/Extras/Printers/cups/ippclient.h' | |||
1757 | --- modules/Ubuntu/Components/Extras/Printers/cups/ippclient.h 2017-02-21 10:46:29 +0000 | |||
1758 | +++ modules/Ubuntu/Components/Extras/Printers/cups/ippclient.h 2017-03-23 12:51:36 +0000 | |||
1759 | @@ -19,11 +19,13 @@ | |||
1760 | 19 | 19 | ||
1761 | 20 | #include "structs.h" | 20 | #include "structs.h" |
1762 | 21 | 21 | ||
1763 | 22 | #include <cups/adminutil.h> | ||
1764 | 22 | #include <cups/cups.h> | 23 | #include <cups/cups.h> |
1765 | 23 | #include <cups/http.h> | 24 | #include <cups/http.h> |
1766 | 24 | #include <cups/ipp.h> | 25 | #include <cups/ipp.h> |
1767 | 25 | #include <cups/ppd.h> | 26 | #include <cups/ppd.h> |
1768 | 26 | 27 | ||
1769 | 28 | #include <QMutex> | ||
1770 | 27 | #include <QString> | 29 | #include <QString> |
1771 | 28 | #include <QStringList> | 30 | #include <QStringList> |
1772 | 29 | 31 | ||
1773 | @@ -51,17 +53,25 @@ | |||
1774 | 51 | const QString &ppdFileName, | 53 | const QString &ppdFileName, |
1775 | 52 | const QString &info, | 54 | const QString &info, |
1776 | 53 | const QString &location); | 55 | const QString &location); |
1777 | 56 | bool printerHoldJob(const QString &printerName, const int jobId); | ||
1778 | 57 | bool printerReleaseJob(const QString &printerName, const int jobId); | ||
1779 | 54 | bool printerSetDefault(const QString &printerName); | 58 | bool printerSetDefault(const QString &printerName); |
1780 | 55 | bool printerSetEnabled(const QString &printerName, const bool enabled); | 59 | bool printerSetEnabled(const QString &printerName, const bool enabled); |
1781 | 56 | bool printerSetAcceptJobs(const QString &printerName, const bool accept, | 60 | bool printerSetAcceptJobs(const QString &printerName, const bool accept, |
1782 | 57 | const QString &reason); | 61 | const QString &reason); |
1783 | 62 | bool printerSetCopies(const QString &printerName, const int &copies); | ||
1784 | 63 | bool printerSetShared(const QString &printerName, const bool shared); | ||
1785 | 58 | bool printerClassSetInfo(const QString &name, const QString &info); | 64 | bool printerClassSetInfo(const QString &name, const QString &info); |
1786 | 59 | bool printerClassSetOption(const QString &name, const QString &option, | 65 | bool printerClassSetOption(const QString &name, const QString &option, |
1787 | 60 | const QStringList &values); | 66 | const QStringList &values); |
1788 | 61 | ppd_file_t* getPpdFile(const QString &name, const QString &instance) const; | 67 | ppd_file_t* getPpdFile(const QString &name, const QString &instance) const; |
1789 | 62 | cups_dest_t* getDest(const QString &name, const QString &instance) const; | 68 | cups_dest_t* getDest(const QString &name, const QString &instance) const; |
1790 | 63 | 69 | ||
1792 | 64 | QMap<QString, QVariant> printerGetJobAttributes(const int jobId); | 70 | // Fetch more attributes, as normally just a small subset is fetched. |
1793 | 71 | QMap<QString, QVariant> printerGetAttributes(const QString &printerName, | ||
1794 | 72 | const QStringList &attributes); | ||
1795 | 73 | QMap<QString, QVariant> printerGetJobAttributes(const QString &printerName, | ||
1796 | 74 | const int jobId); | ||
1797 | 65 | 75 | ||
1798 | 66 | QString getLastError() const; | 76 | QString getLastError() const; |
1799 | 67 | 77 | ||
1800 | @@ -73,6 +83,7 @@ | |||
1801 | 73 | ); | 83 | ); |
1802 | 74 | int createSubscription(); | 84 | int createSubscription(); |
1803 | 75 | void cancelSubscription(const int &subscriptionId); | 85 | void cancelSubscription(const int &subscriptionId); |
1804 | 86 | bool getDevices(cups_device_cb_t callback, void *context) const; | ||
1805 | 76 | 87 | ||
1806 | 77 | private: | 88 | private: |
1807 | 78 | enum CupsResource | 89 | enum CupsResource |
1808 | @@ -115,6 +126,7 @@ | |||
1809 | 115 | http_t *m_connection; | 126 | http_t *m_connection; |
1810 | 116 | ipp_status_t m_lastStatus = IPP_OK; | 127 | ipp_status_t m_lastStatus = IPP_OK; |
1811 | 117 | mutable QString m_internalStatus = QString::null; | 128 | mutable QString m_internalStatus = QString::null; |
1812 | 129 | QMutex m_thread_lock; | ||
1813 | 118 | }; | 130 | }; |
1814 | 119 | 131 | ||
1815 | 120 | 132 | ||
1816 | 121 | 133 | ||
1817 | === added file 'modules/Ubuntu/Components/Extras/Printers/cups/jobloader.cpp' | |||
1818 | --- modules/Ubuntu/Components/Extras/Printers/cups/jobloader.cpp 1970-01-01 00:00:00 +0000 | |||
1819 | +++ modules/Ubuntu/Components/Extras/Printers/cups/jobloader.cpp 2017-03-23 12:51:36 +0000 | |||
1820 | @@ -0,0 +1,50 @@ | |||
1821 | 1 | /* | ||
1822 | 2 | * Copyright (C) 2017 Canonical, Ltd. | ||
1823 | 3 | * | ||
1824 | 4 | * This program is free software; you can redistribute it and/or modify | ||
1825 | 5 | * it under the terms of the GNU Lesser General Public License as published by | ||
1826 | 6 | * the Free Software Foundation; version 3. | ||
1827 | 7 | * | ||
1828 | 8 | * This program is distributed in the hope that it will be useful, | ||
1829 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1830 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1831 | 11 | * GNU Lesser General Public License for more details. | ||
1832 | 12 | * | ||
1833 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
1834 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1835 | 15 | */ | ||
1836 | 16 | |||
1837 | 17 | #include "jobloader.h" | ||
1838 | 18 | |||
1839 | 19 | #include "backend/backend.h" | ||
1840 | 20 | |||
1841 | 21 | #include "printers/printers.h" | ||
1842 | 22 | |||
1843 | 23 | #include <QDBusConnection> | ||
1844 | 24 | #include <QPrinterInfo> | ||
1845 | 25 | |||
1846 | 26 | class PrinterCupsBackend; | ||
1847 | 27 | JobLoader::JobLoader(PrinterBackend *backend, | ||
1848 | 28 | QString printerName, | ||
1849 | 29 | int jobId, | ||
1850 | 30 | QObject *parent) | ||
1851 | 31 | : QObject(parent) | ||
1852 | 32 | , m_backend(backend) | ||
1853 | 33 | , m_job_id(jobId) | ||
1854 | 34 | , m_printer_name(printerName) | ||
1855 | 35 | { | ||
1856 | 36 | } | ||
1857 | 37 | |||
1858 | 38 | JobLoader::~JobLoader() | ||
1859 | 39 | { | ||
1860 | 40 | } | ||
1861 | 41 | |||
1862 | 42 | void JobLoader::load() | ||
1863 | 43 | { | ||
1864 | 44 | QMap<QString, QVariant> map = m_backend->printerGetJobAttributes( | ||
1865 | 45 | m_printer_name, m_job_id | ||
1866 | 46 | ); | ||
1867 | 47 | |||
1868 | 48 | Q_EMIT loaded(m_printer_name, m_job_id, map); | ||
1869 | 49 | Q_EMIT finished(); | ||
1870 | 50 | } | ||
1871 | 0 | 51 | ||
1872 | === added file 'modules/Ubuntu/Components/Extras/Printers/cups/jobloader.h' | |||
1873 | --- modules/Ubuntu/Components/Extras/Printers/cups/jobloader.h 1970-01-01 00:00:00 +0000 | |||
1874 | +++ modules/Ubuntu/Components/Extras/Printers/cups/jobloader.h 2017-03-23 12:51:36 +0000 | |||
1875 | @@ -0,0 +1,47 @@ | |||
1876 | 1 | /* | ||
1877 | 2 | * Copyright (C) 2017 Canonical, Ltd. | ||
1878 | 3 | * | ||
1879 | 4 | * This program is free software; you can redistribute it and/or modify | ||
1880 | 5 | * it under the terms of the GNU Lesser General Public License as published by | ||
1881 | 6 | * the Free Software Foundation; version 3. | ||
1882 | 7 | * | ||
1883 | 8 | * This program is distributed in the hope that it will be useful, | ||
1884 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1885 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1886 | 11 | * GNU Lesser General Public License for more details. | ||
1887 | 12 | * | ||
1888 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
1889 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1890 | 15 | */ | ||
1891 | 16 | |||
1892 | 17 | #ifndef USC_PRINTERS_CUPS_JOBLOADER_H | ||
1893 | 18 | #define USC_PRINTERS_CUPS_JOBLOADER_H | ||
1894 | 19 | |||
1895 | 20 | #include "printer/printer.h" | ||
1896 | 21 | #include "printer/printerjob.h" | ||
1897 | 22 | |||
1898 | 23 | #include <QList> | ||
1899 | 24 | #include <QObject> | ||
1900 | 25 | #include <QSharedPointer> | ||
1901 | 26 | |||
1902 | 27 | class JobLoader : public QObject | ||
1903 | 28 | { | ||
1904 | 29 | Q_OBJECT | ||
1905 | 30 | PrinterBackend *m_backend; | ||
1906 | 31 | int m_job_id; | ||
1907 | 32 | QString m_printer_name; | ||
1908 | 33 | public: | ||
1909 | 34 | explicit JobLoader(PrinterBackend *backend, | ||
1910 | 35 | QString printerName, int jobId, | ||
1911 | 36 | QObject *parent = Q_NULLPTR); | ||
1912 | 37 | ~JobLoader(); | ||
1913 | 38 | |||
1914 | 39 | public Q_SLOTS: | ||
1915 | 40 | void load(); | ||
1916 | 41 | |||
1917 | 42 | Q_SIGNALS: | ||
1918 | 43 | void finished(); | ||
1919 | 44 | void loaded(QString, int, QMap<QString, QVariant>); | ||
1920 | 45 | }; | ||
1921 | 46 | |||
1922 | 47 | #endif // USC_PRINTERS_CUPS_JOBLOADER_H | ||
1923 | 0 | 48 | ||
1924 | === modified file 'modules/Ubuntu/Components/Extras/Printers/cups/printerloader.cpp' | |||
1925 | --- modules/Ubuntu/Components/Extras/Printers/cups/printerloader.cpp 2017-02-21 10:46:29 +0000 | |||
1926 | +++ modules/Ubuntu/Components/Extras/Printers/cups/printerloader.cpp 2017-03-23 12:51:36 +0000 | |||
1927 | @@ -18,6 +18,7 @@ | |||
1928 | 18 | #include "backend/backend_cups.h" | 18 | #include "backend/backend_cups.h" |
1929 | 19 | #include "printerloader.h" | 19 | #include "printerloader.h" |
1930 | 20 | 20 | ||
1931 | 21 | #include <QApplication> | ||
1932 | 21 | #include <QPrinterInfo> | 22 | #include <QPrinterInfo> |
1933 | 22 | 23 | ||
1934 | 23 | class PrinterCupsBackend; | 24 | class PrinterCupsBackend; |
1935 | @@ -48,6 +49,8 @@ | |||
1936 | 48 | 49 | ||
1937 | 49 | auto p = QSharedPointer<Printer>(new Printer(backend)); | 50 | auto p = QSharedPointer<Printer>(new Printer(backend)); |
1938 | 50 | 51 | ||
1939 | 52 | p->moveToThread(QApplication::instance()->thread()); | ||
1940 | 53 | |||
1941 | 51 | Q_EMIT loaded(p); | 54 | Q_EMIT loaded(p); |
1942 | 52 | Q_EMIT finished(); | 55 | Q_EMIT finished(); |
1943 | 53 | } | 56 | } |
1944 | 54 | 57 | ||
1945 | === modified file 'modules/Ubuntu/Components/Extras/Printers/enums.h' | |||
1946 | --- modules/Ubuntu/Components/Extras/Printers/enums.h 2017-02-23 14:04:26 +0000 | |||
1947 | +++ modules/Ubuntu/Components/Extras/Printers/enums.h 2017-03-23 12:51:36 +0000 | |||
1948 | @@ -101,6 +101,29 @@ | |||
1949 | 101 | PdfType, | 101 | PdfType, |
1950 | 102 | }; | 102 | }; |
1951 | 103 | Q_ENUM(PrinterType) | 103 | Q_ENUM(PrinterType) |
1952 | 104 | |||
1953 | 105 | enum class DeviceType | ||
1954 | 106 | { | ||
1955 | 107 | UnknownType = 0, | ||
1956 | 108 | LPDType, | ||
1957 | 109 | IppSType, | ||
1958 | 110 | Ipp14Type, | ||
1959 | 111 | HttpType, | ||
1960 | 112 | BehType, | ||
1961 | 113 | SocketType, | ||
1962 | 114 | HttpsType, | ||
1963 | 115 | IppType, | ||
1964 | 116 | HPType, | ||
1965 | 117 | USBType, | ||
1966 | 118 | HPFaxType, | ||
1967 | 119 | DNSSDType, | ||
1968 | 120 | }; | ||
1969 | 121 | Q_ENUM(DeviceType) | ||
1970 | 104 | }; | 122 | }; |
1971 | 105 | 123 | ||
1972 | 124 | inline uint qHash(const PrinterEnum::JobState &state, uint seed) | ||
1973 | 125 | { | ||
1974 | 126 | return qHash((int) state, seed); | ||
1975 | 127 | } | ||
1976 | 128 | |||
1977 | 106 | #endif // USC_PRINTERS_ENUMS_H | 129 | #endif // USC_PRINTERS_ENUMS_H |
1978 | 107 | 130 | ||
1979 | === added file 'modules/Ubuntu/Components/Extras/Printers/models/devicemodel.cpp' | |||
1980 | --- modules/Ubuntu/Components/Extras/Printers/models/devicemodel.cpp 1970-01-01 00:00:00 +0000 | |||
1981 | +++ modules/Ubuntu/Components/Extras/Printers/models/devicemodel.cpp 2017-03-23 12:51:36 +0000 | |||
1982 | @@ -0,0 +1,149 @@ | |||
1983 | 1 | /* | ||
1984 | 2 | * Copyright (C) 2017 Canonical, Ltd. | ||
1985 | 3 | * | ||
1986 | 4 | * This program is free software; you can redistribute it and/or modify | ||
1987 | 5 | * it under the terms of the GNU Lesser General Public License as published by | ||
1988 | 6 | * the Free Software Foundation; version 3. | ||
1989 | 7 | * | ||
1990 | 8 | * This program is distributed in the hope that it will be useful, | ||
1991 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1992 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1993 | 11 | * GNU Lesser General Public License for more details. | ||
1994 | 12 | * | ||
1995 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
1996 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1997 | 15 | */ | ||
1998 | 16 | |||
1999 | 17 | #include "backend/backend_cups.h" | ||
2000 | 18 | #include "models/devicemodel.h" | ||
2001 | 19 | |||
2002 | 20 | #include <QDebug> | ||
2003 | 21 | |||
2004 | 22 | DeviceModel::DeviceModel(PrinterBackend *backend, QObject *parent) | ||
2005 | 23 | : QAbstractListModel(parent) | ||
2006 | 24 | , m_backend(backend) | ||
2007 | 25 | , m_isSearching(false) | ||
2008 | 26 | { | ||
2009 | 27 | connect(m_backend, SIGNAL(deviceFound(const Device&)), | ||
2010 | 28 | this, SLOT(deviceLoaded(const Device&))); | ||
2011 | 29 | connect(m_backend, SIGNAL(deviceSearchFinished()), | ||
2012 | 30 | this, SLOT(deviceSearchFinished())); | ||
2013 | 31 | } | ||
2014 | 32 | |||
2015 | 33 | DeviceModel::~DeviceModel() | ||
2016 | 34 | { | ||
2017 | 35 | } | ||
2018 | 36 | |||
2019 | 37 | int DeviceModel::rowCount(const QModelIndex &parent) const | ||
2020 | 38 | { | ||
2021 | 39 | Q_UNUSED(parent); | ||
2022 | 40 | return m_devices.size(); | ||
2023 | 41 | } | ||
2024 | 42 | |||
2025 | 43 | int DeviceModel::count() const | ||
2026 | 44 | { | ||
2027 | 45 | return rowCount(); | ||
2028 | 46 | } | ||
2029 | 47 | |||
2030 | 48 | QVariant DeviceModel::data(const QModelIndex &index, int role) const | ||
2031 | 49 | { | ||
2032 | 50 | QVariant ret; | ||
2033 | 51 | |||
2034 | 52 | if ((0 <= index.row()) && (index.row() < m_devices.size())) { | ||
2035 | 53 | |||
2036 | 54 | auto device = m_devices[index.row()]; | ||
2037 | 55 | |||
2038 | 56 | switch (role) { | ||
2039 | 57 | case Qt::DisplayRole: | ||
2040 | 58 | ret = device.toString(); | ||
2041 | 59 | break; | ||
2042 | 60 | case IdRole: | ||
2043 | 61 | ret = device.id; | ||
2044 | 62 | break; | ||
2045 | 63 | case InfoRole: | ||
2046 | 64 | ret = device.info; | ||
2047 | 65 | break; | ||
2048 | 66 | case UriRole: | ||
2049 | 67 | ret = device.uri; | ||
2050 | 68 | break; | ||
2051 | 69 | case LocationRole: | ||
2052 | 70 | ret = device.location; | ||
2053 | 71 | break; | ||
2054 | 72 | case TypeRole: | ||
2055 | 73 | ret = QVariant::fromValue(device.type()); | ||
2056 | 74 | break; | ||
2057 | 75 | case MakeModelRole: | ||
2058 | 76 | ret = device.makeModel; | ||
2059 | 77 | break; | ||
2060 | 78 | } | ||
2061 | 79 | } | ||
2062 | 80 | |||
2063 | 81 | return ret; | ||
2064 | 82 | } | ||
2065 | 83 | |||
2066 | 84 | QHash<int, QByteArray> DeviceModel::roleNames() const | ||
2067 | 85 | { | ||
2068 | 86 | static QHash<int,QByteArray> names; | ||
2069 | 87 | |||
2070 | 88 | if (Q_UNLIKELY(names.empty())) { | ||
2071 | 89 | names[Qt::DisplayRole] = "displayName"; | ||
2072 | 90 | names[IdRole] = "id"; | ||
2073 | 91 | names[InfoRole] = "info"; | ||
2074 | 92 | names[UriRole] = "uri"; | ||
2075 | 93 | names[LocationRole] = "location"; | ||
2076 | 94 | names[TypeRole] = "type"; | ||
2077 | 95 | names[MakeModelRole] = "makeModel"; | ||
2078 | 96 | } | ||
2079 | 97 | |||
2080 | 98 | return names; | ||
2081 | 99 | } | ||
2082 | 100 | |||
2083 | 101 | void DeviceModel::deviceLoaded(const Device &device) | ||
2084 | 102 | { | ||
2085 | 103 | if (!deviceWanted(device)) { | ||
2086 | 104 | return; | ||
2087 | 105 | } | ||
2088 | 106 | |||
2089 | 107 | if (!m_devices.contains(device)) { | ||
2090 | 108 | int i = m_devices.size(); | ||
2091 | 109 | beginInsertRows(QModelIndex(), i, i); | ||
2092 | 110 | m_devices.append(device); | ||
2093 | 111 | endInsertRows(); | ||
2094 | 112 | |||
2095 | 113 | Q_EMIT countChanged(); | ||
2096 | 114 | } | ||
2097 | 115 | } | ||
2098 | 116 | |||
2099 | 117 | bool DeviceModel::deviceWanted(const Device &device) | ||
2100 | 118 | { | ||
2101 | 119 | auto parts = device.uri.split(":", QString::SkipEmptyParts); | ||
2102 | 120 | return parts.size() > 1; | ||
2103 | 121 | } | ||
2104 | 122 | |||
2105 | 123 | void DeviceModel::clear() | ||
2106 | 124 | { | ||
2107 | 125 | beginResetModel(); | ||
2108 | 126 | m_devices.clear(); | ||
2109 | 127 | endResetModel(); | ||
2110 | 128 | } | ||
2111 | 129 | |||
2112 | 130 | void DeviceModel::load() | ||
2113 | 131 | { | ||
2114 | 132 | if (m_isSearching) { | ||
2115 | 133 | qWarning() << Q_FUNC_INFO | ||
2116 | 134 | << "Ignoring load request as search is ongoing."; | ||
2117 | 135 | } else { | ||
2118 | 136 | clear(); | ||
2119 | 137 | if (m_backend->type() == PrinterEnum::PrinterType::CupsType) { | ||
2120 | 138 | ((PrinterCupsBackend*) m_backend)->searchForDevices(); | ||
2121 | 139 | m_isSearching = true; | ||
2122 | 140 | Q_EMIT searchingChanged(); | ||
2123 | 141 | } | ||
2124 | 142 | } | ||
2125 | 143 | } | ||
2126 | 144 | |||
2127 | 145 | void DeviceModel::deviceSearchFinished() | ||
2128 | 146 | { | ||
2129 | 147 | m_isSearching = false; | ||
2130 | 148 | Q_EMIT searchingChanged(); | ||
2131 | 149 | } | ||
2132 | 0 | 150 | ||
2133 | === added file 'modules/Ubuntu/Components/Extras/Printers/models/devicemodel.h' | |||
2134 | --- modules/Ubuntu/Components/Extras/Printers/models/devicemodel.h 1970-01-01 00:00:00 +0000 | |||
2135 | +++ modules/Ubuntu/Components/Extras/Printers/models/devicemodel.h 2017-03-23 12:51:36 +0000 | |||
2136 | @@ -0,0 +1,78 @@ | |||
2137 | 1 | /* | ||
2138 | 2 | * Copyright (C) 2017 Canonical, Ltd. | ||
2139 | 3 | * | ||
2140 | 4 | * This program is free software; you can redistribute it and/or modify | ||
2141 | 5 | * it under the terms of the GNU Lesser General Public License as published by | ||
2142 | 6 | * the Free Software Foundation; version 3. | ||
2143 | 7 | * | ||
2144 | 8 | * This program is distributed in the hope that it will be useful, | ||
2145 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2146 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2147 | 11 | * GNU Lesser General Public License for more details. | ||
2148 | 12 | * | ||
2149 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
2150 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2151 | 15 | */ | ||
2152 | 16 | |||
2153 | 17 | #ifndef USC_PRINTER_DEVICEMODEL_H | ||
2154 | 18 | #define USC_PRINTER_DEVICEMODEL_H | ||
2155 | 19 | |||
2156 | 20 | #include "printers_global.h" | ||
2157 | 21 | |||
2158 | 22 | #include "structs.h" | ||
2159 | 23 | |||
2160 | 24 | #include <QAbstractListModel> | ||
2161 | 25 | #include <QList> | ||
2162 | 26 | #include <QModelIndex> | ||
2163 | 27 | #include <QObject> | ||
2164 | 28 | #include <QVariant> | ||
2165 | 29 | |||
2166 | 30 | class PRINTERS_DECL_EXPORT DeviceModel : public QAbstractListModel | ||
2167 | 31 | { | ||
2168 | 32 | Q_OBJECT | ||
2169 | 33 | Q_PROPERTY(int count READ count NOTIFY countChanged) | ||
2170 | 34 | Q_PROPERTY(bool searching MEMBER m_isSearching NOTIFY searchingChanged) | ||
2171 | 35 | public: | ||
2172 | 36 | explicit DeviceModel(PrinterBackend *backend, QObject *parent = Q_NULLPTR); | ||
2173 | 37 | ~DeviceModel(); | ||
2174 | 38 | |||
2175 | 39 | enum Roles | ||
2176 | 40 | { | ||
2177 | 41 | // Qt::DisplayRole holds device name | ||
2178 | 42 | ClassRole = Qt::UserRole, | ||
2179 | 43 | IdRole, | ||
2180 | 44 | InfoRole, | ||
2181 | 45 | UriRole, | ||
2182 | 46 | LocationRole, | ||
2183 | 47 | TypeRole, | ||
2184 | 48 | MakeModelRole, | ||
2185 | 49 | LastRole = MakeModelRole, | ||
2186 | 50 | }; | ||
2187 | 51 | |||
2188 | 52 | virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; | ||
2189 | 53 | virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; | ||
2190 | 54 | virtual QHash<int, QByteArray> roleNames() const override; | ||
2191 | 55 | |||
2192 | 56 | int count() const; | ||
2193 | 57 | void load(); | ||
2194 | 58 | void clear(); | ||
2195 | 59 | |||
2196 | 60 | private Q_SLOTS: | ||
2197 | 61 | void deviceLoaded(const Device &device); | ||
2198 | 62 | void deviceSearchFinished(); | ||
2199 | 63 | |||
2200 | 64 | Q_SIGNALS: | ||
2201 | 65 | void countChanged(); | ||
2202 | 66 | void searchingChanged(); | ||
2203 | 67 | |||
2204 | 68 | private: | ||
2205 | 69 | /* Checks if we want it in the list or not. Wanted is intentionally | ||
2206 | 70 | ambiguous. */ | ||
2207 | 71 | bool deviceWanted(const Device &device); | ||
2208 | 72 | |||
2209 | 73 | PrinterBackend *m_backend; | ||
2210 | 74 | QList<Device> m_devices; | ||
2211 | 75 | bool m_isSearching; | ||
2212 | 76 | }; | ||
2213 | 77 | |||
2214 | 78 | #endif // USC_PRINTER_DEVICEMODEL_H | ||
2215 | 0 | 79 | ||
2216 | === modified file 'modules/Ubuntu/Components/Extras/Printers/models/jobmodel.cpp' | |||
2217 | --- modules/Ubuntu/Components/Extras/Printers/models/jobmodel.cpp 2017-02-23 14:04:26 +0000 | |||
2218 | +++ modules/Ubuntu/Components/Extras/Printers/models/jobmodel.cpp 2017-03-23 12:51:36 +0000 | |||
2219 | @@ -31,113 +31,190 @@ | |||
2220 | 31 | : QAbstractListModel(parent) | 31 | : QAbstractListModel(parent) |
2221 | 32 | , m_backend(backend) | 32 | , m_backend(backend) |
2222 | 33 | { | 33 | { |
2223 | 34 | update(); | ||
2224 | 35 | |||
2225 | 36 | QObject::connect(m_backend, &PrinterBackend::jobCreated, | 34 | QObject::connect(m_backend, &PrinterBackend::jobCreated, |
2227 | 37 | this, &JobModel::jobSignalCatchAll); | 35 | this, &JobModel::jobCreated); |
2228 | 38 | QObject::connect(m_backend, &PrinterBackend::jobState, | 36 | QObject::connect(m_backend, &PrinterBackend::jobState, |
2230 | 39 | this, &JobModel::jobSignalCatchAll); | 37 | this, &JobModel::jobState); |
2231 | 40 | QObject::connect(m_backend, &PrinterBackend::jobCompleted, | 38 | QObject::connect(m_backend, &PrinterBackend::jobCompleted, |
2233 | 41 | this, &JobModel::jobSignalCatchAll); | 39 | this, &JobModel::jobCompleted); |
2234 | 40 | |||
2235 | 41 | connect(m_backend, SIGNAL(jobLoaded(QString, int, QMap<QString, QVariant>)), | ||
2236 | 42 | this, SLOT(updateJob(QString, int, QMap<QString, QVariant>))); | ||
2237 | 43 | |||
2238 | 44 | // Impressions completed happens via printer state changed | ||
2239 | 45 | QObject::connect(m_backend, &PrinterBackend::printerStateChanged, | ||
2240 | 46 | &m_signalHandler, &SignalRateLimiter::onPrinterStateChanged); | ||
2241 | 47 | |||
2242 | 48 | QObject::connect(&m_signalHandler, SIGNAL(printerModified(const QString&)), | ||
2243 | 49 | this, SLOT(jobSignalPrinterModified(const QString&))); | ||
2244 | 50 | |||
2245 | 51 | // Add already existing jobs | ||
2246 | 52 | // TODO: even this should probably be in a background thread? | ||
2247 | 53 | // so that it doesn't block startup? | ||
2248 | 54 | Q_FOREACH(auto job, m_backend->printerGetJobs()) { | ||
2249 | 55 | addJob(job); | ||
2250 | 56 | } | ||
2251 | 42 | } | 57 | } |
2252 | 43 | 58 | ||
2253 | 44 | JobModel::~JobModel() | 59 | JobModel::~JobModel() |
2254 | 45 | { | 60 | { |
2255 | 46 | } | 61 | } |
2256 | 47 | 62 | ||
2271 | 48 | void JobModel::jobSignalCatchAll( | 63 | void JobModel::jobCreated( |
2272 | 49 | const QString &text, const QString &printer_uri, | 64 | const QString &text, const QString &printer_uri, |
2273 | 50 | const QString &printer_name, uint printer_state, | 65 | const QString &printer_name, uint printer_state, |
2274 | 51 | const QString &printer_state_reasons, bool printer_is_accepting_jobs, | 66 | const QString &printer_state_reasons, bool printer_is_accepting_jobs, |
2275 | 52 | uint job_id, uint job_state, const QString &job_state_reasons, | 67 | uint job_id, uint job_state, const QString &job_state_reasons, |
2276 | 53 | const QString &job_name, uint job_impressions_completed) | 68 | const QString &job_name, uint job_impressions_completed) |
2277 | 54 | { | 69 | { |
2278 | 55 | Q_UNUSED(text); | 70 | Q_UNUSED(text); // "Job Created" |
2279 | 56 | Q_UNUSED(printer_uri); | 71 | Q_UNUSED(printer_uri); |
2280 | 57 | Q_UNUSED(printer_name); | 72 | Q_UNUSED(printer_state); |
2281 | 58 | Q_UNUSED(printer_state); | 73 | Q_UNUSED(printer_state_reasons); |
2282 | 59 | Q_UNUSED(printer_state_reasons); | 74 | Q_UNUSED(printer_is_accepting_jobs); |
2283 | 60 | Q_UNUSED(printer_is_accepting_jobs); | 75 | Q_UNUSED(job_state_reasons); |
2284 | 61 | Q_UNUSED(job_id); | 76 | |
2285 | 77 | QSharedPointer<PrinterJob> job = QSharedPointer<PrinterJob>( | ||
2286 | 78 | new PrinterJob(printer_name, m_backend, job_id) | ||
2287 | 79 | ); | ||
2288 | 80 | job->setImpressionsCompleted(job_impressions_completed); | ||
2289 | 81 | job->setState(static_cast<PrinterEnum::JobState>(job_state)); | ||
2290 | 82 | job->setTitle(job_name); | ||
2291 | 83 | |||
2292 | 84 | // Printers listens to rowInserted and spawns a JobLoader to set the | ||
2293 | 85 | // printer of the job, which triggers the extended attributes to be loaded | ||
2294 | 86 | // once complete this triggers JobModel::updateJob | ||
2295 | 87 | addJob(job); | ||
2296 | 88 | } | ||
2297 | 89 | |||
2298 | 90 | void JobModel::jobState( | ||
2299 | 91 | const QString &text, const QString &printer_uri, | ||
2300 | 92 | const QString &printer_name, uint printer_state, | ||
2301 | 93 | const QString &printer_state_reasons, bool printer_is_accepting_jobs, | ||
2302 | 94 | uint job_id, uint job_state, const QString &job_state_reasons, | ||
2303 | 95 | const QString &job_name, uint job_impressions_completed) | ||
2304 | 96 | { | ||
2305 | 97 | Q_UNUSED(text); | ||
2306 | 98 | Q_UNUSED(printer_uri); | ||
2307 | 99 | Q_UNUSED(printer_state); | ||
2308 | 100 | Q_UNUSED(printer_state_reasons); | ||
2309 | 101 | Q_UNUSED(printer_is_accepting_jobs); | ||
2310 | 102 | Q_UNUSED(job_state_reasons); | ||
2311 | 103 | Q_UNUSED(job_name); | ||
2312 | 104 | |||
2313 | 105 | QSharedPointer<PrinterJob> job = getJob(printer_name, job_id); | ||
2314 | 106 | |||
2315 | 107 | if (job) { | ||
2316 | 108 | job->setImpressionsCompleted(job_impressions_completed); | ||
2317 | 109 | job->setState(static_cast<PrinterEnum::JobState>(job_state)); | ||
2318 | 110 | |||
2319 | 111 | updateJob(job); | ||
2320 | 112 | } else { | ||
2321 | 113 | qWarning() << "JobModel::jobState for unknown job: " << job_name << " (" | ||
2322 | 114 | << job_id << ") for " << printer_name; | ||
2323 | 115 | } | ||
2324 | 116 | } | ||
2325 | 117 | |||
2326 | 118 | void JobModel::jobCompleted( | ||
2327 | 119 | const QString &text, const QString &printer_uri, | ||
2328 | 120 | const QString &printer_name, uint printer_state, | ||
2329 | 121 | const QString &printer_state_reasons, bool printer_is_accepting_jobs, | ||
2330 | 122 | uint job_id, uint job_state, const QString &job_state_reasons, | ||
2331 | 123 | const QString &job_name, uint job_impressions_completed) | ||
2332 | 124 | { | ||
2333 | 125 | Q_UNUSED(text); | ||
2334 | 126 | Q_UNUSED(printer_uri); | ||
2335 | 127 | Q_UNUSED(printer_state); | ||
2336 | 128 | Q_UNUSED(printer_state_reasons); | ||
2337 | 129 | Q_UNUSED(printer_is_accepting_jobs); | ||
2338 | 62 | Q_UNUSED(job_state); | 130 | Q_UNUSED(job_state); |
2339 | 63 | Q_UNUSED(job_state_reasons); | 131 | Q_UNUSED(job_state_reasons); |
2340 | 64 | Q_UNUSED(job_name); | 132 | Q_UNUSED(job_name); |
2417 | 65 | 133 | Q_UNUSED(job_impressions_completed); | |
2418 | 66 | auto job = getJobById(job_id); | 134 | |
2419 | 67 | if (job) | 135 | auto job = getJob(printer_name, job_id); |
2420 | 68 | job->setImpressionsCompleted(job_impressions_completed); | 136 | if (job) { |
2421 | 69 | 137 | removeJob(job); | |
2422 | 70 | update(); | 138 | } else { |
2423 | 71 | } | 139 | qWarning() << "JobModel::jobCompleted for unknown job: " << job_name << " (" |
2424 | 72 | 140 | << job_id << ") for " << printer_name; | |
2425 | 73 | void JobModel::update() | 141 | } |
2426 | 74 | { | 142 | } |
2427 | 75 | // Store the old count and get the new printers | 143 | |
2428 | 76 | int oldCount = m_jobs.size(); | 144 | void JobModel::jobSignalPrinterModified(const QString &printerName) |
2429 | 77 | QList<QSharedPointer<PrinterJob>> newJobs = m_backend->printerGetJobs(); | 145 | { |
2430 | 78 | 146 | // Find the active or pending job and force a refresh | |
2431 | 79 | // Go through the old model | 147 | // We force refresh pending jobs incase there is a flood of signals |
2432 | 80 | for (int i=0; i < m_jobs.count(); i++) { | 148 | // meaning that the jobStateChanged signal might not have happened yet |
2433 | 81 | // Determine if the old printer exists in the new model | 149 | Q_FOREACH(auto job, m_jobs) { |
2434 | 82 | bool exists = false; | 150 | if (job->printerName() == printerName |
2435 | 83 | 151 | && (job->state() == PrinterEnum::JobState::Processing | |
2436 | 84 | Q_FOREACH(QSharedPointer<PrinterJob> p, newJobs) { | 152 | || job->state() == PrinterEnum::JobState::Pending)) { |
2437 | 85 | if (p->jobId() == m_jobs.at(i)->jobId()) { | 153 | Q_EMIT forceJobRefresh(printerName, job->jobId()); |
2438 | 86 | exists = true; | 154 | } |
2439 | 87 | 155 | } | |
2440 | 88 | // Ensure the other properties of the job are up to date | 156 | } |
2441 | 89 | if (!m_jobs.at(i)->deepCompare(p)) { | 157 | |
2442 | 90 | m_jobs.at(i)->updateFrom(p); | 158 | void JobModel::addJob(QSharedPointer<PrinterJob> job) |
2443 | 91 | 159 | { | |
2444 | 92 | Q_EMIT dataChanged(index(i), index(i)); | 160 | int i = m_jobs.size(); |
2445 | 93 | } | 161 | |
2446 | 94 | 162 | beginInsertRows(QModelIndex(), i, i); | |
2447 | 95 | break; | 163 | m_jobs.append(job); |
2448 | 96 | } | 164 | endInsertRows(); |
2449 | 97 | } | 165 | |
2450 | 98 | 166 | Q_EMIT countChanged(); | |
2451 | 99 | // If it doesn't exist then remove it from the old model | 167 | } |
2452 | 100 | if (!exists) { | 168 | |
2453 | 101 | beginRemoveRows(QModelIndex(), i, i); | 169 | void JobModel::removeJob(QSharedPointer<PrinterJob> job) |
2454 | 102 | QSharedPointer<PrinterJob> p = m_jobs.takeAt(i); | 170 | { |
2455 | 103 | endRemoveRows(); | 171 | int i = m_jobs.indexOf(job); |
2456 | 104 | 172 | ||
2457 | 105 | i--; // as we have removed an item decrement | 173 | beginRemoveRows(QModelIndex(), i, i); |
2458 | 106 | } | 174 | m_jobs.removeAt(i); |
2459 | 107 | } | 175 | endRemoveRows(); |
2460 | 108 | 176 | ||
2461 | 109 | // Go through the new model | 177 | Q_EMIT countChanged(); |
2462 | 110 | for (int i=0; i < newJobs.count(); i++) { | 178 | } |
2463 | 111 | // Determine if the new printer exists in the old model | 179 | |
2464 | 112 | bool exists = false; | 180 | // This is used by JobModel::jobState as it has modified an existing job |
2465 | 113 | int j; | 181 | void JobModel::updateJob(QSharedPointer<PrinterJob> job) |
2466 | 114 | 182 | { | |
2467 | 115 | for (j=0; j < m_jobs.count(); j++) { | 183 | int i = m_jobs.indexOf(job); |
2468 | 116 | if (m_jobs.at(j)->jobId() == newJobs.at(i)->jobId()) { | 184 | QModelIndex idx = index(i); |
2469 | 117 | exists = true; | 185 | Q_EMIT dataChanged(idx, idx); |
2470 | 118 | break; | 186 | } |
2471 | 119 | } | 187 | |
2472 | 120 | } | 188 | // This is used by JobLoader as it gives us the oldJob and a newJob which has |
2473 | 121 | 189 | // the extended attributes loaded. We then load the data from this newJob. | |
2474 | 122 | if (exists) { | 190 | void JobModel::updateJob(QString printerName, int jobId, |
2475 | 123 | if (j == i) { // New printer exists and in correct position | 191 | QMap<QString, QVariant> attributes) |
2476 | 124 | continue; | 192 | { |
2477 | 125 | } else { | 193 | QSharedPointer<PrinterJob> job = getJob(printerName, jobId); |
2478 | 126 | // New printer does exist but needs to be moved in old model | 194 | |
2479 | 127 | beginMoveRows(QModelIndex(), j, 1, QModelIndex(), i); | 195 | int i = m_jobs.indexOf(job); |
2480 | 128 | m_jobs.move(j, i); | 196 | QModelIndex idx = index(i); |
2481 | 129 | endMoveRows(); | 197 | |
2482 | 130 | } | 198 | if (i > -1) { |
2483 | 131 | } else { | 199 | job->loadAttributes(attributes); |
2484 | 132 | // New printer does not exist insert into model | 200 | |
2485 | 133 | beginInsertRows(QModelIndex(), i, i); | 201 | Q_EMIT dataChanged(idx, idx); |
2486 | 134 | m_jobs.insert(i, newJobs.at(i)); | 202 | } else { |
2487 | 135 | endInsertRows(); | 203 | qWarning() << "Tried to updateJob which doesn't exist:" << printerName << jobId; |
2488 | 136 | } | 204 | } |
2489 | 137 | } | 205 | } |
2490 | 138 | 206 | ||
2491 | 139 | if (oldCount != m_jobs.size()) { | 207 | void JobModel::updateJobPrinter(QSharedPointer<PrinterJob> job, QSharedPointer<Printer> printer) |
2492 | 140 | Q_EMIT countChanged(); | 208 | { |
2493 | 209 | int i = m_jobs.indexOf(job); | ||
2494 | 210 | QModelIndex idx = index(i); | ||
2495 | 211 | |||
2496 | 212 | if (i > -1) { | ||
2497 | 213 | job->setPrinter(printer); | ||
2498 | 214 | |||
2499 | 215 | Q_EMIT dataChanged(idx, idx); | ||
2500 | 216 | } else { | ||
2501 | 217 | qWarning() << "Tried to updateJobPrinter which doesn't exist:" << printer->name() << job->jobId(); | ||
2502 | 141 | } | 218 | } |
2503 | 142 | } | 219 | } |
2504 | 143 | 220 | ||
2505 | @@ -166,7 +243,8 @@ | |||
2506 | 166 | break; | 243 | break; |
2507 | 167 | case ColorModelRole: { | 244 | case ColorModelRole: { |
2508 | 168 | if (job->printer()) { | 245 | if (job->printer()) { |
2510 | 169 | ret = job->printer()->supportedColorModels().at(job->colorModel()).text; | 246 | ColorModel m = job->printer()->supportedColorModels().at(job->colorModel()); |
2511 | 247 | ret = m.text.isEmpty() ? m.name : m.text; | ||
2512 | 170 | } else { | 248 | } else { |
2513 | 171 | qWarning() << "Printer is undefined, no colorModel"; | 249 | qWarning() << "Printer is undefined, no colorModel"; |
2514 | 172 | ret = ""; | 250 | ret = ""; |
2515 | @@ -174,13 +252,13 @@ | |||
2516 | 174 | break; | 252 | break; |
2517 | 175 | } | 253 | } |
2518 | 176 | case CompletedTimeRole: | 254 | case CompletedTimeRole: |
2520 | 177 | ret = job->completedTime().toString(QLocale::system().dateTimeFormat()); | 255 | ret = job->completedTime().toLocalTime(); |
2521 | 178 | break; | 256 | break; |
2522 | 179 | case CopiesRole: | 257 | case CopiesRole: |
2523 | 180 | ret = job->copies(); | 258 | ret = job->copies(); |
2524 | 181 | break; | 259 | break; |
2525 | 182 | case CreationTimeRole: | 260 | case CreationTimeRole: |
2527 | 183 | ret = job->creationTime().toString(QLocale::system().dateTimeFormat()); | 261 | ret = job->creationTime().toLocalTime(); |
2528 | 184 | break; | 262 | break; |
2529 | 185 | case DuplexRole: { | 263 | case DuplexRole: { |
2530 | 186 | if (job->printer()) { | 264 | if (job->printer()) { |
2531 | @@ -194,6 +272,9 @@ | |||
2532 | 194 | case IdRole: | 272 | case IdRole: |
2533 | 195 | ret = job->jobId(); | 273 | ret = job->jobId(); |
2534 | 196 | break; | 274 | break; |
2535 | 275 | case HeldRole: | ||
2536 | 276 | ret = job->state() == PrinterEnum::JobState::Held; | ||
2537 | 277 | break; | ||
2538 | 197 | case ImpressionsCompletedRole: | 278 | case ImpressionsCompletedRole: |
2539 | 198 | ret = job->impressionsCompleted(); | 279 | ret = job->impressionsCompleted(); |
2540 | 199 | break; | 280 | break; |
2541 | @@ -213,11 +294,12 @@ | |||
2542 | 213 | ret = QVariant::fromValue<PrinterEnum::PrintRange>(job->printRangeMode()); | 294 | ret = QVariant::fromValue<PrinterEnum::PrintRange>(job->printRangeMode()); |
2543 | 214 | break; | 295 | break; |
2544 | 215 | case ProcessingTimeRole: | 296 | case ProcessingTimeRole: |
2546 | 216 | ret = job->processingTime().toString(QLocale::system().dateTimeFormat()); | 297 | ret = job->processingTime().toLocalTime(); |
2547 | 217 | break; | 298 | break; |
2548 | 218 | case QualityRole: { | 299 | case QualityRole: { |
2549 | 219 | if (job->printer()) { | 300 | if (job->printer()) { |
2551 | 220 | ret = job->printer()->supportedPrintQualities().at(job->quality()).text; | 301 | PrintQuality q = job->printer()->supportedPrintQualities().at(job->quality()); |
2552 | 302 | ret = q.text.isEmpty() ? q.name : q.text; | ||
2553 | 221 | } else { | 303 | } else { |
2554 | 222 | qWarning() << "Printer is undefined, no quality"; | 304 | qWarning() << "Printer is undefined, no quality"; |
2555 | 223 | ret = ""; | 305 | ret = ""; |
2556 | @@ -231,30 +313,7 @@ | |||
2557 | 231 | ret = job->size(); | 313 | ret = job->size(); |
2558 | 232 | break; | 314 | break; |
2559 | 233 | case StateRole: | 315 | case StateRole: |
2584 | 234 | // TODO: improve, for now have a switch | 316 | ret = QVariant::fromValue<PrinterEnum::JobState>(job->state()); |
2561 | 235 | switch (job->state()) { | ||
2562 | 236 | case PrinterEnum::JobState::Aborted: | ||
2563 | 237 | ret = "Aborted"; | ||
2564 | 238 | break; | ||
2565 | 239 | case PrinterEnum::JobState::Canceled: | ||
2566 | 240 | ret = "Canceled"; | ||
2567 | 241 | break; | ||
2568 | 242 | case PrinterEnum::JobState::Complete: | ||
2569 | 243 | ret = "Compelete"; | ||
2570 | 244 | break; | ||
2571 | 245 | case PrinterEnum::JobState::Held: | ||
2572 | 246 | ret = "Held"; | ||
2573 | 247 | break; | ||
2574 | 248 | case PrinterEnum::JobState::Pending: | ||
2575 | 249 | ret = "Pending"; | ||
2576 | 250 | break; | ||
2577 | 251 | case PrinterEnum::JobState::Processing: | ||
2578 | 252 | ret = "Processing"; | ||
2579 | 253 | break; | ||
2580 | 254 | case PrinterEnum::JobState::Stopped: | ||
2581 | 255 | ret = "Stopped"; | ||
2582 | 256 | break; | ||
2583 | 257 | } | ||
2585 | 258 | break; | 317 | break; |
2586 | 259 | case Qt::DisplayRole: | 318 | case Qt::DisplayRole: |
2587 | 260 | case TitleRole: | 319 | case TitleRole: |
2588 | @@ -263,6 +322,15 @@ | |||
2589 | 263 | case UserRole: | 322 | case UserRole: |
2590 | 264 | ret = job->user(); | 323 | ret = job->user(); |
2591 | 265 | break; | 324 | break; |
2592 | 325 | case LastStateMessageRole: { | ||
2593 | 326 | if (job->printer()) { | ||
2594 | 327 | ret = job->printer()->lastMessage(); | ||
2595 | 328 | } else { | ||
2596 | 329 | ret = ""; | ||
2597 | 330 | } | ||
2598 | 331 | break; | ||
2599 | 332 | } | ||
2600 | 333 | |||
2601 | 266 | } | 334 | } |
2602 | 267 | } | 335 | } |
2603 | 268 | 336 | ||
2604 | @@ -283,6 +351,7 @@ | |||
2605 | 283 | names[CreationTimeRole] = "creationTime"; | 351 | names[CreationTimeRole] = "creationTime"; |
2606 | 284 | names[DuplexRole] = "duplexMode"; | 352 | names[DuplexRole] = "duplexMode"; |
2607 | 285 | names[ImpressionsCompletedRole] = "impressionsCompleted"; | 353 | names[ImpressionsCompletedRole] = "impressionsCompleted"; |
2608 | 354 | names[HeldRole] = "held"; | ||
2609 | 286 | names[LandscapeRole] = "landscape"; | 355 | names[LandscapeRole] = "landscape"; |
2610 | 287 | names[MessagesRole] = "messages"; | 356 | names[MessagesRole] = "messages"; |
2611 | 288 | names[PrinterNameRole] = "printerName"; | 357 | names[PrinterNameRole] = "printerName"; |
2612 | @@ -315,10 +384,10 @@ | |||
2613 | 315 | return result; | 384 | return result; |
2614 | 316 | } | 385 | } |
2615 | 317 | 386 | ||
2617 | 318 | QSharedPointer<PrinterJob> JobModel::getJobById(const int &id) | 387 | QSharedPointer<PrinterJob> JobModel::getJob(const QString &printerName, const int &id) |
2618 | 319 | { | 388 | { |
2619 | 320 | Q_FOREACH(auto job, m_jobs) { | 389 | Q_FOREACH(auto job, m_jobs) { |
2621 | 321 | if (job->jobId() == id) { | 390 | if (job->printerName() == printerName && job->jobId() == id) { |
2622 | 322 | return job; | 391 | return job; |
2623 | 323 | } | 392 | } |
2624 | 324 | } | 393 | } |
2625 | @@ -367,6 +436,33 @@ | |||
2626 | 367 | return rowCount(); | 436 | return rowCount(); |
2627 | 368 | } | 437 | } |
2628 | 369 | 438 | ||
2629 | 439 | void JobFilter::filterOnActive() | ||
2630 | 440 | { | ||
2631 | 441 | m_activeStates = QSet<PrinterEnum::JobState>{ | ||
2632 | 442 | PrinterEnum::JobState::Processing, | ||
2633 | 443 | }; | ||
2634 | 444 | m_activeFilterEnabled = true; | ||
2635 | 445 | invalidate(); | ||
2636 | 446 | } | ||
2637 | 447 | |||
2638 | 448 | void JobFilter::filterOnPaused() | ||
2639 | 449 | { | ||
2640 | 450 | m_pausedStates = QSet<PrinterEnum::JobState>{ | ||
2641 | 451 | PrinterEnum::JobState::Held, | ||
2642 | 452 | }; | ||
2643 | 453 | m_pausedFilterEnabled = true; | ||
2644 | 454 | invalidate(); | ||
2645 | 455 | } | ||
2646 | 456 | |||
2647 | 457 | void JobFilter::filterOnQueued() | ||
2648 | 458 | { | ||
2649 | 459 | m_queuedStates = QSet<PrinterEnum::JobState>{ | ||
2650 | 460 | PrinterEnum::JobState::Pending, | ||
2651 | 461 | }; | ||
2652 | 462 | m_queuedFilterEnabled = true; | ||
2653 | 463 | invalidate(); | ||
2654 | 464 | } | ||
2655 | 465 | |||
2656 | 370 | void JobFilter::filterOnPrinterName(const QString &name) | 466 | void JobFilter::filterOnPrinterName(const QString &name) |
2657 | 371 | { | 467 | { |
2658 | 372 | m_printerName = name; | 468 | m_printerName = name; |
2659 | @@ -386,5 +482,50 @@ | |||
2660 | 386 | accepts = m_printerName == printerName; | 482 | accepts = m_printerName == printerName; |
2661 | 387 | } | 483 | } |
2662 | 388 | 484 | ||
2663 | 485 | if (accepts && m_activeFilterEnabled) { | ||
2664 | 486 | PrinterEnum::JobState state = childIndex.model()->data( | ||
2665 | 487 | childIndex, JobModel::StateRole | ||
2666 | 488 | ).value<PrinterEnum::JobState>(); | ||
2667 | 489 | |||
2668 | 490 | accepts = m_activeStates.contains(state); | ||
2669 | 491 | } | ||
2670 | 492 | |||
2671 | 493 | if (accepts && m_pausedFilterEnabled) { | ||
2672 | 494 | PrinterEnum::JobState state = childIndex.model()->data( | ||
2673 | 495 | childIndex, JobModel::StateRole | ||
2674 | 496 | ).value<PrinterEnum::JobState>(); | ||
2675 | 497 | |||
2676 | 498 | accepts = m_pausedStates.contains(state); | ||
2677 | 499 | } | ||
2678 | 500 | |||
2679 | 501 | if (accepts && m_queuedFilterEnabled) { | ||
2680 | 502 | PrinterEnum::JobState state = childIndex.model()->data( | ||
2681 | 503 | childIndex, JobModel::StateRole | ||
2682 | 504 | ).value<PrinterEnum::JobState>(); | ||
2683 | 505 | |||
2684 | 506 | accepts = m_queuedStates.contains(state); | ||
2685 | 507 | } | ||
2686 | 508 | |||
2687 | 389 | return accepts; | 509 | return accepts; |
2688 | 390 | } | 510 | } |
2689 | 511 | |||
2690 | 512 | bool JobFilter::lessThan(const QModelIndex &source_left, | ||
2691 | 513 | const QModelIndex &source_right) const | ||
2692 | 514 | { | ||
2693 | 515 | QVariant leftData = sourceModel()->data(source_left, sortRole()); | ||
2694 | 516 | QVariant rightData = sourceModel()->data(source_right, sortRole()); | ||
2695 | 517 | |||
2696 | 518 | if (sortRole() == (int) JobModel::CreationTimeRole) { | ||
2697 | 519 | // If creationDateTime is the same, fallback to Id | ||
2698 | 520 | if (leftData.toDateTime() == rightData.toDateTime()) { | ||
2699 | 521 | int leftId = sourceModel()->data(source_left, JobModel::IdRole).toInt(); | ||
2700 | 522 | int rightId = sourceModel()->data(source_right, JobModel::IdRole).toInt(); | ||
2701 | 523 | |||
2702 | 524 | return leftId < rightId; | ||
2703 | 525 | } else { | ||
2704 | 526 | return leftData.toDateTime() < rightData.toDateTime(); | ||
2705 | 527 | } | ||
2706 | 528 | } else { | ||
2707 | 529 | return leftData < rightData; | ||
2708 | 530 | } | ||
2709 | 531 | } | ||
2710 | 391 | 532 | ||
2711 | === modified file 'modules/Ubuntu/Components/Extras/Printers/models/jobmodel.h' | |||
2712 | --- modules/Ubuntu/Components/Extras/Printers/models/jobmodel.h 2017-02-21 10:46:29 +0000 | |||
2713 | +++ modules/Ubuntu/Components/Extras/Printers/models/jobmodel.h 2017-03-23 12:51:36 +0000 | |||
2714 | @@ -20,6 +20,7 @@ | |||
2715 | 20 | #include "printers_global.h" | 20 | #include "printers_global.h" |
2716 | 21 | #include "backend/backend.h" | 21 | #include "backend/backend.h" |
2717 | 22 | #include "printer/printerjob.h" | 22 | #include "printer/printerjob.h" |
2718 | 23 | #include "printer/signalratelimiter.h" | ||
2719 | 23 | 24 | ||
2720 | 24 | #include <QAbstractListModel> | 25 | #include <QAbstractListModel> |
2721 | 25 | #include <QByteArray> | 26 | #include <QByteArray> |
2722 | @@ -30,6 +31,8 @@ | |||
2723 | 30 | #include <QTimer> | 31 | #include <QTimer> |
2724 | 31 | #include <QVariant> | 32 | #include <QVariant> |
2725 | 32 | 33 | ||
2726 | 34 | class PrinterBackend; | ||
2727 | 35 | class PrinterJob; | ||
2728 | 33 | class PRINTERS_DECL_EXPORT JobModel : public QAbstractListModel | 36 | class PRINTERS_DECL_EXPORT JobModel : public QAbstractListModel |
2729 | 34 | { | 37 | { |
2730 | 35 | Q_OBJECT | 38 | Q_OBJECT |
2731 | @@ -51,6 +54,7 @@ | |||
2732 | 51 | CopiesRole, | 54 | CopiesRole, |
2733 | 52 | CreationTimeRole, | 55 | CreationTimeRole, |
2734 | 53 | DuplexRole, | 56 | DuplexRole, |
2735 | 57 | HeldRole, | ||
2736 | 54 | ImpressionsCompletedRole, | 58 | ImpressionsCompletedRole, |
2737 | 55 | LandscapeRole, | 59 | LandscapeRole, |
2738 | 56 | MessagesRole, | 60 | MessagesRole, |
2739 | @@ -75,23 +79,46 @@ | |||
2740 | 75 | int count() const; | 79 | int count() const; |
2741 | 76 | 80 | ||
2742 | 77 | Q_INVOKABLE QVariantMap get(const int row) const; | 81 | Q_INVOKABLE QVariantMap get(const int row) const; |
2744 | 78 | QSharedPointer<PrinterJob> getJobById(const int &id); | 82 | QSharedPointer<PrinterJob> getJob(const QString &printerName, const int &id); |
2745 | 83 | |||
2746 | 84 | void updateJobPrinter(QSharedPointer<PrinterJob> job, QSharedPointer<Printer> printer); | ||
2747 | 79 | private: | 85 | private: |
2748 | 86 | void addJob(QSharedPointer<PrinterJob> job); | ||
2749 | 87 | void removeJob(QSharedPointer<PrinterJob> job); | ||
2750 | 88 | void updateJob(QSharedPointer<PrinterJob> Job); | ||
2751 | 89 | |||
2752 | 80 | PrinterBackend *m_backend; | 90 | PrinterBackend *m_backend; |
2753 | 81 | 91 | ||
2754 | 82 | QList<QSharedPointer<PrinterJob>> m_jobs; | 92 | QList<QSharedPointer<PrinterJob>> m_jobs; |
2755 | 93 | SignalRateLimiter m_signalHandler; | ||
2756 | 83 | private Q_SLOTS: | 94 | private Q_SLOTS: |
2765 | 84 | void update(); | 95 | void jobCreated(const QString &text, const QString &printer_uri, |
2766 | 85 | void jobSignalCatchAll(const QString &text, const QString &printer_uri, | 96 | const QString &printer_name, uint printer_state, |
2767 | 86 | const QString &printer_name, uint printer_state, | 97 | const QString &printer_state_reasons, |
2768 | 87 | const QString &printer_state_reasons, | 98 | bool printer_is_accepting_jobs, uint job_id, |
2769 | 88 | bool printer_is_accepting_jobs, uint job_id, | 99 | uint job_state, const QString &job_state_reasons, |
2770 | 89 | uint job_state, const QString &job_state_reasons, | 100 | const QString &job_name, |
2771 | 90 | const QString &job_name, | 101 | uint job_impressions_completed); |
2772 | 91 | uint job_impressions_completed); | 102 | void jobState(const QString &text, const QString &printer_uri, |
2773 | 103 | const QString &printer_name, uint printer_state, | ||
2774 | 104 | const QString &printer_state_reasons, | ||
2775 | 105 | bool printer_is_accepting_jobs, uint job_id, | ||
2776 | 106 | uint job_state, const QString &job_state_reasons, | ||
2777 | 107 | const QString &job_name, | ||
2778 | 108 | uint job_impressions_completed); | ||
2779 | 109 | void jobCompleted(const QString &text, const QString &printer_uri, | ||
2780 | 110 | const QString &printer_name, uint printer_state, | ||
2781 | 111 | const QString &printer_state_reasons, | ||
2782 | 112 | bool printer_is_accepting_jobs, uint job_id, | ||
2783 | 113 | uint job_state, const QString &job_state_reasons, | ||
2784 | 114 | const QString &job_name, | ||
2785 | 115 | uint job_impressions_completed); | ||
2786 | 116 | void jobSignalPrinterModified(const QString &printerName); | ||
2787 | 117 | void updateJob(QString printerName, int jobId, QMap<QString, QVariant> attributes); | ||
2788 | 92 | 118 | ||
2789 | 93 | Q_SIGNALS: | 119 | Q_SIGNALS: |
2790 | 94 | void countChanged(); | 120 | void countChanged(); |
2791 | 121 | void forceJobRefresh(const QString &printerName, const int jobId); | ||
2792 | 95 | }; | 122 | }; |
2793 | 96 | 123 | ||
2794 | 97 | class PRINTERS_DECL_EXPORT JobFilter : public QSortFilterProxyModel | 124 | class PRINTERS_DECL_EXPORT JobFilter : public QSortFilterProxyModel |
2795 | @@ -102,13 +129,19 @@ | |||
2796 | 102 | explicit JobFilter(QObject *parent = Q_NULLPTR); | 129 | explicit JobFilter(QObject *parent = Q_NULLPTR); |
2797 | 103 | ~JobFilter(); | 130 | ~JobFilter(); |
2798 | 104 | 131 | ||
2799 | 105 | Q_INVOKABLE QVariantMap get(const int row) const; | ||
2800 | 106 | |||
2801 | 107 | void filterOnPrinterName(const QString &name); | 132 | void filterOnPrinterName(const QString &name); |
2802 | 108 | int count() const; | 133 | int count() const; |
2803 | 134 | public Q_SLOTS: | ||
2804 | 135 | QVariantMap get(const int row) const; | ||
2805 | 136 | |||
2806 | 137 | void filterOnActive(); | ||
2807 | 138 | void filterOnQueued(); | ||
2808 | 139 | void filterOnPaused(); | ||
2809 | 109 | protected: | 140 | protected: |
2810 | 110 | virtual bool filterAcceptsRow( | 141 | virtual bool filterAcceptsRow( |
2811 | 111 | int sourceRow, const QModelIndex &sourceParent) const override; | 142 | int sourceRow, const QModelIndex &sourceParent) const override; |
2812 | 143 | virtual bool lessThan(const QModelIndex &source_left, | ||
2813 | 144 | const QModelIndex &source_right) const; | ||
2814 | 112 | 145 | ||
2815 | 113 | Q_SIGNALS: | 146 | Q_SIGNALS: |
2816 | 114 | void countChanged(); | 147 | void countChanged(); |
2817 | @@ -120,6 +153,15 @@ | |||
2818 | 120 | private: | 153 | private: |
2819 | 121 | QString m_printerName = QString::null; | 154 | QString m_printerName = QString::null; |
2820 | 122 | bool m_printerNameFilterEnabled = false; | 155 | bool m_printerNameFilterEnabled = false; |
2821 | 156 | |||
2822 | 157 | bool m_activeFilterEnabled = false; | ||
2823 | 158 | QSet<PrinterEnum::JobState> m_activeStates; | ||
2824 | 159 | |||
2825 | 160 | bool m_queuedFilterEnabled = false; | ||
2826 | 161 | QSet<PrinterEnum::JobState> m_queuedStates; | ||
2827 | 162 | |||
2828 | 163 | bool m_pausedFilterEnabled = false; | ||
2829 | 164 | QSet<PrinterEnum::JobState> m_pausedStates; | ||
2830 | 123 | }; | 165 | }; |
2831 | 124 | 166 | ||
2832 | 125 | #endif // USC_JOB_MODEL_H | 167 | #endif // USC_JOB_MODEL_H |
2833 | 126 | 168 | ||
2834 | === modified file 'modules/Ubuntu/Components/Extras/Printers/models/printermodel.cpp' | |||
2835 | --- modules/Ubuntu/Components/Extras/Printers/models/printermodel.cpp 2017-02-23 14:04:26 +0000 | |||
2836 | +++ modules/Ubuntu/Components/Extras/Printers/models/printermodel.cpp 2017-03-23 12:51:36 +0000 | |||
2837 | @@ -22,6 +22,7 @@ | |||
2838 | 22 | #include "utils.h" | 22 | #include "utils.h" |
2839 | 23 | 23 | ||
2840 | 24 | #include <QDebug> | 24 | #include <QDebug> |
2841 | 25 | #include <QUrl> | ||
2842 | 25 | 26 | ||
2843 | 26 | PrinterModel::PrinterModel(PrinterBackend *backend, QObject *parent) | 27 | PrinterModel::PrinterModel(PrinterBackend *backend, QObject *parent) |
2844 | 27 | : QAbstractListModel(parent) | 28 | : QAbstractListModel(parent) |
2845 | @@ -31,9 +32,9 @@ | |||
2846 | 31 | QObject::connect(m_backend, &PrinterBackend::printerAdded, | 32 | QObject::connect(m_backend, &PrinterBackend::printerAdded, |
2847 | 32 | this, &PrinterModel::printerAdded); | 33 | this, &PrinterModel::printerAdded); |
2848 | 33 | QObject::connect(m_backend, &PrinterBackend::printerModified, | 34 | QObject::connect(m_backend, &PrinterBackend::printerModified, |
2850 | 34 | &m_signalHandler, &PrinterSignalHandler::onPrinterModified); | 35 | &m_signalHandler, &SignalRateLimiter::onPrinterModified); |
2851 | 35 | QObject::connect(m_backend, &PrinterBackend::printerStateChanged, | 36 | QObject::connect(m_backend, &PrinterBackend::printerStateChanged, |
2853 | 36 | &m_signalHandler, &PrinterSignalHandler::onPrinterModified); | 37 | &m_signalHandler, &SignalRateLimiter::onPrinterModified); |
2854 | 37 | QObject::connect(m_backend, &PrinterBackend::printerDeleted, | 38 | QObject::connect(m_backend, &PrinterBackend::printerDeleted, |
2855 | 38 | this, &PrinterModel::printerDeleted); | 39 | this, &PrinterModel::printerDeleted); |
2856 | 39 | 40 | ||
2857 | @@ -63,20 +64,18 @@ | |||
2858 | 63 | 64 | ||
2859 | 64 | void PrinterModel::printerLoaded(QSharedPointer<Printer> printer) | 65 | void PrinterModel::printerLoaded(QSharedPointer<Printer> printer) |
2860 | 65 | { | 66 | { |
2868 | 66 | // Find and possibly replace an old printer. | 67 | // If there is an existing printer then get it |
2869 | 67 | for (int i=0; i < m_printers.count(); i++) { | 68 | QSharedPointer<Printer> oldPrinter = getPrinterByName(printer->name()); |
2863 | 68 | auto oldPrinter = m_printers.at(i); | ||
2864 | 69 | if (printer->name() == oldPrinter->name()) { | ||
2865 | 70 | if (!oldPrinter->deepCompare(printer)) { | ||
2866 | 71 | updatePrinter(oldPrinter, printer); | ||
2867 | 72 | } | ||
2870 | 73 | 69 | ||
2873 | 74 | // We're done. | 70 | if (oldPrinter) { |
2874 | 75 | return; | 71 | // Check if the existing printer needs updating |
2875 | 72 | if (!oldPrinter->deepCompare(printer)) { | ||
2876 | 73 | updatePrinter(oldPrinter, printer); | ||
2877 | 76 | } | 74 | } |
2878 | 75 | } else { | ||
2879 | 76 | // There isn't an existing printer so add it | ||
2880 | 77 | addPrinter(printer, CountChangeSignal::Emit); | ||
2881 | 77 | } | 78 | } |
2882 | 78 | |||
2883 | 79 | addPrinter(printer, CountChangeSignal::Emit); | ||
2884 | 80 | } | 79 | } |
2885 | 81 | 80 | ||
2886 | 82 | void PrinterModel::printerModified(const QString &printerName) | 81 | void PrinterModel::printerModified(const QString &printerName) |
2887 | @@ -97,6 +96,12 @@ | |||
2888 | 97 | Q_UNUSED(printerStateReason); | 96 | Q_UNUSED(printerStateReason); |
2889 | 98 | Q_UNUSED(acceptingJobs); | 97 | Q_UNUSED(acceptingJobs); |
2890 | 99 | 98 | ||
2891 | 99 | // If there isn't an existing printer then add a proxy printer | ||
2892 | 100 | if (!getPrinterByName(printerName)) { | ||
2893 | 101 | auto p = QSharedPointer<Printer>(new Printer(new PrinterBackend(printerName))); | ||
2894 | 102 | addPrinter(p); | ||
2895 | 103 | } | ||
2896 | 104 | |||
2897 | 100 | m_backend->requestPrinter(printerName); | 105 | m_backend->requestPrinter(printerName); |
2898 | 101 | } | 106 | } |
2899 | 102 | 107 | ||
2900 | @@ -126,22 +131,6 @@ | |||
2901 | 126 | return QSharedPointer<Printer>(Q_NULLPTR); | 131 | return QSharedPointer<Printer>(Q_NULLPTR); |
2902 | 127 | } | 132 | } |
2903 | 128 | 133 | ||
2904 | 129 | void PrinterModel::movePrinter(const int &from, const int &to) | ||
2905 | 130 | { | ||
2906 | 131 | int size = m_printers.size(); | ||
2907 | 132 | if (from < 0 || to < 0 || from >= size || to >= size) { | ||
2908 | 133 | qWarning() << Q_FUNC_INFO << "Illegal move operation from" | ||
2909 | 134 | << from << "to" << to << ". Size was" << size; | ||
2910 | 135 | return; | ||
2911 | 136 | } | ||
2912 | 137 | if (!beginMoveRows(QModelIndex(), from, from, QModelIndex(), to)) { | ||
2913 | 138 | qWarning() << Q_FUNC_INFO << "failed to move rows."; | ||
2914 | 139 | return; | ||
2915 | 140 | } | ||
2916 | 141 | m_printers.move(from, to); | ||
2917 | 142 | endMoveRows(); | ||
2918 | 143 | } | ||
2919 | 144 | |||
2920 | 145 | void PrinterModel::removePrinter(QSharedPointer<Printer> printer, const CountChangeSignal ¬ify) | 134 | void PrinterModel::removePrinter(QSharedPointer<Printer> printer, const CountChangeSignal ¬ify) |
2921 | 146 | { | 135 | { |
2922 | 147 | int idx = m_printers.indexOf(printer); | 136 | int idx = m_printers.indexOf(printer); |
2923 | @@ -214,6 +203,15 @@ | |||
2924 | 214 | case Qt::DisplayRole: | 203 | case Qt::DisplayRole: |
2925 | 215 | ret = printer->name(); | 204 | ret = printer->name(); |
2926 | 216 | break; | 205 | break; |
2927 | 206 | case DeviceUriRole: | ||
2928 | 207 | ret = printer->deviceUri(); | ||
2929 | 208 | break; | ||
2930 | 209 | case HostNameRole: | ||
2931 | 210 | ret = QUrl(printer->deviceUri()).host(); | ||
2932 | 211 | break; | ||
2933 | 212 | case MakeRole: | ||
2934 | 213 | ret = printer->make(); | ||
2935 | 214 | break; | ||
2936 | 217 | case ColorModelRole: | 215 | case ColorModelRole: |
2937 | 218 | ret = printer->supportedColorModels().indexOf(printer->defaultColorModel()); | 216 | ret = printer->supportedColorModels().indexOf(printer->defaultColorModel()); |
2938 | 219 | break; | 217 | break; |
2939 | @@ -248,6 +246,9 @@ | |||
2940 | 248 | case DescriptionRole: | 246 | case DescriptionRole: |
2941 | 249 | ret = printer->description(); | 247 | ret = printer->description(); |
2942 | 250 | break; | 248 | break; |
2943 | 249 | case LocationRole: | ||
2944 | 250 | ret = printer->location(); | ||
2945 | 251 | break; | ||
2946 | 251 | case PageSizeRole: | 252 | case PageSizeRole: |
2947 | 252 | ret = printer->defaultPageSize().name(); | 253 | ret = printer->defaultPageSize().name(); |
2948 | 253 | break; | 254 | break; |
2949 | @@ -274,15 +275,27 @@ | |||
2950 | 274 | case IsRawRole: | 275 | case IsRawRole: |
2951 | 275 | ret = !printer->holdsDefinition(); | 276 | ret = !printer->holdsDefinition(); |
2952 | 276 | break; | 277 | break; |
2953 | 278 | case IsRemoteRole: | ||
2954 | 279 | ret = printer->isRemote(); | ||
2955 | 280 | break; | ||
2956 | 281 | case LastMessageRole: | ||
2957 | 282 | ret = printer->lastMessage(); | ||
2958 | 283 | break; | ||
2959 | 277 | case JobRole: | 284 | case JobRole: |
2960 | 278 | ret = QVariant::fromValue(printer->jobs()); | 285 | ret = QVariant::fromValue(printer->jobs()); |
2961 | 279 | break; | 286 | break; |
2962 | 287 | case CopiesRole: | ||
2963 | 288 | ret = printer->copies(); | ||
2964 | 289 | break; | ||
2965 | 280 | case EnabledRole: | 290 | case EnabledRole: |
2966 | 281 | ret = printer->enabled(); | 291 | ret = printer->enabled(); |
2967 | 282 | break; | 292 | break; |
2968 | 283 | case AcceptJobsRole: | 293 | case AcceptJobsRole: |
2969 | 284 | ret = printer->acceptJobs(); | 294 | ret = printer->acceptJobs(); |
2970 | 285 | break; | 295 | break; |
2971 | 296 | case SharedRole: | ||
2972 | 297 | ret = printer->shared(); | ||
2973 | 298 | break; | ||
2974 | 286 | } | 299 | } |
2975 | 287 | } | 300 | } |
2976 | 288 | 301 | ||
2977 | @@ -338,6 +351,11 @@ | |||
2978 | 338 | case AcceptJobsRole: | 351 | case AcceptJobsRole: |
2979 | 339 | printer->setAcceptJobs(value.toBool()); | 352 | printer->setAcceptJobs(value.toBool()); |
2980 | 340 | break; | 353 | break; |
2981 | 354 | case CopiesRole: | ||
2982 | 355 | printer->setCopies(value.toInt()); | ||
2983 | 356 | case SharedRole: | ||
2984 | 357 | printer->setShared(value.toBool()); | ||
2985 | 358 | break; | ||
2986 | 341 | } | 359 | } |
2987 | 342 | } | 360 | } |
2988 | 343 | 361 | ||
2989 | @@ -356,12 +374,16 @@ | |||
2990 | 356 | names[DuplexRole] = "duplexMode"; | 374 | names[DuplexRole] = "duplexMode"; |
2991 | 357 | names[SupportedDuplexModesRole] = "supportedDuplexModes"; | 375 | names[SupportedDuplexModesRole] = "supportedDuplexModes"; |
2992 | 358 | names[NameRole] = "name"; | 376 | names[NameRole] = "name"; |
2993 | 377 | names[DeviceUriRole] = "deviceUri"; | ||
2994 | 378 | names[HostNameRole] = "hostname"; | ||
2995 | 379 | names[MakeRole] = "make"; | ||
2996 | 359 | names[EnabledRole] = "printerEnabled"; | 380 | names[EnabledRole] = "printerEnabled"; |
2997 | 360 | names[AcceptJobsRole] = "acceptJobs"; | 381 | names[AcceptJobsRole] = "acceptJobs"; |
2999 | 361 | names[PdfModeRole] = "pdfMode"; | 382 | names[SharedRole] = "shared"; |
3000 | 362 | names[PrintQualityRole] = "printQuality"; | 383 | names[PrintQualityRole] = "printQuality"; |
3001 | 363 | names[SupportedPrintQualitiesRole] = "supportedPrintQualities"; | 384 | names[SupportedPrintQualitiesRole] = "supportedPrintQualities"; |
3002 | 364 | names[DescriptionRole] = "description"; | 385 | names[DescriptionRole] = "description"; |
3003 | 386 | names[LocationRole] = "location"; | ||
3004 | 365 | names[PageSizeRole] = "pageSize"; | 387 | names[PageSizeRole] = "pageSize"; |
3005 | 366 | names[SupportedPageSizesRole] = "supportedPageSizes"; | 388 | names[SupportedPageSizesRole] = "supportedPageSizes"; |
3006 | 367 | names[StateRole] = "state"; | 389 | names[StateRole] = "state"; |
3007 | @@ -369,6 +391,9 @@ | |||
3008 | 369 | names[IsPdfRole] = "isPdf"; | 391 | names[IsPdfRole] = "isPdf"; |
3009 | 370 | names[IsLoadedRole] = "isLoaded"; | 392 | names[IsLoadedRole] = "isLoaded"; |
3010 | 371 | names[IsRawRole] = "isRaw"; | 393 | names[IsRawRole] = "isRaw"; |
3011 | 394 | names[IsRemoteRole] = "isRemote"; | ||
3012 | 395 | names[LastMessageRole] = "lastMessage"; | ||
3013 | 396 | names[CopiesRole] = "copies"; | ||
3014 | 372 | names[JobRole] = "jobs"; | 397 | names[JobRole] = "jobs"; |
3015 | 373 | } | 398 | } |
3016 | 374 | 399 | ||
3017 | @@ -447,6 +472,13 @@ | |||
3018 | 447 | m_pdf = pdf; | 472 | m_pdf = pdf; |
3019 | 448 | } | 473 | } |
3020 | 449 | 474 | ||
3021 | 475 | void PrinterFilter::filterOnRemote(const bool remote) | ||
3022 | 476 | { | ||
3023 | 477 | m_remoteEnabled = true; | ||
3024 | 478 | m_remote = remote; | ||
3025 | 479 | invalidate(); | ||
3026 | 480 | } | ||
3027 | 481 | |||
3028 | 450 | bool PrinterFilter::filterAcceptsRow(int sourceRow, | 482 | bool PrinterFilter::filterAcceptsRow(int sourceRow, |
3029 | 451 | const QModelIndex &sourceParent) const | 483 | const QModelIndex &sourceParent) const |
3030 | 452 | { | 484 | { |
3031 | @@ -472,6 +504,14 @@ | |||
3032 | 472 | accepts = m_state == state; | 504 | accepts = m_state == state; |
3033 | 473 | } | 505 | } |
3034 | 474 | 506 | ||
3035 | 507 | // If m_remote is true, we only show remote printers. | ||
3036 | 508 | if (accepts && m_remoteEnabled) { | ||
3037 | 509 | const bool isRemote = childIndex.model()->data( | ||
3038 | 510 | childIndex, PrinterModel::IsRemoteRole | ||
3039 | 511 | ).toBool(); | ||
3040 | 512 | accepts = m_remote == isRemote; | ||
3041 | 513 | } | ||
3042 | 514 | |||
3043 | 475 | return accepts; | 515 | return accepts; |
3044 | 476 | } | 516 | } |
3045 | 477 | bool PrinterFilter::lessThan(const QModelIndex &left, | 517 | bool PrinterFilter::lessThan(const QModelIndex &left, |
3046 | 478 | 518 | ||
3047 | === modified file 'modules/Ubuntu/Components/Extras/Printers/models/printermodel.h' | |||
3048 | --- modules/Ubuntu/Components/Extras/Printers/models/printermodel.h 2017-02-23 14:04:26 +0000 | |||
3049 | +++ modules/Ubuntu/Components/Extras/Printers/models/printermodel.h 2017-03-23 12:51:36 +0000 | |||
3050 | @@ -21,7 +21,7 @@ | |||
3051 | 21 | 21 | ||
3052 | 22 | #include "models/jobmodel.h" | 22 | #include "models/jobmodel.h" |
3053 | 23 | #include "printer/printer.h" | 23 | #include "printer/printer.h" |
3055 | 24 | #include "printer/printersignalhandler.h" | 24 | #include "printer/signalratelimiter.h" |
3056 | 25 | 25 | ||
3057 | 26 | #include <QAbstractListModel> | 26 | #include <QAbstractListModel> |
3058 | 27 | #include <QByteArray> | 27 | #include <QByteArray> |
3059 | @@ -47,9 +47,13 @@ | |||
3060 | 47 | DuplexRole, | 47 | DuplexRole, |
3061 | 48 | SupportedDuplexModesRole, | 48 | SupportedDuplexModesRole, |
3062 | 49 | NameRole, | 49 | NameRole, |
3063 | 50 | DeviceUriRole, | ||
3064 | 51 | HostNameRole, | ||
3065 | 52 | MakeRole, | ||
3066 | 53 | LocationRole, | ||
3067 | 50 | EnabledRole, | 54 | EnabledRole, |
3068 | 51 | AcceptJobsRole, | 55 | AcceptJobsRole, |
3070 | 52 | PdfModeRole, | 56 | SharedRole, |
3071 | 53 | PrintQualityRole, | 57 | PrintQualityRole, |
3072 | 54 | SupportedPrintQualitiesRole, | 58 | SupportedPrintQualitiesRole, |
3073 | 55 | DescriptionRole, | 59 | DescriptionRole, |
3074 | @@ -68,6 +72,9 @@ | |||
3075 | 68 | 72 | ||
3076 | 69 | /* Indicates that this printers has no associated PPD. */ | 73 | /* Indicates that this printers has no associated PPD. */ |
3077 | 70 | IsRawRole, | 74 | IsRawRole, |
3078 | 75 | IsRemoteRole, | ||
3079 | 76 | LastMessageRole, | ||
3080 | 77 | CopiesRole, | ||
3081 | 71 | JobRole, | 78 | JobRole, |
3082 | 72 | LastRole = JobRole, | 79 | LastRole = JobRole, |
3083 | 73 | }; | 80 | }; |
3084 | @@ -92,13 +99,12 @@ | |||
3085 | 92 | const CountChangeSignal ¬ify = CountChangeSignal::Defer); | 99 | const CountChangeSignal ¬ify = CountChangeSignal::Defer); |
3086 | 93 | void removePrinter(QSharedPointer<Printer> printer, | 100 | void removePrinter(QSharedPointer<Printer> printer, |
3087 | 94 | const CountChangeSignal ¬ify = CountChangeSignal::Defer); | 101 | const CountChangeSignal ¬ify = CountChangeSignal::Defer); |
3088 | 95 | void movePrinter(const int &from, const int &to); | ||
3089 | 96 | void updatePrinter(QSharedPointer<Printer> old, | 102 | void updatePrinter(QSharedPointer<Printer> old, |
3090 | 97 | QSharedPointer<Printer> newPrinter); | 103 | QSharedPointer<Printer> newPrinter); |
3091 | 98 | PrinterBackend *m_backend; | 104 | PrinterBackend *m_backend; |
3092 | 99 | 105 | ||
3093 | 100 | QList<QSharedPointer<Printer>> m_printers; | 106 | QList<QSharedPointer<Printer>> m_printers; |
3095 | 101 | PrinterSignalHandler m_signalHandler; | 107 | SignalRateLimiter m_signalHandler; |
3096 | 102 | 108 | ||
3097 | 103 | private Q_SLOTS: | 109 | private Q_SLOTS: |
3098 | 104 | void printerLoaded(QSharedPointer<Printer> printer); | 110 | void printerLoaded(QSharedPointer<Printer> printer); |
3099 | @@ -127,6 +133,7 @@ | |||
3100 | 127 | void filterOnState(const PrinterEnum::State &state); | 133 | void filterOnState(const PrinterEnum::State &state); |
3101 | 128 | void filterOnRecent(const bool recent); | 134 | void filterOnRecent(const bool recent); |
3102 | 129 | void filterOnPdf(const bool pdf); | 135 | void filterOnPdf(const bool pdf); |
3103 | 136 | void filterOnRemote(const bool remote); | ||
3104 | 130 | 137 | ||
3105 | 131 | int count() const; | 138 | int count() const; |
3106 | 132 | protected: | 139 | protected: |
3107 | @@ -149,6 +156,8 @@ | |||
3108 | 149 | bool m_recentEnabled = false; | 156 | bool m_recentEnabled = false; |
3109 | 150 | bool m_pdfEnabled = false; | 157 | bool m_pdfEnabled = false; |
3110 | 151 | bool m_pdf = false; | 158 | bool m_pdf = false; |
3111 | 159 | bool m_remoteEnabled = false; | ||
3112 | 160 | bool m_remote = false; | ||
3113 | 152 | }; | 161 | }; |
3114 | 153 | 162 | ||
3115 | 154 | #endif // USC_PRINTER_MODEL_H | 163 | #endif // USC_PRINTER_MODEL_H |
3116 | 155 | 164 | ||
3117 | === modified file 'modules/Ubuntu/Components/Extras/Printers/plugin.cpp' | |||
3118 | --- modules/Ubuntu/Components/Extras/Printers/plugin.cpp 2017-02-21 11:31:44 +0000 | |||
3119 | +++ modules/Ubuntu/Components/Extras/Printers/plugin.cpp 2017-03-23 12:51:36 +0000 | |||
3120 | @@ -54,5 +54,7 @@ | |||
3121 | 54 | 54 | ||
3122 | 55 | qmlRegisterUncreatableType<PrinterEnum>(uri, 0, 1, "PrinterEnum", "Is an enum"); | 55 | qmlRegisterUncreatableType<PrinterEnum>(uri, 0, 1, "PrinterEnum", "Is an enum"); |
3123 | 56 | qRegisterMetaType<QList<PrinterDriver>>("QList<PrinterDriver>"); | 56 | qRegisterMetaType<QList<PrinterDriver>>("QList<PrinterDriver>"); |
3124 | 57 | qRegisterMetaType<QSharedPointer<PrinterJob>>("QSharedPointer<PrinterJob>"); | ||
3125 | 57 | qRegisterMetaType<QList<QSharedPointer<Printer>>>("QList<QSharedPointer<Printer>>"); | 58 | qRegisterMetaType<QList<QSharedPointer<Printer>>>("QList<QSharedPointer<Printer>>"); |
3126 | 59 | qRegisterMetaType<Device>("Device"); | ||
3127 | 58 | } | 60 | } |
3128 | 59 | 61 | ||
3129 | === modified file 'modules/Ubuntu/Components/Extras/Printers/printer/printer.cpp' | |||
3130 | --- modules/Ubuntu/Components/Extras/Printers/printer/printer.cpp 2017-02-24 17:47:22 +0000 | |||
3131 | +++ modules/Ubuntu/Components/Extras/Printers/printer/printer.cpp 2017-03-23 12:51:36 +0000 | |||
3132 | @@ -14,22 +14,26 @@ | |||
3133 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3134 | 15 | */ | 15 | */ |
3135 | 16 | 16 | ||
3136 | 17 | #include "i18n.h" | ||
3137 | 17 | #include "utils.h" | 18 | #include "utils.h" |
3138 | 18 | 19 | ||
3139 | 19 | #include "printer.h" | 20 | #include "printer.h" |
3140 | 20 | 21 | ||
3141 | 21 | #include <QDebug> | 22 | #include <QDebug> |
3142 | 23 | #include <QLocale> | ||
3143 | 22 | #include <QQmlEngine> | 24 | #include <QQmlEngine> |
3144 | 23 | 25 | ||
3145 | 24 | Printer::Printer(PrinterBackend *backend, QObject *parent) | 26 | Printer::Printer(PrinterBackend *backend, QObject *parent) |
3146 | 25 | : QObject(parent) | 27 | : QObject(parent) |
3147 | 26 | , m_backend(backend) | 28 | , m_backend(backend) |
3148 | 27 | { | 29 | { |
3152 | 28 | loadColorModel(); | 30 | loadAttributes(); |
3150 | 29 | loadPrintQualities(); | ||
3151 | 30 | loadAcceptJobs(); | ||
3153 | 31 | 31 | ||
3154 | 32 | m_jobs.setParent(this); | ||
3155 | 32 | m_jobs.filterOnPrinterName(name()); | 33 | m_jobs.filterOnPrinterName(name()); |
3156 | 34 | |||
3157 | 35 | QObject::connect(m_backend, &PrinterBackend::printerStateChanged, | ||
3158 | 36 | this, &Printer::onPrinterStateChanged); | ||
3159 | 33 | } | 37 | } |
3160 | 34 | 38 | ||
3161 | 35 | Printer::~Printer() | 39 | Printer::~Printer() |
3162 | @@ -41,48 +45,87 @@ | |||
3163 | 41 | { | 45 | { |
3164 | 42 | if (!m_jobs.sourceModel()) { | 46 | if (!m_jobs.sourceModel()) { |
3165 | 43 | m_jobs.setSourceModel(jobModel); | 47 | m_jobs.setSourceModel(jobModel); |
3166 | 44 | m_jobs.sort(JobModel::Roles::IdRole); | ||
3167 | 45 | } | 48 | } |
3168 | 46 | } | 49 | } |
3169 | 47 | 50 | ||
3171 | 48 | void Printer::loadAcceptJobs() | 51 | void Printer::updateAcceptJobs(const QMap<QString, QVariant> &serverAttrs) |
3172 | 49 | { | 52 | { |
3175 | 50 | auto opt = QStringLiteral("AcceptJobs"); | 53 | m_acceptJobs = serverAttrs.value(QStringLiteral("AcceptJobs")).toBool(); |
3174 | 51 | m_acceptJobs = m_backend->printerGetOption(name(), opt).toBool(); | ||
3176 | 52 | } | 54 | } |
3177 | 53 | 55 | ||
3179 | 54 | void Printer::loadColorModel() | 56 | void Printer::updateColorModel(const QMap<QString, QVariant> &serverAttrs) |
3180 | 55 | { | 57 | { |
3181 | 56 | auto defModel = QStringLiteral("DefaultColorModel"); | 58 | auto defModel = QStringLiteral("DefaultColorModel"); |
3182 | 57 | auto models = QStringLiteral("SupportedColorModels"); | 59 | auto models = QStringLiteral("SupportedColorModels"); |
3183 | 58 | auto result = m_backend->printerGetOptions( | ||
3184 | 59 | name(), QStringList({defModel, models}) | ||
3185 | 60 | ); | ||
3186 | 61 | 60 | ||
3189 | 62 | m_defaultColorModel = result.value(defModel).value<ColorModel>(); | 61 | m_defaultColorModel = serverAttrs.value(defModel).value<ColorModel>(); |
3190 | 63 | m_supportedColorModels = result.value(models).value<QList<ColorModel>>(); | 62 | m_supportedColorModels = serverAttrs.value(models).value<QList<ColorModel>>(); |
3191 | 64 | 63 | ||
3192 | 65 | if (m_supportedColorModels.size() == 0) { | 64 | if (m_supportedColorModels.size() == 0) { |
3193 | 66 | m_supportedColorModels.append(m_defaultColorModel); | 65 | m_supportedColorModels.append(m_defaultColorModel); |
3194 | 67 | } | 66 | } |
3195 | 68 | } | 67 | } |
3196 | 69 | 68 | ||
3198 | 70 | void Printer::loadPrintQualities() | 69 | void Printer::updatePrintQualities(const QMap<QString, QVariant> &serverAttrs) |
3199 | 71 | { | 70 | { |
3200 | 72 | auto defQuality = QStringLiteral("DefaultPrintQuality"); | 71 | auto defQuality = QStringLiteral("DefaultPrintQuality"); |
3201 | 73 | auto qualities = QStringLiteral("SupportedPrintQualities"); | 72 | auto qualities = QStringLiteral("SupportedPrintQualities"); |
3202 | 74 | auto result = m_backend->printerGetOptions( | ||
3203 | 75 | name(), QStringList({defQuality, qualities}) | ||
3204 | 76 | ); | ||
3205 | 77 | 73 | ||
3208 | 78 | m_supportedPrintQualities = result.value(qualities).value<QList<PrintQuality>>(); | 74 | m_supportedPrintQualities = serverAttrs.value(qualities).value<QList<PrintQuality>>(); |
3209 | 79 | m_defaultPrintQuality = result.value(defQuality).value<PrintQuality>(); | 75 | m_defaultPrintQuality = serverAttrs.value(defQuality).value<PrintQuality>(); |
3210 | 80 | 76 | ||
3211 | 81 | if (m_supportedPrintQualities.size() == 0) { | 77 | if (m_supportedPrintQualities.size() == 0) { |
3212 | 82 | m_supportedPrintQualities.append(m_defaultPrintQuality); | 78 | m_supportedPrintQualities.append(m_defaultPrintQuality); |
3213 | 83 | } | 79 | } |
3214 | 84 | } | 80 | } |
3215 | 85 | 81 | ||
3216 | 82 | void Printer::updateLastMessage(const QMap<QString, QVariant> &serverAttrs) | ||
3217 | 83 | { | ||
3218 | 84 | m_stateMessage = serverAttrs.value(QStringLiteral("StateMessage")).toString(); | ||
3219 | 85 | } | ||
3220 | 86 | |||
3221 | 87 | |||
3222 | 88 | void Printer::updateDeviceUri(const QMap<QString, QVariant> &serverAttrs) | ||
3223 | 89 | { | ||
3224 | 90 | m_deviceUri = serverAttrs.value(QStringLiteral("DeviceUri")).toString(); | ||
3225 | 91 | } | ||
3226 | 92 | |||
3227 | 93 | void Printer::updateCopies(const QMap<QString, QVariant> &serverAttrs) | ||
3228 | 94 | { | ||
3229 | 95 | m_copies = serverAttrs.value(QStringLiteral("Copies")).toInt(); | ||
3230 | 96 | if (m_copies <= 0) | ||
3231 | 97 | m_copies = 1; | ||
3232 | 98 | } | ||
3233 | 99 | |||
3234 | 100 | void Printer::updateShared(const QMap<QString, QVariant> &serverAttrs) | ||
3235 | 101 | { | ||
3236 | 102 | m_shared = serverAttrs.value(QStringLiteral("Shared")).toBool(); | ||
3237 | 103 | } | ||
3238 | 104 | |||
3239 | 105 | void Printer::loadAttributes() | ||
3240 | 106 | { | ||
3241 | 107 | auto opts = QStringList({ | ||
3242 | 108 | QStringLiteral("AcceptJobs"), | ||
3243 | 109 | QStringLiteral("DefaultColorModel"), | ||
3244 | 110 | QStringLiteral("SupportedColorModels"), | ||
3245 | 111 | QStringLiteral("DefaultPrintQuality"), | ||
3246 | 112 | QStringLiteral("SupportedPrintQualities"), | ||
3247 | 113 | QStringLiteral("StateMessage"), | ||
3248 | 114 | QStringLiteral("DeviceUri"), | ||
3249 | 115 | QStringLiteral("Copies"), | ||
3250 | 116 | QStringLiteral("Shared"), | ||
3251 | 117 | }); | ||
3252 | 118 | auto result = m_backend->printerGetOptions(name(), opts); | ||
3253 | 119 | |||
3254 | 120 | updateAcceptJobs(result); | ||
3255 | 121 | updateColorModel(result); | ||
3256 | 122 | updatePrintQualities(result); | ||
3257 | 123 | updateLastMessage(result); | ||
3258 | 124 | updateDeviceUri(result); | ||
3259 | 125 | updateCopies(result); | ||
3260 | 126 | updateShared(result); | ||
3261 | 127 | } | ||
3262 | 128 | |||
3263 | 86 | ColorModel Printer::defaultColorModel() const | 129 | ColorModel Printer::defaultColorModel() const |
3264 | 87 | { | 130 | { |
3265 | 88 | return m_defaultColorModel; | 131 | return m_defaultColorModel; |
3266 | @@ -135,11 +178,26 @@ | |||
3267 | 135 | return m_backend->printerName(); | 178 | return m_backend->printerName(); |
3268 | 136 | } | 179 | } |
3269 | 137 | 180 | ||
3270 | 181 | QString Printer::deviceUri() const | ||
3271 | 182 | { | ||
3272 | 183 | return m_deviceUri; | ||
3273 | 184 | } | ||
3274 | 185 | |||
3275 | 186 | QString Printer::make() const | ||
3276 | 187 | { | ||
3277 | 188 | return m_backend->makeAndModel(); | ||
3278 | 189 | } | ||
3279 | 190 | |||
3280 | 138 | QString Printer::description() const | 191 | QString Printer::description() const |
3281 | 139 | { | 192 | { |
3282 | 140 | return m_backend->description(); | 193 | return m_backend->description(); |
3283 | 141 | } | 194 | } |
3284 | 142 | 195 | ||
3285 | 196 | QString Printer::location() const | ||
3286 | 197 | { | ||
3287 | 198 | return m_backend->location(); | ||
3288 | 199 | } | ||
3289 | 200 | |||
3290 | 143 | QPageSize Printer::defaultPageSize() const | 201 | QPageSize Printer::defaultPageSize() const |
3291 | 144 | { | 202 | { |
3292 | 145 | return m_backend->defaultPageSize(); | 203 | return m_backend->defaultPageSize(); |
3293 | @@ -170,6 +228,11 @@ | |||
3294 | 170 | return m_backend->state(); | 228 | return m_backend->state(); |
3295 | 171 | } | 229 | } |
3296 | 172 | 230 | ||
3297 | 231 | bool Printer::shared() const | ||
3298 | 232 | { | ||
3299 | 233 | return m_shared; | ||
3300 | 234 | } | ||
3301 | 235 | |||
3302 | 173 | bool Printer::acceptJobs() const | 236 | bool Printer::acceptJobs() const |
3303 | 174 | { | 237 | { |
3304 | 175 | return m_acceptJobs; | 238 | return m_acceptJobs; |
3305 | @@ -180,11 +243,21 @@ | |||
3306 | 180 | return m_backend->holdsDefinition(); | 243 | return m_backend->holdsDefinition(); |
3307 | 181 | } | 244 | } |
3308 | 182 | 245 | ||
3309 | 246 | bool Printer::isRemote() const | ||
3310 | 247 | { | ||
3311 | 248 | return m_backend->isRemote(); | ||
3312 | 249 | } | ||
3313 | 250 | |||
3314 | 183 | PrinterEnum::PrinterType Printer::type() const | 251 | PrinterEnum::PrinterType Printer::type() const |
3315 | 184 | { | 252 | { |
3316 | 185 | return m_backend->type(); | 253 | return m_backend->type(); |
3317 | 186 | } | 254 | } |
3318 | 187 | 255 | ||
3319 | 256 | int Printer::copies() const | ||
3320 | 257 | { | ||
3321 | 258 | return m_copies; | ||
3322 | 259 | } | ||
3323 | 260 | |||
3324 | 188 | void Printer::setDefaultColorModel(const ColorModel &colorModel) | 261 | void Printer::setDefaultColorModel(const ColorModel &colorModel) |
3325 | 189 | { | 262 | { |
3326 | 190 | if (defaultColorModel() == colorModel) { | 263 | if (defaultColorModel() == colorModel) { |
3327 | @@ -229,6 +302,7 @@ | |||
3328 | 229 | if (!reply.isEmpty()) { | 302 | if (!reply.isEmpty()) { |
3329 | 230 | qWarning() << Q_FUNC_INFO << "failed to set enabled:" << reply; | 303 | qWarning() << Q_FUNC_INFO << "failed to set enabled:" << reply; |
3330 | 231 | } | 304 | } |
3331 | 305 | m_backend->refresh(); | ||
3332 | 232 | } | 306 | } |
3333 | 233 | } | 307 | } |
3334 | 234 | 308 | ||
3335 | @@ -242,6 +316,16 @@ | |||
3336 | 242 | } | 316 | } |
3337 | 243 | } | 317 | } |
3338 | 244 | 318 | ||
3339 | 319 | void Printer::setShared(const bool shared) | ||
3340 | 320 | { | ||
3341 | 321 | if (this->shared() != shared) { | ||
3342 | 322 | QString reply = m_backend->printerSetShared(name(), shared); | ||
3343 | 323 | if (!reply.isEmpty()) { | ||
3344 | 324 | qWarning() << Q_FUNC_INFO << "failed to set shared:" << reply; | ||
3345 | 325 | } | ||
3346 | 326 | } | ||
3347 | 327 | } | ||
3348 | 328 | |||
3349 | 245 | void Printer::setDefaultPrintQuality(const PrintQuality &quality) | 329 | void Printer::setDefaultPrintQuality(const PrintQuality &quality) |
3350 | 246 | { | 330 | { |
3351 | 247 | if (defaultPrintQuality() == quality) { | 331 | if (defaultPrintQuality() == quality) { |
3352 | @@ -278,6 +362,20 @@ | |||
3353 | 278 | m_backend->refresh(); | 362 | m_backend->refresh(); |
3354 | 279 | } | 363 | } |
3355 | 280 | 364 | ||
3356 | 365 | void Printer::setCopies(const int &copies) | ||
3357 | 366 | { | ||
3358 | 367 | if (this->copies() == copies) { | ||
3359 | 368 | return; | ||
3360 | 369 | } | ||
3361 | 370 | |||
3362 | 371 | m_backend->printerSetCopies(name(), copies); | ||
3363 | 372 | } | ||
3364 | 373 | |||
3365 | 374 | QString Printer::lastMessage() const | ||
3366 | 375 | { | ||
3367 | 376 | return m_stateMessage; | ||
3368 | 377 | } | ||
3369 | 378 | |||
3370 | 281 | QAbstractItemModel* Printer::jobs() | 379 | QAbstractItemModel* Printer::jobs() |
3371 | 282 | { | 380 | { |
3372 | 283 | auto ret = &m_jobs; | 381 | auto ret = &m_jobs; |
3373 | @@ -296,16 +394,44 @@ | |||
3374 | 296 | && type() == other->type() | 394 | && type() == other->type() |
3375 | 297 | && acceptJobs() == other->acceptJobs() | 395 | && acceptJobs() == other->acceptJobs() |
3376 | 298 | && enabled() == other->enabled() | 396 | && enabled() == other->enabled() |
3378 | 299 | && state() == other->state(); | 397 | && state() == other->state() |
3379 | 398 | && lastMessage() == other->lastMessage() | ||
3380 | 399 | && deviceUri() == other->deviceUri() | ||
3381 | 400 | && shared() == other->shared() | ||
3382 | 401 | && copies() == other->copies() | ||
3383 | 402 | && isRemote() == other->isRemote(); | ||
3384 | 300 | } | 403 | } |
3385 | 301 | 404 | ||
3386 | 302 | void Printer::updateFrom(QSharedPointer<Printer> other) | 405 | void Printer::updateFrom(QSharedPointer<Printer> other) |
3387 | 303 | { | 406 | { |
3388 | 304 | PrinterBackend *tmp = m_backend; | 407 | PrinterBackend *tmp = m_backend; |
3389 | 408 | |||
3390 | 409 | // Copy values from other printer which has been loaded in another thread | ||
3391 | 410 | // Note: do not use loadAttributes otherwise can cause UI block | ||
3392 | 411 | m_acceptJobs = other->m_acceptJobs; | ||
3393 | 305 | m_backend = other->m_backend; | 412 | m_backend = other->m_backend; |
3394 | 413 | m_defaultColorModel = other->m_defaultColorModel; | ||
3395 | 414 | m_defaultPrintQuality = other->m_defaultPrintQuality; | ||
3396 | 415 | m_deviceUri = other->m_deviceUri; | ||
3397 | 416 | m_shared = other->m_shared; | ||
3398 | 417 | m_stateMessage = other->m_stateMessage; | ||
3399 | 418 | m_supportedColorModels = other->m_supportedColorModels; | ||
3400 | 419 | m_supportedPrintQualities = other->m_supportedPrintQualities; | ||
3401 | 420 | |||
3402 | 306 | other->m_backend = tmp; | 421 | other->m_backend = tmp; |
3407 | 307 | 422 | } | |
3408 | 308 | loadColorModel(); | 423 | |
3409 | 309 | loadPrintQualities(); | 424 | void Printer::onPrinterStateChanged( |
3410 | 310 | loadAcceptJobs(); | 425 | const QString &text, const QString &printerUri, |
3411 | 426 | const QString &printerName, uint printerState, | ||
3412 | 427 | const QString &printerStateReason, bool acceptingJobs) | ||
3413 | 428 | { | ||
3414 | 429 | Q_UNUSED(printerUri); | ||
3415 | 430 | Q_UNUSED(printerState); | ||
3416 | 431 | Q_UNUSED(printerStateReason); | ||
3417 | 432 | Q_UNUSED(acceptingJobs); | ||
3418 | 433 | |||
3419 | 434 | if (name() == printerName) { | ||
3420 | 435 | m_stateMessage = text; | ||
3421 | 436 | } | ||
3422 | 311 | } | 437 | } |
3423 | 312 | 438 | ||
3424 | === modified file 'modules/Ubuntu/Components/Extras/Printers/printer/printer.h' | |||
3425 | --- modules/Ubuntu/Components/Extras/Printers/printer/printer.h 2017-02-23 14:04:26 +0000 | |||
3426 | +++ modules/Ubuntu/Components/Extras/Printers/printer/printer.h 2017-03-23 12:51:36 +0000 | |||
3427 | @@ -49,17 +49,24 @@ | |||
3428 | 49 | QStringList supportedDuplexStrings() const; | 49 | QStringList supportedDuplexStrings() const; |
3429 | 50 | PrinterEnum::DuplexMode defaultDuplexMode() const; | 50 | PrinterEnum::DuplexMode defaultDuplexMode() const; |
3430 | 51 | QString name() const; | 51 | QString name() const; |
3431 | 52 | QString deviceUri() const; | ||
3432 | 53 | QString make() const; | ||
3433 | 52 | PrintQuality defaultPrintQuality() const; | 54 | PrintQuality defaultPrintQuality() const; |
3434 | 53 | QList<PrintQuality> supportedPrintQualities() const; | 55 | QList<PrintQuality> supportedPrintQualities() const; |
3435 | 54 | QString description() const; | 56 | QString description() const; |
3436 | 57 | QString location() const; | ||
3437 | 55 | QPageSize defaultPageSize() const; | 58 | QPageSize defaultPageSize() const; |
3438 | 56 | QList<QPageSize> supportedPageSizes() const; | 59 | QList<QPageSize> supportedPageSizes() const; |
3439 | 57 | PrinterEnum::AccessControl accessControl() const; | 60 | PrinterEnum::AccessControl accessControl() const; |
3440 | 58 | PrinterEnum::ErrorPolicy errorPolicy() const; | 61 | PrinterEnum::ErrorPolicy errorPolicy() const; |
3441 | 59 | PrinterEnum::State state() const; | 62 | PrinterEnum::State state() const; |
3442 | 63 | bool shared() const; | ||
3443 | 60 | bool acceptJobs() const; | 64 | bool acceptJobs() const; |
3444 | 61 | bool holdsDefinition() const; | 65 | bool holdsDefinition() const; |
3445 | 66 | bool isRemote() const; | ||
3446 | 67 | QString lastMessage() const; | ||
3447 | 62 | QAbstractItemModel* jobs(); | 68 | QAbstractItemModel* jobs(); |
3448 | 69 | int copies() const; | ||
3449 | 63 | 70 | ||
3450 | 64 | PrinterEnum::PrinterType type() const; | 71 | PrinterEnum::PrinterType type() const; |
3451 | 65 | 72 | ||
3452 | @@ -68,9 +75,11 @@ | |||
3453 | 68 | void setDefaultDuplexMode(const PrinterEnum::DuplexMode &duplexMode); | 75 | void setDefaultDuplexMode(const PrinterEnum::DuplexMode &duplexMode); |
3454 | 69 | void setEnabled(const bool enabled); | 76 | void setEnabled(const bool enabled); |
3455 | 70 | void setAcceptJobs(const bool accepting); | 77 | void setAcceptJobs(const bool accepting); |
3456 | 78 | void setShared(const bool shared); | ||
3457 | 71 | void setDefaultPrintQuality(const PrintQuality &quality); | 79 | void setDefaultPrintQuality(const PrintQuality &quality); |
3458 | 72 | void setDefaultPageSize(const QPageSize &pageSize); | 80 | void setDefaultPageSize(const QPageSize &pageSize); |
3459 | 73 | void setJobModel(JobModel* jobModel); | 81 | void setJobModel(JobModel* jobModel); |
3460 | 82 | void setCopies(const int &copies); | ||
3461 | 74 | 83 | ||
3462 | 75 | bool deepCompare(QSharedPointer<Printer> other) const; | 84 | bool deepCompare(QSharedPointer<Printer> other) const; |
3463 | 76 | void updateFrom(QSharedPointer<Printer> other); | 85 | void updateFrom(QSharedPointer<Printer> other); |
3464 | @@ -79,10 +88,22 @@ | |||
3465 | 79 | public Q_SLOTS: | 88 | public Q_SLOTS: |
3466 | 80 | int printFile(const QString &filepath, const PrinterJob *options); | 89 | int printFile(const QString &filepath, const PrinterJob *options); |
3467 | 81 | 90 | ||
3468 | 91 | private Q_SLOTS: | ||
3469 | 92 | void onPrinterStateChanged( | ||
3470 | 93 | const QString &text, const QString &printerUri, | ||
3471 | 94 | const QString &printerName, uint printerState, | ||
3472 | 95 | const QString &printerStateReason, bool acceptingJobs | ||
3473 | 96 | ); | ||
3474 | 97 | |||
3475 | 82 | private: | 98 | private: |
3479 | 83 | void loadAcceptJobs(); | 99 | void updateAcceptJobs(const QMap<QString, QVariant> &serverAttrs); |
3480 | 84 | void loadColorModel(); | 100 | void updateColorModel(const QMap<QString, QVariant> &serverAttrs); |
3481 | 85 | void loadPrintQualities(); | 101 | void updatePrintQualities(const QMap<QString, QVariant> &serverAttrs); |
3482 | 102 | void updateLastMessage(const QMap<QString, QVariant> &serverAttrs); | ||
3483 | 103 | void updateDeviceUri(const QMap<QString, QVariant> &serverAttrs); | ||
3484 | 104 | void updateCopies(const QMap<QString, QVariant> &serverAttrs); | ||
3485 | 105 | void updateShared(const QMap<QString, QVariant> &serverAttrs); | ||
3486 | 106 | void loadAttributes(); | ||
3487 | 86 | 107 | ||
3488 | 87 | JobFilter m_jobs; | 108 | JobFilter m_jobs; |
3489 | 88 | PrinterBackend *m_backend; | 109 | PrinterBackend *m_backend; |
3490 | @@ -91,6 +112,11 @@ | |||
3491 | 91 | PrintQuality m_defaultPrintQuality; | 112 | PrintQuality m_defaultPrintQuality; |
3492 | 92 | QList<PrintQuality> m_supportedPrintQualities; | 113 | QList<PrintQuality> m_supportedPrintQualities; |
3493 | 93 | bool m_acceptJobs; | 114 | bool m_acceptJobs; |
3494 | 115 | bool m_shared; | ||
3495 | 116 | QString m_deviceUri; | ||
3496 | 117 | int m_copies; | ||
3497 | 118 | |||
3498 | 119 | QString m_stateMessage; | ||
3499 | 94 | }; | 120 | }; |
3500 | 95 | 121 | ||
3501 | 96 | #endif // USC_PRINTERS_PRINTER_H | 122 | #endif // USC_PRINTERS_PRINTER_H |
3502 | 97 | 123 | ||
3503 | === modified file 'modules/Ubuntu/Components/Extras/Printers/printer/printerjob.cpp' | |||
3504 | --- modules/Ubuntu/Components/Extras/Printers/printer/printerjob.cpp 2017-02-24 17:47:22 +0000 | |||
3505 | +++ modules/Ubuntu/Components/Extras/Printers/printer/printerjob.cpp 2017-03-23 12:51:36 +0000 | |||
3506 | @@ -55,6 +55,8 @@ | |||
3507 | 55 | , m_title(QStringLiteral("")) | 55 | , m_title(QStringLiteral("")) |
3508 | 56 | , m_user("") | 56 | , m_user("") |
3509 | 57 | { | 57 | { |
3510 | 58 | connect(this, SIGNAL(printerAboutToChange(QSharedPointer<Printer>, QSharedPointer<Printer>)), | ||
3511 | 59 | this, SLOT(onPrinterAboutToChange(QSharedPointer<Printer>, QSharedPointer<Printer>))); | ||
3512 | 58 | } | 60 | } |
3513 | 59 | 61 | ||
3514 | 60 | PrinterJob::~PrinterJob() | 62 | PrinterJob::~PrinterJob() |
3515 | @@ -143,6 +145,69 @@ | |||
3516 | 143 | return m_landscape; | 145 | return m_landscape; |
3517 | 144 | } | 146 | } |
3518 | 145 | 147 | ||
3519 | 148 | void PrinterJob::loadAttributes(const QMap<QString, QVariant> &attributes) | ||
3520 | 149 | { | ||
3521 | 150 | // Load the extra attributes for the job | ||
3522 | 151 | // NOTE: we don't need to type check them as they have been filtered for us | ||
3523 | 152 | |||
3524 | 153 | setCollate(attributes.value("Collate").toBool()); | ||
3525 | 154 | setCopies(attributes.value("copies").toInt()); | ||
3526 | 155 | |||
3527 | 156 | // No colorModel will result in PrinterJob using defaultColorModel | ||
3528 | 157 | QString colorModel = attributes.value("ColorModel").toString(); | ||
3529 | 158 | for (int i=0; i < m_printer->supportedColorModels().length(); i++) { | ||
3530 | 159 | if (m_printer->supportedColorModels().at(i).name == colorModel) { | ||
3531 | 160 | setColorModel(i); | ||
3532 | 161 | } | ||
3533 | 162 | } | ||
3534 | 163 | |||
3535 | 164 | setCompletedTime(attributes.value("CompletedTime").toDateTime()); | ||
3536 | 165 | setCreationTime(attributes.value("CreationTime").toDateTime()); | ||
3537 | 166 | |||
3538 | 167 | // No duplexMode will result in PrinterJob using defaultDuplexMode | ||
3539 | 168 | QString duplex = attributes.value("Duplex").toString(); | ||
3540 | 169 | PrinterEnum::DuplexMode duplexMode = Utils::ppdChoiceToDuplexMode(duplex); | ||
3541 | 170 | for (int i=0; i < m_printer->supportedDuplexModes().length(); i++) { | ||
3542 | 171 | if (m_printer->supportedDuplexModes().at(i) == duplexMode) { | ||
3543 | 172 | setDuplexMode(i); | ||
3544 | 173 | } | ||
3545 | 174 | } | ||
3546 | 175 | |||
3547 | 176 | setImpressionsCompleted(attributes.value("impressionsCompleted").toInt()); | ||
3548 | 177 | setLandscape(attributes.value("landscape").toBool()); | ||
3549 | 178 | setMessages(attributes.value("messages").toStringList()); | ||
3550 | 179 | |||
3551 | 180 | QStringList pageRanges = attributes.value("page-ranges").toStringList(); | ||
3552 | 181 | if (pageRanges.isEmpty()) { | ||
3553 | 182 | setPrintRangeMode(PrinterEnum::PrintRange::AllPages); | ||
3554 | 183 | setPrintRange(QStringLiteral("")); | ||
3555 | 184 | } else { | ||
3556 | 185 | setPrintRangeMode(PrinterEnum::PrintRange::PageRange); | ||
3557 | 186 | // Use groupSeparator as createSeparatedList adds "and" into the string | ||
3558 | 187 | setPrintRange(pageRanges.join(QLocale::system().groupSeparator())); | ||
3559 | 188 | } | ||
3560 | 189 | |||
3561 | 190 | setProcessingTime(attributes.value("ProcessingTime").toDateTime()); | ||
3562 | 191 | |||
3563 | 192 | // No quality will result in PrinterJob using defaultPrintQuality | ||
3564 | 193 | QString quality = attributes.value("quality").toString(); | ||
3565 | 194 | for (int i=0; i < m_printer->supportedPrintQualities().length(); i++) { | ||
3566 | 195 | if (m_printer->supportedPrintQualities().at(i).name == quality) { | ||
3567 | 196 | setQuality(i); | ||
3568 | 197 | } | ||
3569 | 198 | } | ||
3570 | 199 | |||
3571 | 200 | setReverse(attributes.value("OutputOrder").toString() == "Reverse"); | ||
3572 | 201 | |||
3573 | 202 | // If there was a state then set it | ||
3574 | 203 | if (attributes.contains("State")) { | ||
3575 | 204 | setState(static_cast<PrinterEnum::JobState>(attributes.value("State").toInt())); | ||
3576 | 205 | } | ||
3577 | 206 | |||
3578 | 207 | setSize(attributes.value("Size").toInt()); | ||
3579 | 208 | setUser(attributes.value("User").toString()); | ||
3580 | 209 | } | ||
3581 | 210 | |||
3582 | 146 | void PrinterJob::loadDefaults() | 211 | void PrinterJob::loadDefaults() |
3583 | 147 | { | 212 | { |
3584 | 148 | if (!m_printer) { | 213 | if (!m_printer) { |
3585 | @@ -150,62 +215,17 @@ | |||
3586 | 150 | return; | 215 | return; |
3587 | 151 | } | 216 | } |
3588 | 152 | 217 | ||
3589 | 153 | qWarning() << Q_FUNC_INFO << jobId(); | ||
3590 | 154 | |||
3591 | 155 | if (jobId() > 0) { | 218 | if (jobId() > 0) { |
3640 | 156 | // Load the extra attributes for the job | 219 | loadAttributes( |
3641 | 157 | // NOTE: we don't need to type check them as they have been filtered for us | 220 | m_backend->printerGetJobAttributes( |
3642 | 158 | 221 | printerName(), jobId() | |
3643 | 159 | QMap<QString, QVariant> attributes = m_backend->printerGetJobAttributes( | 222 | ) |
3644 | 160 | m_printer->name(), jobId()); | 223 | ); |
3645 | 161 | 224 | } else { | |
3646 | 162 | setCollate(attributes.value("Collate").toBool()); | 225 | setColorModel(m_printer->supportedColorModels().indexOf(m_printer->defaultColorModel())); |
3647 | 163 | setCopies(attributes.value("copies").toInt()); | 226 | setDuplexMode(m_printer->supportedDuplexModes().indexOf(m_printer->defaultDuplexMode())); |
3648 | 164 | 227 | setQuality(m_printer->supportedPrintQualities().indexOf(m_printer->defaultPrintQuality())); | |
3601 | 165 | // No colorModel will result in PrinterJob using defaultColorModel | ||
3602 | 166 | QString colorModel = attributes.value("ColorModel").toString(); | ||
3603 | 167 | for (int i=0; i < m_printer->supportedColorModels().length(); i++) { | ||
3604 | 168 | if (m_printer->supportedColorModels().at(i).originalOption == colorModel) { | ||
3605 | 169 | setColorModel(i); | ||
3606 | 170 | } | ||
3607 | 171 | } | ||
3608 | 172 | |||
3609 | 173 | // No duplexMode will result in PrinterJob using defaultDuplexMode | ||
3610 | 174 | QString duplex = attributes.value("Duplex").toString(); | ||
3611 | 175 | PrinterEnum::DuplexMode duplexMode = Utils::ppdChoiceToDuplexMode(duplex); | ||
3612 | 176 | for (int i=0; i < m_printer->supportedDuplexModes().length(); i++) { | ||
3613 | 177 | if (m_printer->supportedDuplexModes().at(i) == duplexMode) { | ||
3614 | 178 | setDuplexMode(i); | ||
3615 | 179 | } | ||
3616 | 180 | } | ||
3617 | 181 | |||
3618 | 182 | setLandscape(attributes.value("landscape").toBool()); | ||
3619 | 183 | setMessages(attributes.value("messages").toStringList()); | ||
3620 | 184 | |||
3621 | 185 | QStringList pageRanges = attributes.value("page-ranges").toStringList(); | ||
3622 | 186 | if (pageRanges.isEmpty()) { | ||
3623 | 187 | setPrintRangeMode(PrinterEnum::PrintRange::AllPages); | ||
3624 | 188 | setPrintRange(QStringLiteral("")); | ||
3625 | 189 | } else { | ||
3626 | 190 | setPrintRangeMode(PrinterEnum::PrintRange::PageRange); | ||
3627 | 191 | // Use groupSeparator as createSeparatedList adds "and" into the string | ||
3628 | 192 | setPrintRange(pageRanges.join(QLocale::system().groupSeparator())); | ||
3629 | 193 | } | ||
3630 | 194 | |||
3631 | 195 | // No quality will result in PrinterJob using defaultPrintQuality | ||
3632 | 196 | QString quality = attributes.value("quality").toString(); | ||
3633 | 197 | for (int i=0; i < m_printer->supportedPrintQualities().length(); i++) { | ||
3634 | 198 | if (m_printer->supportedPrintQualities().at(i).name == quality) { | ||
3635 | 199 | setQuality(i); | ||
3636 | 200 | } | ||
3637 | 201 | } | ||
3638 | 202 | |||
3639 | 203 | setReverse(attributes.value("OutputOrder").toString() == "Reverse"); | ||
3649 | 204 | } | 228 | } |
3650 | 205 | |||
3651 | 206 | setColorModel(m_printer->supportedColorModels().indexOf(m_printer->defaultColorModel())); | ||
3652 | 207 | setDuplexMode(m_printer->supportedDuplexModes().indexOf(m_printer->defaultDuplexMode())); | ||
3653 | 208 | setQuality(m_printer->supportedPrintQualities().indexOf(m_printer->defaultPrintQuality())); | ||
3654 | 209 | } | 229 | } |
3655 | 210 | 230 | ||
3656 | 211 | QStringList PrinterJob::messages() const | 231 | QStringList PrinterJob::messages() const |
3657 | @@ -373,16 +393,16 @@ | |||
3658 | 373 | void PrinterJob::setPrinter(QSharedPointer<Printer> printer) | 393 | void PrinterJob::setPrinter(QSharedPointer<Printer> printer) |
3659 | 374 | { | 394 | { |
3660 | 375 | if (m_printer != printer) { | 395 | if (m_printer != printer) { |
3662 | 376 | m_printer = printer; | 396 | Q_EMIT printerAboutToChange(m_printer, printer); |
3663 | 397 | m_printer = printer; | ||
3664 | 377 | 398 | ||
3666 | 378 | if (printer->name() != m_printerName) { | 399 | if (printer->name() != m_printerName) { |
3667 | 379 | m_printerName = printer->name(); | 400 | m_printerName = printer->name(); |
3668 | 380 | Q_EMIT printerNameChanged(); | 401 | Q_EMIT printerNameChanged(); |
3670 | 381 | } | 402 | } |
3671 | 382 | 403 | ||
3673 | 383 | Q_EMIT printerChanged(); | 404 | Q_EMIT printerChanged(); |
3674 | 384 | } | 405 | } |
3675 | 385 | loadDefaults(); | ||
3676 | 386 | } | 406 | } |
3677 | 387 | 407 | ||
3678 | 388 | void PrinterJob::setPrintRange(const QString &printRange) | 408 | void PrinterJob::setPrintRange(const QString &printRange) |
3679 | @@ -478,33 +498,61 @@ | |||
3680 | 478 | // Return true if they are the same | 498 | // Return true if they are the same |
3681 | 479 | return collate() == other->collate() | 499 | return collate() == other->collate() |
3682 | 480 | && colorModel() == other->colorModel() | 500 | && colorModel() == other->colorModel() |
3683 | 501 | && completedTime() == other->completedTime() | ||
3684 | 481 | && copies() == other->copies() | 502 | && copies() == other->copies() |
3685 | 503 | && creationTime() == other->creationTime() | ||
3686 | 482 | && duplexMode() == other->duplexMode() | 504 | && duplexMode() == other->duplexMode() |
3687 | 505 | && impressionsCompleted() == other->impressionsCompleted() | ||
3688 | 483 | && landscape() == other->landscape() | 506 | && landscape() == other->landscape() |
3689 | 507 | && messages() == other->messages() | ||
3690 | 484 | && printRange() == other->printRange() | 508 | && printRange() == other->printRange() |
3691 | 485 | && printRangeMode() == other->printRangeMode() | 509 | && printRangeMode() == other->printRangeMode() |
3692 | 510 | && processingTime() == other->processingTime() | ||
3693 | 486 | && quality() == other->quality() | 511 | && quality() == other->quality() |
3694 | 487 | && reverse() == other->reverse() | 512 | && reverse() == other->reverse() |
3695 | 513 | && size() == other->size() | ||
3696 | 488 | && state() == other->state() | 514 | && state() == other->state() |
3698 | 489 | && title() == other->title(); | 515 | && title() == other->title() |
3699 | 516 | && user() == other->user(); | ||
3700 | 490 | } | 517 | } |
3701 | 491 | 518 | ||
3702 | 492 | void PrinterJob::updateFrom(QSharedPointer<PrinterJob> other) | 519 | void PrinterJob::updateFrom(QSharedPointer<PrinterJob> other) |
3703 | 493 | { | 520 | { |
3704 | 494 | setCollate(other->collate()); | 521 | setCollate(other->collate()); |
3705 | 495 | setColorModel(other->colorModel()); | 522 | setColorModel(other->colorModel()); |
3706 | 523 | setCompletedTime(other->completedTime()); | ||
3707 | 496 | setCopies(other->copies()); | 524 | setCopies(other->copies()); |
3708 | 525 | setCreationTime(other->creationTime()); | ||
3709 | 497 | setDuplexMode(other->duplexMode()); | 526 | setDuplexMode(other->duplexMode()); |
3710 | 527 | setImpressionsCompleted(other->impressionsCompleted()); | ||
3711 | 498 | setLandscape(other->landscape()); | 528 | setLandscape(other->landscape()); |
3712 | 529 | setMessages(other->messages()); | ||
3713 | 499 | setPrintRange(other->printRange()); | 530 | setPrintRange(other->printRange()); |
3714 | 500 | setPrintRangeMode(other->printRangeMode()); | 531 | setPrintRangeMode(other->printRangeMode()); |
3715 | 532 | setProcessingTime(other->processingTime()); | ||
3716 | 501 | setQuality(other->quality()); | 533 | setQuality(other->quality()); |
3717 | 502 | setReverse(other->reverse()); | 534 | setReverse(other->reverse()); |
3718 | 535 | setSize(other->size()); | ||
3719 | 503 | setState(other->state()); | 536 | setState(other->state()); |
3720 | 504 | setTitle(other->title()); | 537 | setTitle(other->title()); |
3721 | 538 | setUser(other->user()); | ||
3722 | 505 | } | 539 | } |
3723 | 506 | 540 | ||
3724 | 507 | QString PrinterJob::user() const | 541 | QString PrinterJob::user() const |
3725 | 508 | { | 542 | { |
3726 | 509 | return m_user; | 543 | return m_user; |
3727 | 510 | } | 544 | } |
3728 | 545 | |||
3729 | 546 | void PrinterJob::onPrinterAboutToChange(QSharedPointer<Printer> old, | ||
3730 | 547 | QSharedPointer<Printer> replacement) | ||
3731 | 548 | { | ||
3732 | 549 | /* If we have an old printer, and the current copies value matches that | ||
3733 | 550 | of the old printer's, we'll use the new printer's copy value. | ||
3734 | 551 | |||
3735 | 552 | The second case is if there was no old printer. */ | ||
3736 | 553 | bool haveOld = old && replacement && (copies() == old->copies()); | ||
3737 | 554 | bool noOld = !old && replacement; | ||
3738 | 555 | if (haveOld || noOld) { | ||
3739 | 556 | setCopies(replacement->copies()); | ||
3740 | 557 | } | ||
3741 | 558 | } | ||
3742 | 511 | 559 | ||
3743 | === modified file 'modules/Ubuntu/Components/Extras/Printers/printer/printerjob.h' | |||
3744 | --- modules/Ubuntu/Components/Extras/Printers/printer/printerjob.h 2017-02-23 14:04:26 +0000 | |||
3745 | +++ modules/Ubuntu/Components/Extras/Printers/printer/printerjob.h 2017-03-23 12:51:36 +0000 | |||
3746 | @@ -58,8 +58,6 @@ | |||
3747 | 58 | Q_PROPERTY(PrinterEnum::JobState state READ state NOTIFY stateChanged) | 58 | Q_PROPERTY(PrinterEnum::JobState state READ state NOTIFY stateChanged) |
3748 | 59 | Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged) | 59 | Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged) |
3749 | 60 | Q_PROPERTY(QString user READ user NOTIFY userChanged) | 60 | Q_PROPERTY(QString user READ user NOTIFY userChanged) |
3750 | 61 | |||
3751 | 62 | friend class PrinterCupsBackend; | ||
3752 | 63 | public: | 61 | public: |
3753 | 64 | explicit PrinterJob(QString dest, | 62 | explicit PrinterJob(QString dest, |
3754 | 65 | PrinterBackend *backend, | 63 | PrinterBackend *backend, |
3755 | @@ -97,31 +95,34 @@ | |||
3756 | 97 | PrinterEnum::DuplexMode getDuplexMode() const; | 95 | PrinterEnum::DuplexMode getDuplexMode() const; |
3757 | 98 | ColorModel getColorModel() const; | 96 | ColorModel getColorModel() const; |
3758 | 99 | PrintQuality getPrintQuality() const; | 97 | PrintQuality getPrintQuality() const; |
3759 | 98 | void loadAttributes(const QMap<QString, QVariant>& attributes); | ||
3760 | 99 | void loadDefaults(); | ||
3761 | 100 | Q_INVOKABLE void printFile(const QUrl &url); | 100 | Q_INVOKABLE void printFile(const QUrl &url); |
3762 | 101 | void setCollate(const bool collate); | 101 | void setCollate(const bool collate); |
3763 | 102 | void setColorModel(const int colorModel); | 102 | void setColorModel(const int colorModel); |
3764 | 103 | void setCompletedTime(const QDateTime &completedTime); | ||
3765 | 103 | void setCopies(const int copies); | 104 | void setCopies(const int copies); |
3766 | 105 | void setCreationTime(const QDateTime &creationTime); | ||
3767 | 104 | void setDuplexMode(const int duplexMode); | 106 | void setDuplexMode(const int duplexMode); |
3768 | 105 | void setImpressionsCompleted(const int &impressionsCompleted); | 107 | void setImpressionsCompleted(const int &impressionsCompleted); |
3769 | 108 | void setIsTwoSided(const bool isTwoSided); | ||
3770 | 106 | void setLandscape(const bool landscape); | 109 | void setLandscape(const bool landscape); |
3771 | 110 | void setMessages(const QStringList &messages); | ||
3772 | 107 | void setPrinter(QSharedPointer<Printer> printer); | 111 | void setPrinter(QSharedPointer<Printer> printer); |
3773 | 108 | void setPrintRange(const QString &printRange); | 112 | void setPrintRange(const QString &printRange); |
3774 | 109 | void setPrintRangeMode(const PrinterEnum::PrintRange printRangeMode); | 113 | void setPrintRangeMode(const PrinterEnum::PrintRange printRangeMode); |
3775 | 114 | void setProcessingTime(const QDateTime &processingTime); | ||
3776 | 110 | void setQuality(const int quality); | 115 | void setQuality(const int quality); |
3777 | 111 | void setReverse(const bool reverse); | 116 | void setReverse(const bool reverse); |
3778 | 117 | void setSize(const int size); | ||
3779 | 118 | void setState(const PrinterEnum::JobState &state); | ||
3780 | 112 | void setTitle(const QString &title); | 119 | void setTitle(const QString &title); |
3781 | 120 | void setUser(const QString &user); | ||
3782 | 113 | 121 | ||
3783 | 114 | void updateFrom(QSharedPointer<PrinterJob> other); | 122 | void updateFrom(QSharedPointer<PrinterJob> other); |
3784 | 115 | private Q_SLOTS: | 123 | private Q_SLOTS: |
3794 | 116 | void loadDefaults(); | 124 | void onPrinterAboutToChange(QSharedPointer<Printer> old, |
3795 | 117 | void setCompletedTime(const QDateTime &completedTime); | 125 | QSharedPointer<Printer> replacement); |
3787 | 118 | void setCreationTime(const QDateTime &creationTime); | ||
3788 | 119 | void setIsTwoSided(const bool isTwoSided); | ||
3789 | 120 | void setMessages(const QStringList &messages); | ||
3790 | 121 | void setProcessingTime(const QDateTime &processingTime); | ||
3791 | 122 | void setSize(const int size); | ||
3792 | 123 | void setState(const PrinterEnum::JobState &state); | ||
3793 | 124 | void setUser(const QString &user); | ||
3796 | 125 | Q_SIGNALS: | 126 | Q_SIGNALS: |
3797 | 126 | void collateChanged(); | 127 | void collateChanged(); |
3798 | 127 | void colorModelChanged(); | 128 | void colorModelChanged(); |
3799 | @@ -134,6 +135,8 @@ | |||
3800 | 134 | void isTwoSidedChanged(); | 135 | void isTwoSidedChanged(); |
3801 | 135 | void landscapeChanged(); | 136 | void landscapeChanged(); |
3802 | 136 | void messagesChanged(); | 137 | void messagesChanged(); |
3803 | 138 | void printerAboutToChange(QSharedPointer<Printer> old, | ||
3804 | 139 | QSharedPointer<Printer> replacement); | ||
3805 | 137 | void printerChanged(); | 140 | void printerChanged(); |
3806 | 138 | void printerNameChanged(); | 141 | void printerNameChanged(); |
3807 | 139 | void printRangeChanged(); | 142 | void printRangeChanged(); |
3808 | 140 | 143 | ||
3809 | === renamed file 'modules/Ubuntu/Components/Extras/Printers/printer/printersignalhandler.cpp' => 'modules/Ubuntu/Components/Extras/Printers/printer/signalratelimiter.cpp' | |||
3810 | --- modules/Ubuntu/Components/Extras/Printers/printer/printersignalhandler.cpp 2017-02-21 10:46:29 +0000 | |||
3811 | +++ modules/Ubuntu/Components/Extras/Printers/printer/signalratelimiter.cpp 2017-03-23 12:51:36 +0000 | |||
3812 | @@ -14,9 +14,9 @@ | |||
3813 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3814 | 15 | */ | 15 | */ |
3815 | 16 | 16 | ||
3817 | 17 | #include "printersignalhandler.h" | 17 | #include "signalratelimiter.h" |
3818 | 18 | 18 | ||
3820 | 19 | PrinterSignalHandler::PrinterSignalHandler(int triggerEventDelay, | 19 | SignalRateLimiter::SignalRateLimiter(int triggerEventDelay, |
3821 | 20 | QObject *parent) | 20 | QObject *parent) |
3822 | 21 | : QObject(parent) | 21 | : QObject(parent) |
3823 | 22 | { | 22 | { |
3824 | @@ -24,11 +24,11 @@ | |||
3825 | 24 | connect(&m_timer, SIGNAL(timeout()), this, SLOT(process())); | 24 | connect(&m_timer, SIGNAL(timeout()), this, SLOT(process())); |
3826 | 25 | } | 25 | } |
3827 | 26 | 26 | ||
3829 | 27 | PrinterSignalHandler::~PrinterSignalHandler() | 27 | SignalRateLimiter::~SignalRateLimiter() |
3830 | 28 | { | 28 | { |
3831 | 29 | } | 29 | } |
3832 | 30 | 30 | ||
3834 | 31 | void PrinterSignalHandler::process() | 31 | void SignalRateLimiter::process() |
3835 | 32 | { | 32 | { |
3836 | 33 | Q_FOREACH(auto printer, m_unprocessed) { | 33 | Q_FOREACH(auto printer, m_unprocessed) { |
3837 | 34 | Q_EMIT printerModified(printer); | 34 | Q_EMIT printerModified(printer); |
3838 | @@ -37,7 +37,7 @@ | |||
3839 | 37 | m_timer.stop(); | 37 | m_timer.stop(); |
3840 | 38 | } | 38 | } |
3841 | 39 | 39 | ||
3843 | 40 | void PrinterSignalHandler::onPrinterModified( | 40 | void SignalRateLimiter::onPrinterModified( |
3844 | 41 | const QString &text, const QString &printerUri, | 41 | const QString &text, const QString &printerUri, |
3845 | 42 | const QString &printerName, uint printerState, | 42 | const QString &printerName, uint printerState, |
3846 | 43 | const QString &printerStateReason, bool acceptingJobs) | 43 | const QString &printerStateReason, bool acceptingJobs) |
3847 | @@ -49,11 +49,22 @@ | |||
3848 | 49 | Q_UNUSED(printerStateReason); | 49 | Q_UNUSED(printerStateReason); |
3849 | 50 | Q_UNUSED(acceptingJobs); | 50 | Q_UNUSED(acceptingJobs); |
3850 | 51 | 51 | ||
3851 | 52 | // Track when the first item was added to the unprocessed queue | ||
3852 | 53 | if (m_unprocessed.count() == 0) { | ||
3853 | 54 | m_unprocessed_time = QDateTime::currentDateTime(); | ||
3854 | 55 | } | ||
3855 | 56 | |||
3856 | 52 | m_unprocessed << printerName; | 57 | m_unprocessed << printerName; |
3857 | 53 | m_timer.start(); | 58 | m_timer.start(); |
3858 | 59 | |||
3859 | 60 | // Ensure that process is fired if we have reached four times | ||
3860 | 61 | // longer than the timer, this is due to many signals coming in rapidly | ||
3861 | 62 | if (m_unprocessed_time.msecsTo(QDateTime::currentDateTime()) > m_timer.interval() * 4) { | ||
3862 | 63 | process(); | ||
3863 | 64 | } | ||
3864 | 54 | } | 65 | } |
3865 | 55 | 66 | ||
3867 | 56 | void PrinterSignalHandler::onPrinterStateChanged( | 67 | void SignalRateLimiter::onPrinterStateChanged( |
3868 | 57 | const QString &text, const QString &printerUri, | 68 | const QString &text, const QString &printerUri, |
3869 | 58 | const QString &printerName, uint printerState, | 69 | const QString &printerName, uint printerState, |
3870 | 59 | const QString &printerStateReason, bool acceptingJobs) | 70 | const QString &printerStateReason, bool acceptingJobs) |
3871 | @@ -64,6 +75,17 @@ | |||
3872 | 64 | Q_UNUSED(printerStateReason); | 75 | Q_UNUSED(printerStateReason); |
3873 | 65 | Q_UNUSED(acceptingJobs); | 76 | Q_UNUSED(acceptingJobs); |
3874 | 66 | 77 | ||
3875 | 78 | // Track when the first item was added to the unprocessed queue | ||
3876 | 79 | if (m_unprocessed.count() == 0) { | ||
3877 | 80 | m_unprocessed_time = QDateTime::currentDateTime(); | ||
3878 | 81 | } | ||
3879 | 82 | |||
3880 | 67 | m_unprocessed << printerName; | 83 | m_unprocessed << printerName; |
3881 | 68 | m_timer.start(); | 84 | m_timer.start(); |
3882 | 85 | |||
3883 | 86 | // Ensure that process is fired if we have reached four times | ||
3884 | 87 | // longer than the timer, this is due to many signals coming in rapidly | ||
3885 | 88 | if (m_unprocessed_time.msecsTo(QDateTime::currentDateTime()) > m_timer.interval() * 4) { | ||
3886 | 89 | process(); | ||
3887 | 90 | } | ||
3888 | 69 | } | 91 | } |
3889 | 70 | 92 | ||
3890 | === renamed file 'modules/Ubuntu/Components/Extras/Printers/printer/printersignalhandler.h' => 'modules/Ubuntu/Components/Extras/Printers/printer/signalratelimiter.h' | |||
3891 | --- modules/Ubuntu/Components/Extras/Printers/printer/printersignalhandler.h 2017-02-21 10:46:29 +0000 | |||
3892 | +++ modules/Ubuntu/Components/Extras/Printers/printer/signalratelimiter.h 2017-03-23 12:51:36 +0000 | |||
3893 | @@ -14,24 +14,26 @@ | |||
3894 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3895 | 15 | */ | 15 | */ |
3896 | 16 | 16 | ||
3899 | 17 | #ifndef USC_PRINTER_SIGNAL_HANDLER_H | 17 | #ifndef USC_SIGNAL_RATE_LIMITER_H |
3900 | 18 | #define USC_PRINTER_SIGNAL_HANDLER_H | 18 | #define USC_SIGNAL_RATE_LIMITER_H |
3901 | 19 | 19 | ||
3902 | 20 | #include "printers_global.h" | 20 | #include "printers_global.h" |
3903 | 21 | 21 | ||
3904 | 22 | #include <QDateTime> | ||
3905 | 22 | #include <QObject> | 23 | #include <QObject> |
3906 | 23 | #include <QSet> | 24 | #include <QSet> |
3907 | 24 | #include <QTimer> | 25 | #include <QTimer> |
3908 | 25 | 26 | ||
3910 | 26 | class PRINTERS_DECL_EXPORT PrinterSignalHandler : public QObject | 27 | class PRINTERS_DECL_EXPORT SignalRateLimiter : public QObject |
3911 | 27 | { | 28 | { |
3912 | 28 | Q_OBJECT | 29 | Q_OBJECT |
3913 | 29 | QTimer m_timer; | 30 | QTimer m_timer; |
3914 | 30 | QSet<QString> m_unprocessed; | 31 | QSet<QString> m_unprocessed; |
3915 | 32 | QDateTime m_unprocessed_time; | ||
3916 | 31 | public: | 33 | public: |
3918 | 32 | explicit PrinterSignalHandler(int triggerEventDelay = 500, | 34 | explicit SignalRateLimiter(int triggerEventDelay = 500, |
3919 | 33 | QObject *parent = Q_NULLPTR); | 35 | QObject *parent = Q_NULLPTR); |
3921 | 34 | ~PrinterSignalHandler(); | 36 | ~SignalRateLimiter(); |
3922 | 35 | 37 | ||
3923 | 36 | public Q_SLOTS: | 38 | public Q_SLOTS: |
3924 | 37 | void onPrinterModified( | 39 | void onPrinterModified( |
3925 | @@ -52,4 +54,4 @@ | |||
3926 | 52 | void printerModified(const QString &printerName); | 54 | void printerModified(const QString &printerName); |
3927 | 53 | }; | 55 | }; |
3928 | 54 | 56 | ||
3930 | 55 | #endif // USC_PRINTER_SIGNAL_HANDLER_H | 57 | #endif // USC_SIGNAL_RATE_LIMITERR_H |
3931 | 56 | 58 | ||
3932 | === modified file 'modules/Ubuntu/Components/Extras/Printers/printers/printers.cpp' | |||
3933 | --- modules/Ubuntu/Components/Extras/Printers/printers/printers.cpp 2017-02-24 13:14:13 +0000 | |||
3934 | +++ modules/Ubuntu/Components/Extras/Printers/printers/printers.cpp 2017-03-23 12:51:36 +0000 | |||
3935 | @@ -15,6 +15,7 @@ | |||
3936 | 15 | */ | 15 | */ |
3937 | 16 | 16 | ||
3938 | 17 | #include "backend/backend_cups.h" | 17 | #include "backend/backend_cups.h" |
3939 | 18 | #include "i18n.h" | ||
3940 | 18 | #include "printers/printers.h" | 19 | #include "printers/printers.h" |
3941 | 19 | #include "cupsdnotifier.h" // Note: this file was generated. | 20 | #include "cupsdnotifier.h" // Note: this file was generated. |
3942 | 20 | 21 | ||
3943 | @@ -33,6 +34,7 @@ | |||
3944 | 33 | Printers::Printers(PrinterBackend *backend, QObject *parent) | 34 | Printers::Printers(PrinterBackend *backend, QObject *parent) |
3945 | 34 | : QObject(parent) | 35 | : QObject(parent) |
3946 | 35 | , m_backend(backend) | 36 | , m_backend(backend) |
3947 | 37 | , m_devices(backend) | ||
3948 | 36 | , m_drivers(backend) | 38 | , m_drivers(backend) |
3949 | 37 | , m_model(backend) | 39 | , m_model(backend) |
3950 | 38 | , m_jobs(backend) | 40 | , m_jobs(backend) |
3951 | @@ -56,8 +58,20 @@ | |||
3952 | 56 | const QModelIndex &parent, int first, int) { | 58 | const QModelIndex &parent, int first, int) { |
3953 | 57 | int jobId = m_jobs.data(m_jobs.index(first, 0, parent), | 59 | int jobId = m_jobs.data(m_jobs.index(first, 0, parent), |
3954 | 58 | JobModel::Roles::IdRole).toInt(); | 60 | JobModel::Roles::IdRole).toInt(); |
3957 | 59 | jobAdded(m_jobs.getJobById(jobId)); | 61 | QString printerName = m_jobs.data( |
3958 | 60 | }); | 62 | m_jobs.index(first, 0, parent), |
3959 | 63 | JobModel::Roles::PrinterNameRole | ||
3960 | 64 | ).toString(); | ||
3961 | 65 | |||
3962 | 66 | jobAdded(m_jobs.getJob(printerName, jobId)); | ||
3963 | 67 | }); | ||
3964 | 68 | |||
3965 | 69 | // If the jobModel forces a refresh, load extended attributes for the job | ||
3966 | 70 | connect(&m_jobs, &JobModel::forceJobRefresh, [this]( | ||
3967 | 71 | const QString &printerName, const int jobId) { | ||
3968 | 72 | jobAdded(m_jobs.getJob(printerName, jobId)); | ||
3969 | 73 | }); | ||
3970 | 74 | |||
3971 | 61 | connect(&m_model, &QAbstractItemModel::rowsInserted, [this]( | 75 | connect(&m_model, &QAbstractItemModel::rowsInserted, [this]( |
3972 | 62 | const QModelIndex &parent, int first, int) { | 76 | const QModelIndex &parent, int first, int) { |
3973 | 63 | auto printer = m_model.data( | 77 | auto printer = m_model.data( |
3974 | @@ -76,6 +90,17 @@ | |||
3975 | 76 | ); | 90 | ); |
3976 | 77 | } | 91 | } |
3977 | 78 | 92 | ||
3978 | 93 | // Ensure existing jobs have been added, incase some were added before | ||
3979 | 94 | // the connect to rowsInserted was done | ||
3980 | 95 | for (int i = 0; i < m_jobs.rowCount(); i++) { | ||
3981 | 96 | jobAdded( | ||
3982 | 97 | m_jobs.getJob( | ||
3983 | 98 | m_jobs.data(m_jobs.index(i), JobModel::Roles::PrinterNameRole).toString(), | ||
3984 | 99 | m_jobs.data(m_jobs.index(i), JobModel::IdRole).toInt() | ||
3985 | 100 | ) | ||
3986 | 101 | ); | ||
3987 | 102 | } | ||
3988 | 103 | |||
3989 | 79 | if (m_backend->type() == PrinterEnum::PrinterType::CupsType) { | 104 | if (m_backend->type() == PrinterEnum::PrinterType::CupsType) { |
3990 | 80 | ((PrinterCupsBackend*) m_backend)->createSubscription(); | 105 | ((PrinterCupsBackend*) m_backend)->createSubscription(); |
3991 | 81 | } | 106 | } |
3992 | @@ -103,6 +128,41 @@ | |||
3993 | 103 | return ret; | 128 | return ret; |
3994 | 104 | } | 129 | } |
3995 | 105 | 130 | ||
3996 | 131 | QAbstractItemModel* Printers::remotePrinters() | ||
3997 | 132 | { | ||
3998 | 133 | /* Lazily initialize this model. Local printers are discerned from remotes | ||
3999 | 134 | by checking if they are remote. */ | ||
4000 | 135 | if (!m_remotePrinters.sourceModel()) { | ||
4001 | 136 | m_remotePrinters.setSourceModel(&m_model); | ||
4002 | 137 | m_remotePrinters.filterOnRemote(true); | ||
4003 | 138 | m_remotePrinters.filterOnPdf(false); | ||
4004 | 139 | m_remotePrinters.invalidate(); | ||
4005 | 140 | m_remotePrinters.sort(0, Qt::DescendingOrder); | ||
4006 | 141 | } | ||
4007 | 142 | |||
4008 | 143 | auto ret = &m_remotePrinters; | ||
4009 | 144 | QQmlEngine::setObjectOwnership(ret, QQmlEngine::CppOwnership); | ||
4010 | 145 | return ret; | ||
4011 | 146 | } | ||
4012 | 147 | |||
4013 | 148 | QAbstractItemModel* Printers::localPrinters() | ||
4014 | 149 | { | ||
4015 | 150 | /* Lazily initialize this model. Local printers are discerned from remotes | ||
4016 | 151 | by checking if they are remote. */ | ||
4017 | 152 | if (!m_localPrinters.sourceModel()) { | ||
4018 | 153 | m_localPrinters.setSourceModel(&m_model); | ||
4019 | 154 | m_localPrinters.filterOnRemote(false); | ||
4020 | 155 | m_localPrinters.filterOnPdf(false); | ||
4021 | 156 | m_localPrinters.setSortRole(PrinterModel::Roles::DefaultPrinterRole); | ||
4022 | 157 | m_localPrinters.invalidate(); | ||
4023 | 158 | m_localPrinters.sort(0, Qt::DescendingOrder); | ||
4024 | 159 | } | ||
4025 | 160 | |||
4026 | 161 | auto ret = &m_localPrinters; | ||
4027 | 162 | QQmlEngine::setObjectOwnership(ret, QQmlEngine::CppOwnership); | ||
4028 | 163 | return ret; | ||
4029 | 164 | } | ||
4030 | 165 | |||
4031 | 106 | QAbstractItemModel* Printers::printJobs() | 166 | QAbstractItemModel* Printers::printJobs() |
4032 | 107 | { | 167 | { |
4033 | 108 | auto ret = &m_jobs; | 168 | auto ret = &m_jobs; |
4034 | @@ -117,6 +177,14 @@ | |||
4035 | 117 | return ret; | 177 | return ret; |
4036 | 118 | } | 178 | } |
4037 | 119 | 179 | ||
4038 | 180 | QAbstractItemModel* Printers::devices() | ||
4039 | 181 | { | ||
4040 | 182 | m_devices.load(); | ||
4041 | 183 | auto ret = &m_devices; | ||
4042 | 184 | QQmlEngine::setObjectOwnership(ret, QQmlEngine::CppOwnership); | ||
4043 | 185 | return ret; | ||
4044 | 186 | } | ||
4045 | 187 | |||
4046 | 120 | QString Printers::driverFilter() const | 188 | QString Printers::driverFilter() const |
4047 | 121 | { | 189 | { |
4048 | 122 | return m_drivers.filter(); | 190 | return m_drivers.filter(); |
4049 | @@ -143,11 +211,33 @@ | |||
4050 | 143 | return new PrinterJob(printerName, m_backend); | 211 | return new PrinterJob(printerName, m_backend); |
4051 | 144 | } | 212 | } |
4052 | 145 | 213 | ||
4053 | 214 | QAbstractItemModel* Printers::createJobFilter() | ||
4054 | 215 | { | ||
4055 | 216 | // Note: If called by QML, it gains ownership of the job filter. | ||
4056 | 217 | JobFilter *filter = new JobFilter(); | ||
4057 | 218 | filter->setSourceModel(&m_jobs); | ||
4058 | 219 | |||
4059 | 220 | filter->setSortRole(JobModel::Roles::CreationTimeRole); | ||
4060 | 221 | filter->sort(0, Qt::AscendingOrder); | ||
4061 | 222 | |||
4062 | 223 | return filter; | ||
4063 | 224 | } | ||
4064 | 225 | |||
4065 | 146 | void Printers::cancelJob(const QString &printerName, const int jobId) | 226 | void Printers::cancelJob(const QString &printerName, const int jobId) |
4066 | 147 | { | 227 | { |
4067 | 148 | m_backend->cancelJob(printerName, jobId); | 228 | m_backend->cancelJob(printerName, jobId); |
4068 | 149 | } | 229 | } |
4069 | 150 | 230 | ||
4070 | 231 | void Printers::holdJob(const QString &printerName, const int jobId) | ||
4071 | 232 | { | ||
4072 | 233 | m_backend->holdJob(printerName, jobId); | ||
4073 | 234 | } | ||
4074 | 235 | |||
4075 | 236 | void Printers::releaseJob(const QString &printerName, const int jobId) | ||
4076 | 237 | { | ||
4077 | 238 | m_backend->releaseJob(printerName, jobId); | ||
4078 | 239 | } | ||
4079 | 240 | |||
4080 | 151 | void Printers::setDefaultPrinterName(const QString &name) | 241 | void Printers::setDefaultPrinterName(const QString &name) |
4081 | 152 | { | 242 | { |
4082 | 153 | QString reply = m_backend->printerSetDefault(name); | 243 | QString reply = m_backend->printerSetDefault(name); |
4083 | @@ -164,6 +254,11 @@ | |||
4084 | 164 | } | 254 | } |
4085 | 165 | } | 255 | } |
4086 | 166 | 256 | ||
4087 | 257 | void Printers::searchForDevices() | ||
4088 | 258 | { | ||
4089 | 259 | m_devices.load(); | ||
4090 | 260 | } | ||
4091 | 261 | |||
4092 | 167 | bool Printers::addPrinter(const QString &name, const QString &ppd, | 262 | bool Printers::addPrinter(const QString &name, const QString &ppd, |
4093 | 168 | const QString &device, const QString &description, | 263 | const QString &device, const QString &description, |
4094 | 169 | const QString &location) | 264 | const QString &location) |
4095 | @@ -174,6 +269,9 @@ | |||
4096 | 174 | m_lastMessage = reply; | 269 | m_lastMessage = reply; |
4097 | 175 | return false; | 270 | return false; |
4098 | 176 | } | 271 | } |
4099 | 272 | |||
4100 | 273 | provisionPrinter(name); | ||
4101 | 274 | |||
4102 | 177 | return true; | 275 | return true; |
4103 | 178 | } | 276 | } |
4104 | 179 | 277 | ||
4105 | @@ -189,9 +287,19 @@ | |||
4106 | 189 | m_lastMessage = reply; | 287 | m_lastMessage = reply; |
4107 | 190 | return false; | 288 | return false; |
4108 | 191 | } | 289 | } |
4109 | 290 | |||
4110 | 291 | provisionPrinter(name); | ||
4111 | 292 | |||
4112 | 192 | return true; | 293 | return true; |
4113 | 193 | } | 294 | } |
4114 | 194 | 295 | ||
4115 | 296 | void Printers::provisionPrinter(const QString &name) | ||
4116 | 297 | { | ||
4117 | 298 | // We mimic what System Config Printer does here. | ||
4118 | 299 | m_backend->printerSetEnabled(name, true); | ||
4119 | 300 | m_backend->printerSetAcceptJobs(name, true); | ||
4120 | 301 | } | ||
4121 | 302 | |||
4122 | 195 | bool Printers::removePrinter(const QString &name) | 303 | bool Printers::removePrinter(const QString &name) |
4123 | 196 | { | 304 | { |
4124 | 197 | QString reply = m_backend->printerDelete(name); | 305 | QString reply = m_backend->printerDelete(name); |
4125 | @@ -206,8 +314,21 @@ | |||
4126 | 206 | void Printers::jobAdded(QSharedPointer<PrinterJob> job) | 314 | void Printers::jobAdded(QSharedPointer<PrinterJob> job) |
4127 | 207 | { | 315 | { |
4128 | 208 | auto printer = m_model.getPrinterByName(job->printerName()); | 316 | auto printer = m_model.getPrinterByName(job->printerName()); |
4131 | 209 | if (printer && job) | 317 | |
4132 | 210 | job->setPrinter(printer); | 318 | // Check if we have a valid printer, does not need to be loaded as JobLoader |
4133 | 319 | // creates it's own Backend. | ||
4134 | 320 | if (printer && job) { | ||
4135 | 321 | // TODO: this printer may not be fully loaded | ||
4136 | 322 | // Which has the side affect of colorModel, duplex, quality not working | ||
4137 | 323 | // in PrinterJob as Printer::supportedColorModels etc fail | ||
4138 | 324 | // Potentially trigger loadPrinter and listen for the new printer? | ||
4139 | 325 | |||
4140 | 326 | // Set the printer to the job | ||
4141 | 327 | m_jobs.updateJobPrinter(job, printer); | ||
4142 | 328 | |||
4143 | 329 | // Trigger JobLoader to load extended attributes in the background | ||
4144 | 330 | m_backend->requestJobExtendedAttributes(printer, job); | ||
4145 | 331 | } | ||
4146 | 211 | } | 332 | } |
4147 | 212 | 333 | ||
4148 | 213 | void Printers::printerAdded(QSharedPointer<Printer> printer) | 334 | void Printers::printerAdded(QSharedPointer<Printer> printer) |
4149 | @@ -223,10 +344,9 @@ | |||
4150 | 223 | ).toString(); | 344 | ).toString(); |
4151 | 224 | 345 | ||
4152 | 225 | int jobId = m_jobs.data(idx, JobModel::Roles::IdRole).toInt(); | 346 | int jobId = m_jobs.data(idx, JobModel::Roles::IdRole).toInt(); |
4154 | 226 | auto job = m_jobs.getJobById(jobId); | 347 | auto job = m_jobs.getJob(printerName, jobId); |
4155 | 227 | if (printerName == printer->name() && !job->printer()) { | 348 | if (printerName == printer->name() && !job->printer()) { |
4158 | 228 | job->setPrinter(printer); | 349 | jobAdded(job); |
4157 | 229 | return; | ||
4159 | 230 | } | 350 | } |
4160 | 231 | } | 351 | } |
4161 | 232 | } | 352 | } |
4162 | @@ -243,3 +363,28 @@ | |||
4163 | 243 | m_backend->requestPrinter(name); | 363 | m_backend->requestPrinter(name); |
4164 | 244 | } | 364 | } |
4165 | 245 | } | 365 | } |
4166 | 366 | |||
4167 | 367 | void Printers::printTestPage(const QString &name) | ||
4168 | 368 | { | ||
4169 | 369 | |||
4170 | 370 | auto printer = m_model.getPrinterByName(name); | ||
4171 | 371 | if (!printer) { | ||
4172 | 372 | qWarning() << Q_FUNC_INFO << "no known printer named" << name; | ||
4173 | 373 | return; | ||
4174 | 374 | } | ||
4175 | 375 | |||
4176 | 376 | auto page = QStandardPaths::locate(QStandardPaths::GenericDataLocation, | ||
4177 | 377 | "cups/data/default-testpage.pdf", | ||
4178 | 378 | QStandardPaths::LocateFile); | ||
4179 | 379 | |||
4180 | 380 | if (page.isEmpty()) { | ||
4181 | 381 | qCritical() << Q_FUNC_INFO << "Could not find test page."; | ||
4182 | 382 | return; | ||
4183 | 383 | } | ||
4184 | 384 | |||
4185 | 385 | auto job = new PrinterJob(name, m_backend); | ||
4186 | 386 | job->setPrinter(printer); | ||
4187 | 387 | job->setTitle(__("Test page")); | ||
4188 | 388 | job->printFile(QUrl::fromLocalFile(page)); | ||
4189 | 389 | job->deleteLater(); | ||
4190 | 390 | } | ||
4191 | 246 | 391 | ||
4192 | === modified file 'modules/Ubuntu/Components/Extras/Printers/printers/printers.h' | |||
4193 | --- modules/Ubuntu/Components/Extras/Printers/printers/printers.h 2017-02-24 12:20:07 +0000 | |||
4194 | +++ modules/Ubuntu/Components/Extras/Printers/printers/printers.h 2017-03-23 12:51:36 +0000 | |||
4195 | @@ -19,6 +19,7 @@ | |||
4196 | 19 | 19 | ||
4197 | 20 | #include "printers_global.h" | 20 | #include "printers_global.h" |
4198 | 21 | 21 | ||
4199 | 22 | #include "models/devicemodel.h" | ||
4200 | 22 | #include "models/drivermodel.h" | 23 | #include "models/drivermodel.h" |
4201 | 23 | #include "models/printermodel.h" | 24 | #include "models/printermodel.h" |
4202 | 24 | #include "printer/printer.h" | 25 | #include "printer/printer.h" |
4203 | @@ -36,8 +37,11 @@ | |||
4204 | 36 | Q_OBJECT | 37 | Q_OBJECT |
4205 | 37 | Q_PROPERTY(QAbstractItemModel* allPrinters READ allPrinters CONSTANT) | 38 | Q_PROPERTY(QAbstractItemModel* allPrinters READ allPrinters CONSTANT) |
4206 | 38 | Q_PROPERTY(QAbstractItemModel* allPrintersWithPdf READ allPrintersWithPdf CONSTANT) | 39 | Q_PROPERTY(QAbstractItemModel* allPrintersWithPdf READ allPrintersWithPdf CONSTANT) |
4207 | 40 | Q_PROPERTY(QAbstractItemModel* remotePrinters READ remotePrinters CONSTANT) | ||
4208 | 41 | Q_PROPERTY(QAbstractItemModel* localPrinters READ localPrinters CONSTANT) | ||
4209 | 39 | Q_PROPERTY(QAbstractItemModel* printJobs READ printJobs CONSTANT) | 42 | Q_PROPERTY(QAbstractItemModel* printJobs READ printJobs CONSTANT) |
4210 | 40 | Q_PROPERTY(QAbstractItemModel* drivers READ drivers CONSTANT) | 43 | Q_PROPERTY(QAbstractItemModel* drivers READ drivers CONSTANT) |
4211 | 44 | Q_PROPERTY(QAbstractItemModel* devices READ devices CONSTANT) | ||
4212 | 41 | Q_PROPERTY(QString driverFilter READ driverFilter WRITE setDriverFilter NOTIFY driverFilterChanged) | 45 | Q_PROPERTY(QString driverFilter READ driverFilter WRITE setDriverFilter NOTIFY driverFilterChanged) |
4213 | 42 | Q_PROPERTY(QString defaultPrinterName READ defaultPrinterName WRITE setDefaultPrinterName NOTIFY defaultPrinterNameChanged) | 46 | Q_PROPERTY(QString defaultPrinterName READ defaultPrinterName WRITE setDefaultPrinterName NOTIFY defaultPrinterNameChanged) |
4214 | 43 | Q_PROPERTY(QString lastMessage READ lastMessage CONSTANT) | 47 | Q_PROPERTY(QString lastMessage READ lastMessage CONSTANT) |
4215 | @@ -51,8 +55,11 @@ | |||
4216 | 51 | 55 | ||
4217 | 52 | QAbstractItemModel* allPrinters(); | 56 | QAbstractItemModel* allPrinters(); |
4218 | 53 | QAbstractItemModel* allPrintersWithPdf(); | 57 | QAbstractItemModel* allPrintersWithPdf(); |
4219 | 58 | QAbstractItemModel* remotePrinters(); | ||
4220 | 59 | QAbstractItemModel* localPrinters(); | ||
4221 | 54 | QAbstractItemModel* printJobs(); | 60 | QAbstractItemModel* printJobs(); |
4222 | 55 | QAbstractItemModel* drivers(); | 61 | QAbstractItemModel* drivers(); |
4223 | 62 | QAbstractItemModel* devices(); | ||
4224 | 56 | QString driverFilter() const; | 63 | QString driverFilter() const; |
4225 | 57 | QString defaultPrinterName() const; | 64 | QString defaultPrinterName() const; |
4226 | 58 | QString lastMessage() const; | 65 | QString lastMessage() const; |
4227 | @@ -62,7 +69,11 @@ | |||
4228 | 62 | 69 | ||
4229 | 63 | public Q_SLOTS: | 70 | public Q_SLOTS: |
4230 | 64 | PrinterJob* createJob(const QString &printerName); | 71 | PrinterJob* createJob(const QString &printerName); |
4231 | 72 | QAbstractItemModel* createJobFilter(); | ||
4232 | 73 | |||
4233 | 65 | void cancelJob(const QString &printerName, const int jobId); | 74 | void cancelJob(const QString &printerName, const int jobId); |
4234 | 75 | void holdJob(const QString &printerName, const int jobId); | ||
4235 | 76 | void releaseJob(const QString &printerName, const int jobId); | ||
4236 | 66 | 77 | ||
4237 | 67 | /* Instructs us to start loading drivers and what have you. In most cases, | 78 | /* Instructs us to start loading drivers and what have you. In most cases, |
4238 | 68 | the user is likely to merely configure existing printers/jobs. Loading | 79 | the user is likely to merely configure existing printers/jobs. Loading |
4239 | @@ -70,6 +81,9 @@ | |||
4240 | 70 | add printers, this method should be called first. */ | 81 | add printers, this method should be called first. */ |
4241 | 71 | void prepareToAddPrinter(); | 82 | void prepareToAddPrinter(); |
4242 | 72 | 83 | ||
4243 | 84 | // Starts a search for devices on local and remote resources. | ||
4244 | 85 | void searchForDevices(); | ||
4245 | 86 | |||
4246 | 73 | bool addPrinter(const QString &name, const QString &ppd, | 87 | bool addPrinter(const QString &name, const QString &ppd, |
4247 | 74 | const QString &device, const QString &description, | 88 | const QString &device, const QString &description, |
4248 | 75 | const QString &location); | 89 | const QString &location); |
4249 | @@ -83,6 +97,8 @@ | |||
4250 | 83 | // Instruct us to start (eagerly) loading a printer. | 97 | // Instruct us to start (eagerly) loading a printer. |
4251 | 84 | void loadPrinter(const QString &name); | 98 | void loadPrinter(const QString &name); |
4252 | 85 | 99 | ||
4253 | 100 | void printTestPage(const QString &name); | ||
4254 | 101 | |||
4255 | 86 | private Q_SLOTS: | 102 | private Q_SLOTS: |
4256 | 87 | void jobAdded(QSharedPointer<PrinterJob> job); | 103 | void jobAdded(QSharedPointer<PrinterJob> job); |
4257 | 88 | void printerAdded(QSharedPointer<Printer> printer); | 104 | void printerAdded(QSharedPointer<Printer> printer); |
4258 | @@ -92,12 +108,16 @@ | |||
4259 | 92 | void driverFilterChanged(); | 108 | void driverFilterChanged(); |
4260 | 93 | 109 | ||
4261 | 94 | private: | 110 | private: |
4262 | 111 | void provisionPrinter(const QString &name); | ||
4263 | 95 | PrinterBackend *m_backend; | 112 | PrinterBackend *m_backend; |
4264 | 113 | DeviceModel m_devices; | ||
4265 | 96 | DriverModel m_drivers; | 114 | DriverModel m_drivers; |
4266 | 97 | PrinterModel m_model; | 115 | PrinterModel m_model; |
4267 | 98 | JobModel m_jobs; | 116 | JobModel m_jobs; |
4268 | 99 | PrinterFilter m_allPrinters; | 117 | PrinterFilter m_allPrinters; |
4269 | 100 | PrinterFilter m_allPrintersWithPdf; | 118 | PrinterFilter m_allPrintersWithPdf; |
4270 | 119 | PrinterFilter m_remotePrinters; | ||
4271 | 120 | PrinterFilter m_localPrinters; | ||
4272 | 101 | PrinterFilter m_recentPrinters; | 121 | PrinterFilter m_recentPrinters; |
4273 | 102 | QString m_lastMessage; | 122 | QString m_lastMessage; |
4274 | 103 | }; | 123 | }; |
4275 | 104 | 124 | ||
4276 | === modified file 'modules/Ubuntu/Components/Extras/Printers/structs.h' | |||
4277 | --- modules/Ubuntu/Components/Extras/Printers/structs.h 2017-02-23 14:04:26 +0000 | |||
4278 | +++ modules/Ubuntu/Components/Extras/Printers/structs.h 2017-03-23 12:51:36 +0000 | |||
4279 | @@ -84,6 +84,87 @@ | |||
4280 | 84 | } | 84 | } |
4281 | 85 | }; | 85 | }; |
4282 | 86 | 86 | ||
4283 | 87 | struct Device | ||
4284 | 88 | { | ||
4285 | 89 | public: | ||
4286 | 90 | QString cls; | ||
4287 | 91 | QString id; | ||
4288 | 92 | QString info; | ||
4289 | 93 | QString makeModel; | ||
4290 | 94 | QString uri; | ||
4291 | 95 | QString location; | ||
4292 | 96 | PrinterEnum::DeviceType type() | ||
4293 | 97 | { | ||
4294 | 98 | auto parts = uri.split(":", QString::SkipEmptyParts); | ||
4295 | 99 | QString scheme = parts.size() > 0 ? parts[0] : QStringLiteral(""); | ||
4296 | 100 | if (scheme == QStringLiteral("dnssd")) | ||
4297 | 101 | return PrinterEnum::DeviceType::DNSSDType; | ||
4298 | 102 | else if (scheme == QStringLiteral("lpd")) | ||
4299 | 103 | return PrinterEnum::DeviceType::LPDType; | ||
4300 | 104 | else if (scheme == QStringLiteral("ipps")) | ||
4301 | 105 | return PrinterEnum::DeviceType::IppSType; | ||
4302 | 106 | else if (scheme == QStringLiteral("ipp14")) | ||
4303 | 107 | return PrinterEnum::DeviceType::Ipp14Type; | ||
4304 | 108 | else if (scheme == QStringLiteral("http")) | ||
4305 | 109 | return PrinterEnum::DeviceType::HttpType; | ||
4306 | 110 | else if (scheme == QStringLiteral("beh")) | ||
4307 | 111 | return PrinterEnum::DeviceType::BehType; | ||
4308 | 112 | else if (scheme == QStringLiteral("socket")) | ||
4309 | 113 | return PrinterEnum::DeviceType::SocketType; | ||
4310 | 114 | else if (scheme == QStringLiteral("https")) | ||
4311 | 115 | return PrinterEnum::DeviceType::HttpsType; | ||
4312 | 116 | else if (scheme == QStringLiteral("ipp")) | ||
4313 | 117 | return PrinterEnum::DeviceType::IppType; | ||
4314 | 118 | else if (scheme == QStringLiteral("hp")) | ||
4315 | 119 | return PrinterEnum::DeviceType::HPType; | ||
4316 | 120 | else if (scheme == QStringLiteral("usb")) | ||
4317 | 121 | return PrinterEnum::DeviceType::USBType; | ||
4318 | 122 | else if (scheme == QStringLiteral("hpfax")) | ||
4319 | 123 | return PrinterEnum::DeviceType::HPFaxType; | ||
4320 | 124 | else | ||
4321 | 125 | return PrinterEnum::DeviceType::UnknownType; | ||
4322 | 126 | } | ||
4323 | 127 | |||
4324 | 128 | QString toString() const { | ||
4325 | 129 | /* 1. Split the id, which is of format "KEY:VAL; … KEYN:VALN;" into | ||
4326 | 130 | ["KEY:VAL", …, "KEYN:VALN"] | ||
4327 | 131 | 2. Split each pair into | ||
4328 | 132 | ["KEY", "VAL"] … ["KEYN", "VALN"]*/ | ||
4329 | 133 | QMap<QString, QString> idMap; | ||
4330 | 134 | auto pairs = id.split(";"); | ||
4331 | 135 | Q_FOREACH(const QString &pair, pairs) { | ||
4332 | 136 | auto keyValue = pair.split(":"); | ||
4333 | 137 | |||
4334 | 138 | /* Sometimes key,val pairs are not terminated by ";". We just | ||
4335 | 139 | use the first value in that case. E.g.: | ||
4336 | 140 | "MFG:HP MDL:Laserfjert;" | ||
4337 | 141 | Will give "HP" as MFG, and "" as MDL. */ | ||
4338 | 142 | if (keyValue.size() >= 2) { | ||
4339 | 143 | idMap[keyValue[0]] = keyValue[1]; | ||
4340 | 144 | } | ||
4341 | 145 | } | ||
4342 | 146 | auto mfg = idMap.value("MFG", ""); | ||
4343 | 147 | auto mdl = idMap.value("MDL", ""); | ||
4344 | 148 | |||
4345 | 149 | /* If the MDL field contains CMD, somebody forgot to terminate, and we | ||
4346 | 150 | remove it. */ | ||
4347 | 151 | if (mdl.contains("CMD")) { | ||
4348 | 152 | mdl = mdl.split("CMD")[0]; | ||
4349 | 153 | } | ||
4350 | 154 | |||
4351 | 155 | return QString("%1 %2").arg(mfg).arg(mdl); | ||
4352 | 156 | } | ||
4353 | 157 | |||
4354 | 158 | bool operator==(const Device &other) | ||
4355 | 159 | { | ||
4356 | 160 | return ((cls == other.cls) && (id == other.id) && (info == other.info) && | ||
4357 | 161 | (makeModel == other.makeModel) && (uri == other.uri) && | ||
4358 | 162 | (location == other.location)); | ||
4359 | 163 | } | ||
4360 | 164 | }; | ||
4361 | 165 | |||
4362 | 166 | |||
4363 | 167 | |||
4364 | 87 | Q_DECLARE_TYPEINFO(ColorModel, Q_PRIMITIVE_TYPE); | 168 | Q_DECLARE_TYPEINFO(ColorModel, Q_PRIMITIVE_TYPE); |
4365 | 88 | Q_DECLARE_METATYPE(ColorModel) | 169 | Q_DECLARE_METATYPE(ColorModel) |
4366 | 89 | 170 | ||
4367 | @@ -94,4 +175,7 @@ | |||
4368 | 94 | Q_DECLARE_METATYPE(PrinterDriver) | 175 | Q_DECLARE_METATYPE(PrinterDriver) |
4369 | 95 | Q_DECLARE_METATYPE(QList<PrinterDriver>) | 176 | Q_DECLARE_METATYPE(QList<PrinterDriver>) |
4370 | 96 | 177 | ||
4371 | 178 | Q_DECLARE_TYPEINFO(Device, Q_MOVABLE_TYPE); | ||
4372 | 179 | Q_DECLARE_METATYPE(Device) | ||
4373 | 180 | |||
4374 | 97 | #endif // USC_PRINTERS_STRUCTS_H | 181 | #endif // USC_PRINTERS_STRUCTS_H |
4375 | 98 | 182 | ||
4376 | === modified file 'po/ubuntu-ui-extras.pot' | |||
4377 | --- po/ubuntu-ui-extras.pot 2017-02-21 10:46:29 +0000 | |||
4378 | +++ po/ubuntu-ui-extras.pot 2017-03-23 12:51:36 +0000 | |||
4379 | @@ -8,7 +8,7 @@ | |||
4380 | 8 | msgstr "" | 8 | msgstr "" |
4381 | 9 | "Project-Id-Version: ubuntu-ui-extras\n" | 9 | "Project-Id-Version: ubuntu-ui-extras\n" |
4382 | 10 | "Report-Msgid-Bugs-To: \n" | 10 | "Report-Msgid-Bugs-To: \n" |
4384 | 11 | "POT-Creation-Date: 2017-02-21 10:42+0000\n" | 11 | "POT-Creation-Date: 2017-03-21 15:33+0100\n" |
4385 | 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
4386 | 13 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | 13 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
4387 | 14 | "Language-Team: LANGUAGE <LL@li.org>\n" | 14 | "Language-Team: LANGUAGE <LL@li.org>\n" |
4388 | @@ -17,6 +17,14 @@ | |||
4389 | 17 | "Content-Type: text/plain; charset=CHARSET\n" | 17 | "Content-Type: text/plain; charset=CHARSET\n" |
4390 | 18 | "Content-Transfer-Encoding: 8bit\n" | 18 | "Content-Transfer-Encoding: 8bit\n" |
4391 | 19 | 19 | ||
4392 | 20 | #: modules/Ubuntu/Components/Extras/Example/Printers.qml:106 | ||
4393 | 21 | msgid "Aborted" | ||
4394 | 22 | msgstr "" | ||
4395 | 23 | |||
4396 | 24 | #: modules/Ubuntu/Components/Extras/Example/Printers.qml:108 | ||
4397 | 25 | msgid "Active" | ||
4398 | 26 | msgstr "" | ||
4399 | 27 | |||
4400 | 20 | #: modules/Ubuntu/Components/Extras/PhotoEditor.qml:206 | 28 | #: modules/Ubuntu/Components/Extras/PhotoEditor.qml:206 |
4401 | 21 | #: modules/Ubuntu/Components/Extras/PhotoEditor/ExposureAdjuster.qml:81 | 29 | #: modules/Ubuntu/Components/Extras/PhotoEditor/ExposureAdjuster.qml:81 |
4402 | 22 | msgid "Cancel" | 30 | msgid "Cancel" |
4403 | @@ -26,7 +34,7 @@ | |||
4404 | 26 | msgid "Color" | 34 | msgid "Color" |
4405 | 27 | msgstr "" | 35 | msgstr "" |
4406 | 28 | 36 | ||
4408 | 29 | #: modules/Ubuntu/Components/Extras/Printers/models/printermodel.cpp:53 | 37 | #: modules/Ubuntu/Components/Extras/Printers/models/printermodel.cpp:54 |
4409 | 30 | msgid "Create PDF" | 38 | msgid "Create PDF" |
4410 | 31 | msgstr "" | 39 | msgstr "" |
4411 | 32 | 40 | ||
4412 | @@ -43,10 +51,18 @@ | |||
4413 | 43 | msgid "Enhancing photo..." | 51 | msgid "Enhancing photo..." |
4414 | 44 | msgstr "" | 52 | msgstr "" |
4415 | 45 | 53 | ||
4416 | 54 | #: modules/Ubuntu/Components/Extras/Example/Printers.qml:104 | ||
4417 | 55 | msgid "Idle" | ||
4418 | 56 | msgstr "" | ||
4419 | 57 | |||
4420 | 46 | #: modules/Ubuntu/Components/Extras/Printers/utils.h:61 | 58 | #: modules/Ubuntu/Components/Extras/Printers/utils.h:61 |
4421 | 47 | msgid "Long Edge (Standard)" | 59 | msgid "Long Edge (Standard)" |
4422 | 48 | msgstr "" | 60 | msgstr "" |
4423 | 49 | 61 | ||
4424 | 62 | #: modules/Ubuntu/Components/Extras/Example/Printers.qml:115 | ||
4425 | 63 | msgid "No messages" | ||
4426 | 64 | msgstr "" | ||
4427 | 65 | |||
4428 | 50 | #: modules/Ubuntu/Components/Extras/Printers/backend/backend_pdf.cpp:47 | 66 | #: modules/Ubuntu/Components/Extras/Printers/backend/backend_pdf.cpp:47 |
4429 | 51 | msgid "Normal" | 67 | msgid "Normal" |
4430 | 52 | msgstr "" | 68 | msgstr "" |
4431 | @@ -79,6 +95,14 @@ | |||
4432 | 79 | msgid "Short Edge (Flip)" | 95 | msgid "Short Edge (Flip)" |
4433 | 80 | msgstr "" | 96 | msgstr "" |
4434 | 81 | 97 | ||
4435 | 98 | #: modules/Ubuntu/Components/Extras/Example/Printers.qml:110 | ||
4436 | 99 | msgid "Stopped" | ||
4437 | 100 | msgstr "" | ||
4438 | 101 | |||
4439 | 102 | #: modules/Ubuntu/Components/Extras/Printers/printers/printers.cpp:387 | ||
4440 | 103 | msgid "Test page" | ||
4441 | 104 | msgstr "" | ||
4442 | 105 | |||
4443 | 82 | #: modules/Ubuntu/Components/Extras/PhotoEditor.qml:197 | 106 | #: modules/Ubuntu/Components/Extras/PhotoEditor.qml:197 |
4444 | 83 | msgid "This will undo all edits, including those from previous sessions." | 107 | msgid "This will undo all edits, including those from previous sessions." |
4445 | 84 | msgstr "" | 108 | msgstr "" |
4446 | 85 | 109 | ||
4447 | === modified file 'tests/unittests/Printers/CMakeLists.txt' | |||
4448 | --- tests/unittests/Printers/CMakeLists.txt 2017-02-21 16:55:36 +0000 | |||
4449 | +++ tests/unittests/Printers/CMakeLists.txt 2017-03-23 12:51:36 +0000 | |||
4450 | @@ -22,6 +22,8 @@ | |||
4451 | 22 | add_executable(testPrintersPrinters tst_printers.cpp ${MOCK_SOURCES}) | 22 | add_executable(testPrintersPrinters tst_printers.cpp ${MOCK_SOURCES}) |
4452 | 23 | target_link_libraries(testPrintersPrinters UbuntuComponentsExtrasPrintersQml Qt5::Test Qt5::Gui) | 23 | target_link_libraries(testPrintersPrinters UbuntuComponentsExtrasPrintersQml Qt5::Test Qt5::Gui) |
4453 | 24 | add_test(tst_printers testPrintersPrinters) | 24 | add_test(tst_printers testPrintersPrinters) |
4454 | 25 | set_tests_properties(tst_printers PROPERTIES | ||
4455 | 26 | ENVIRONMENT "XDG_DATA_DIRS=${CMAKE_CURRENT_SOURCE_DIR}/testdata") | ||
4456 | 25 | 27 | ||
4457 | 26 | add_executable(testPrintersPrinterModel tst_printermodel.cpp ${MOCK_SOURCES}) | 28 | add_executable(testPrintersPrinterModel tst_printermodel.cpp ${MOCK_SOURCES}) |
4458 | 27 | target_link_libraries(testPrintersPrinterModel UbuntuComponentsExtrasPrintersQml Qt5::Test Qt5::Gui) | 29 | target_link_libraries(testPrintersPrinterModel UbuntuComponentsExtrasPrintersQml Qt5::Test Qt5::Gui) |
4459 | @@ -43,6 +45,14 @@ | |||
4460 | 43 | target_link_libraries(testPrintersJobFilter UbuntuComponentsExtrasPrintersQml Qt5::Test Qt5::Gui) | 45 | target_link_libraries(testPrintersJobFilter UbuntuComponentsExtrasPrintersQml Qt5::Test Qt5::Gui) |
4461 | 44 | add_test(tst_jobfilter testPrintersJobFilter) | 46 | add_test(tst_jobfilter testPrintersJobFilter) |
4462 | 45 | 47 | ||
4466 | 46 | add_executable(testPrintersSignalHandler tst_signalhandler.cpp ${MOCK_SOURCES}) | 48 | add_executable(testPrintersSignalRateLimiter tst_signalratelimiter.cpp ${MOCK_SOURCES}) |
4467 | 47 | target_link_libraries(testPrintersSignalHandler UbuntuComponentsExtrasPrintersQml Qt5::Test Qt5::Gui) | 49 | target_link_libraries(testPrintersSignalRateLimiter UbuntuComponentsExtrasPrintersQml Qt5::Test Qt5::Gui) |
4468 | 48 | add_test(tst_signalhandler testPrintersSignalHandler) | 50 | add_test(tst_signalratelimiter testPrintersSignalRateLimiter) |
4469 | 51 | |||
4470 | 52 | add_executable(testPrintersDevice tst_printerdevice.cpp ${MOCK_SOURCES}) | ||
4471 | 53 | target_link_libraries(testPrintersDevice UbuntuComponentsExtrasPrintersQml Qt5::Test Qt5::Gui) | ||
4472 | 54 | add_test(tst_printerdevice testPrintersDevice) | ||
4473 | 55 | |||
4474 | 56 | add_executable(testPrintersDeviceModel tst_printerdevicemodel.cpp ${MOCK_SOURCES}) | ||
4475 | 57 | target_link_libraries(testPrintersDeviceModel UbuntuComponentsExtrasPrintersQml Qt5::Test Qt5::Gui) | ||
4476 | 58 | add_test(tst_printerdevicemodel testPrintersDeviceModel) | ||
4477 | 49 | 59 | ||
4478 | === modified file 'tests/unittests/Printers/mockbackend.h' | |||
4479 | --- tests/unittests/Printers/mockbackend.h 2017-02-24 12:20:07 +0000 | |||
4480 | +++ tests/unittests/Printers/mockbackend.h 2017-03-23 12:51:36 +0000 | |||
4481 | @@ -40,7 +40,7 @@ | |||
4482 | 40 | 40 | ||
4483 | 41 | virtual bool holdsDefinition() const override | 41 | virtual bool holdsDefinition() const override |
4484 | 42 | { | 42 | { |
4486 | 43 | return true; | 43 | return m_holdsDefinition; |
4487 | 44 | } | 44 | } |
4488 | 45 | 45 | ||
4489 | 46 | virtual QString printerAdd(const QString &name, | 46 | virtual QString printerAdd(const QString &name, |
4490 | @@ -105,6 +105,19 @@ | |||
4491 | 105 | return returnValue; | 105 | return returnValue; |
4492 | 106 | } | 106 | } |
4493 | 107 | 107 | ||
4494 | 108 | virtual QString printerSetCopies(const QString &name, const int &copies) | ||
4495 | 109 | { | ||
4496 | 110 | printerOptions[name].insert("Copies", copies); | ||
4497 | 111 | return returnValue; | ||
4498 | 112 | } | ||
4499 | 113 | |||
4500 | 114 | virtual QString printerSetShared(const QString &name, | ||
4501 | 115 | const bool shared) override | ||
4502 | 116 | { | ||
4503 | 117 | printerOptions[name].insert("Shared", shared); | ||
4504 | 118 | return returnValue; | ||
4505 | 119 | } | ||
4506 | 120 | |||
4507 | 108 | virtual QString printerSetInfo(const QString &name, | 121 | virtual QString printerSetInfo(const QString &name, |
4508 | 109 | const QString &info) override | 122 | const QString &info) override |
4509 | 110 | { | 123 | { |
4510 | @@ -163,6 +176,32 @@ | |||
4511 | 163 | } | 176 | } |
4512 | 164 | } | 177 | } |
4513 | 165 | 178 | ||
4514 | 179 | virtual void holdJob(const QString &printerName, const int jobId) override | ||
4515 | 180 | { | ||
4516 | 181 | // Change the faked job state | ||
4517 | 182 | Q_FOREACH(auto job, m_jobs) { | ||
4518 | 183 | if (job->printerName() == printerName | ||
4519 | 184 | && job->jobId() == jobId) { | ||
4520 | 185 | job->setState(PrinterEnum::JobState::Held); | ||
4521 | 186 | } | ||
4522 | 187 | } | ||
4523 | 188 | |||
4524 | 189 | Q_EMIT jobState("", "", printerName, 1, "", true, jobId, static_cast<uint>(PrinterEnum::JobState::Held), "", "", 1); | ||
4525 | 190 | } | ||
4526 | 191 | |||
4527 | 192 | virtual void releaseJob(const QString &printerName, const int jobId) override | ||
4528 | 193 | { | ||
4529 | 194 | // Change the faked job state | ||
4530 | 195 | Q_FOREACH(auto job, m_jobs) { | ||
4531 | 196 | if (job->printerName() == printerName | ||
4532 | 197 | && job->jobId() == jobId) { | ||
4533 | 198 | job->setState(PrinterEnum::JobState::Pending); | ||
4534 | 199 | } | ||
4535 | 200 | } | ||
4536 | 201 | |||
4537 | 202 | Q_EMIT jobState("", "", printerName, 1, "", true, jobId, static_cast<uint>(PrinterEnum::JobState::Pending), "", "", 1); | ||
4538 | 203 | } | ||
4539 | 204 | |||
4540 | 166 | virtual int printFileToDest(const QString &filepath, | 205 | virtual int printFileToDest(const QString &filepath, |
4541 | 167 | const QString &title, | 206 | const QString &title, |
4542 | 168 | const cups_dest_t *dest) override | 207 | const cups_dest_t *dest) override |
4543 | @@ -184,9 +223,39 @@ | |||
4544 | 184 | virtual QMap<QString, QVariant> printerGetJobAttributes( | 223 | virtual QMap<QString, QVariant> printerGetJobAttributes( |
4545 | 185 | const QString &name, const int jobId) override | 224 | const QString &name, const int jobId) override |
4546 | 186 | { | 225 | { |
4550 | 187 | Q_UNUSED(name); | 226 | QMap<QString, QVariant> attributes; |
4551 | 188 | Q_UNUSED(jobId); | 227 | |
4552 | 189 | return QMap<QString, QVariant>(); | 228 | Q_FOREACH(auto job, m_jobs) { |
4553 | 229 | if (job->printerName() == name | ||
4554 | 230 | && job->jobId() == jobId) { | ||
4555 | 231 | // Emulate reverse of PrinterJob::loadAttributes | ||
4556 | 232 | // using local jobs defined in tests | ||
4557 | 233 | attributes.insert("Collate", job->collate()); | ||
4558 | 234 | attributes.insert("copies", job->copies()); | ||
4559 | 235 | attributes.insert("ColorModel", job->getColorModel().name); | ||
4560 | 236 | attributes.insert("CompletedTime", job->completedTime()); | ||
4561 | 237 | attributes.insert("CreationTime", job->creationTime()); | ||
4562 | 238 | attributes.insert("Duplex", Utils::duplexModeToPpdChoice(job->getDuplexMode())); | ||
4563 | 239 | attributes.insert("impressionsCompleted", job->impressionsCompleted()); | ||
4564 | 240 | attributes.insert("landscape", job->landscape()); | ||
4565 | 241 | attributes.insert("messages", job->messages()); | ||
4566 | 242 | if (job->printRangeMode() == PrinterEnum::PrintRange::AllPages) { | ||
4567 | 243 | attributes.insert("page-ranges", QStringList()); | ||
4568 | 244 | } else { | ||
4569 | 245 | attributes.insert("page-ranges", job->printRange().split(QLocale::system().groupSeparator())); | ||
4570 | 246 | } | ||
4571 | 247 | attributes.insert("ProcessingTime", job->processingTime()); | ||
4572 | 248 | attributes.insert("Quality", job->getPrintQuality().name); | ||
4573 | 249 | attributes.insert("OutputOrder", job->reverse() ? "Reverse" : "Normal"); | ||
4574 | 250 | attributes.insert("State", static_cast<int>(job->state())); | ||
4575 | 251 | attributes.insert("Size", job->size()); | ||
4576 | 252 | attributes.insert("User", job->user()); | ||
4577 | 253 | |||
4578 | 254 | break; | ||
4579 | 255 | } | ||
4580 | 256 | } | ||
4581 | 257 | |||
4582 | 258 | return attributes; | ||
4583 | 190 | } | 259 | } |
4584 | 191 | 260 | ||
4585 | 192 | virtual QString printerName() const override | 261 | virtual QString printerName() const override |
4586 | @@ -209,6 +278,11 @@ | |||
4587 | 209 | return m_makeAndModel; | 278 | return m_makeAndModel; |
4588 | 210 | } | 279 | } |
4589 | 211 | 280 | ||
4590 | 281 | virtual bool isRemote() const override | ||
4591 | 282 | { | ||
4592 | 283 | return m_remote; | ||
4593 | 284 | } | ||
4594 | 285 | |||
4595 | 212 | virtual PrinterEnum::State state() const override | 286 | virtual PrinterEnum::State state() const override |
4596 | 213 | { | 287 | { |
4597 | 214 | return m_state; | 288 | return m_state; |
4598 | @@ -287,6 +361,17 @@ | |||
4599 | 287 | m_requestedPrinters << printerName; | 361 | m_requestedPrinters << printerName; |
4600 | 288 | } | 362 | } |
4601 | 289 | 363 | ||
4602 | 364 | virtual void requestJobExtendedAttributes(QSharedPointer<Printer> printer, QSharedPointer<PrinterJob> job) override | ||
4603 | 365 | { | ||
4604 | 366 | QMap<QString, QVariant> attributes = printerGetJobAttributes(printer->name(), job->jobId()); | ||
4605 | 367 | |||
4606 | 368 | Q_EMIT jobLoaded(printer->name(), job->jobId(), attributes); | ||
4607 | 369 | } | ||
4608 | 370 | |||
4609 | 371 | virtual PrinterEnum::PrinterType type() const override | ||
4610 | 372 | { | ||
4611 | 373 | return m_type; | ||
4612 | 374 | } | ||
4613 | 290 | 375 | ||
4614 | 291 | void mockPrinterAdded( | 376 | void mockPrinterAdded( |
4615 | 292 | const QString &text, | 377 | const QString &text, |
4616 | @@ -339,6 +424,34 @@ | |||
4617 | 339 | ); | 424 | ); |
4618 | 340 | } | 425 | } |
4619 | 341 | 426 | ||
4620 | 427 | void mockJobCompleted( | ||
4621 | 428 | const QString &text, const QString &printer_uri, | ||
4622 | 429 | const QString &printer_name, uint printer_state, | ||
4623 | 430 | const QString &printer_state_reasons, bool printer_is_accepting_jobs, | ||
4624 | 431 | uint job_id, uint job_state, const QString &job_state_reasons, | ||
4625 | 432 | const QString &job_name, uint job_impressions_completed) | ||
4626 | 433 | { | ||
4627 | 434 | Q_EMIT jobCompleted( | ||
4628 | 435 | text, printer_uri, printer_name, printer_state, | ||
4629 | 436 | printer_state_reasons, printer_is_accepting_jobs, job_id, | ||
4630 | 437 | job_state, job_state_reasons, job_name, job_impressions_completed | ||
4631 | 438 | ); | ||
4632 | 439 | } | ||
4633 | 440 | |||
4634 | 441 | void mockJobState( | ||
4635 | 442 | const QString &text, const QString &printer_uri, | ||
4636 | 443 | const QString &printer_name, uint printer_state, | ||
4637 | 444 | const QString &printer_state_reasons, bool printer_is_accepting_jobs, | ||
4638 | 445 | uint job_id, uint job_state, const QString &job_state_reasons, | ||
4639 | 446 | const QString &job_name, uint job_impressions_completed) | ||
4640 | 447 | { | ||
4641 | 448 | Q_EMIT jobState( | ||
4642 | 449 | text, printer_uri, printer_name, printer_state, | ||
4643 | 450 | printer_state_reasons, printer_is_accepting_jobs, job_id, | ||
4644 | 451 | job_state, job_state_reasons, job_name, job_impressions_completed | ||
4645 | 452 | ); | ||
4646 | 453 | } | ||
4647 | 454 | |||
4648 | 342 | void mockDriversLoaded(const QList<PrinterDriver> &drivers) | 455 | void mockDriversLoaded(const QList<PrinterDriver> &drivers) |
4649 | 343 | { | 456 | { |
4650 | 344 | Q_EMIT printerDriversLoaded(drivers); | 457 | Q_EMIT printerDriversLoaded(drivers); |
4651 | @@ -354,6 +467,11 @@ | |||
4652 | 354 | Q_EMIT printerLoaded(printer); | 467 | Q_EMIT printerLoaded(printer); |
4653 | 355 | } | 468 | } |
4654 | 356 | 469 | ||
4655 | 470 | void mockDeviceFound(const Device &device) | ||
4656 | 471 | { | ||
4657 | 472 | Q_EMIT deviceFound(device); | ||
4658 | 473 | } | ||
4659 | 474 | |||
4660 | 357 | QString returnValue = QString::null; | 475 | QString returnValue = QString::null; |
4661 | 358 | 476 | ||
4662 | 359 | // Map from printer to key/val. | 477 | // Map from printer to key/val. |
4663 | @@ -366,6 +484,9 @@ | |||
4664 | 366 | QMap<QString, PrinterEnum::ErrorPolicy> errorPolicies; | 484 | QMap<QString, PrinterEnum::ErrorPolicy> errorPolicies; |
4665 | 367 | QMap<QString, PrinterEnum::OperationPolicy> operationPolicies; | 485 | QMap<QString, PrinterEnum::OperationPolicy> operationPolicies; |
4666 | 368 | 486 | ||
4667 | 487 | bool m_holdsDefinition = true; | ||
4668 | 488 | bool m_remote = false; | ||
4669 | 489 | |||
4670 | 369 | QString m_description = QString::null; | 490 | QString m_description = QString::null; |
4671 | 370 | QString m_location = QString::null; | 491 | QString m_location = QString::null; |
4672 | 371 | QString m_makeAndModel = QString::null; | 492 | QString m_makeAndModel = QString::null; |
4673 | @@ -383,6 +504,8 @@ | |||
4674 | 383 | QList<QSharedPointer<PrinterJob>> m_jobs; | 504 | QList<QSharedPointer<PrinterJob>> m_jobs; |
4675 | 384 | QStringList m_requestedPrinters; | 505 | QStringList m_requestedPrinters; |
4676 | 385 | 506 | ||
4677 | 507 | PrinterEnum::PrinterType m_type = PrinterEnum::PrinterType::ProxyType; | ||
4678 | 508 | |||
4679 | 386 | Q_SIGNALS: | 509 | Q_SIGNALS: |
4680 | 387 | void printToFile(const QString &filepath, const QString &title); | 510 | void printToFile(const QString &filepath, const QString &title); |
4681 | 388 | }; | 511 | }; |
4682 | 389 | 512 | ||
4683 | === added directory 'tests/unittests/Printers/testdata' | |||
4684 | === added directory 'tests/unittests/Printers/testdata/cups' | |||
4685 | === added directory 'tests/unittests/Printers/testdata/cups/data' | |||
4686 | === added file 'tests/unittests/Printers/testdata/cups/data/default-testpage.pdf' | |||
4687 | === modified file 'tests/unittests/Printers/tst_jobfilter.cpp' | |||
4688 | --- tests/unittests/Printers/tst_jobfilter.cpp 2017-02-21 10:46:29 +0000 | |||
4689 | +++ tests/unittests/Printers/tst_jobfilter.cpp 2017-03-23 12:51:36 +0000 | |||
4690 | @@ -32,10 +32,12 @@ | |||
4691 | 32 | QScopedPointer<MockPrinterBackend> backend(new MockPrinterBackend); | 32 | QScopedPointer<MockPrinterBackend> backend(new MockPrinterBackend); |
4692 | 33 | JobModel model(backend.data()); | 33 | JobModel model(backend.data()); |
4693 | 34 | 34 | ||
4695 | 35 | auto job = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", backend.data())); | 35 | auto job = QSharedPointer<PrinterJob>( |
4696 | 36 | new PrinterJob("test-printer", backend.data(), 100) | ||
4697 | 37 | ); | ||
4698 | 36 | backend->m_jobs << job; | 38 | backend->m_jobs << job; |
4699 | 37 | // Trigger update. | 39 | // Trigger update. |
4701 | 38 | backend->mockJobCreated("", "", "", 1, "", true, 100, 1, "", "", 1); | 40 | backend->mockJobCreated("", "", "test-printer", 1, "", true, 100, 3, "", "", 1); |
4702 | 39 | 41 | ||
4703 | 40 | JobFilter filter; | 42 | JobFilter filter; |
4704 | 41 | filter.setSourceModel(&model); | 43 | filter.setSourceModel(&model); |
4705 | 42 | 44 | ||
4706 | === modified file 'tests/unittests/Printers/tst_jobmodel.cpp' | |||
4707 | --- tests/unittests/Printers/tst_jobmodel.cpp 2017-02-21 10:46:29 +0000 | |||
4708 | +++ tests/unittests/Printers/tst_jobmodel.cpp 2017-03-23 12:51:36 +0000 | |||
4709 | @@ -18,12 +18,14 @@ | |||
4710 | 18 | 18 | ||
4711 | 19 | #include "backend/backend.h" | 19 | #include "backend/backend.h" |
4712 | 20 | #include "models/jobmodel.h" | 20 | #include "models/jobmodel.h" |
4713 | 21 | #include "printers/printers.h" | ||
4714 | 21 | 22 | ||
4715 | 22 | #include <QDebug> | 23 | #include <QDebug> |
4716 | 23 | #include <QObject> | 24 | #include <QObject> |
4717 | 24 | #include <QSignalSpy> | 25 | #include <QSignalSpy> |
4718 | 25 | #include <QTest> | 26 | #include <QTest> |
4719 | 26 | 27 | ||
4720 | 28 | |||
4721 | 27 | class TestJobModel : public QObject | 29 | class TestJobModel : public QObject |
4722 | 28 | { | 30 | { |
4723 | 29 | Q_OBJECT | 31 | Q_OBJECT |
4724 | @@ -31,15 +33,23 @@ | |||
4725 | 31 | void init() | 33 | void init() |
4726 | 32 | { | 34 | { |
4727 | 33 | m_backend = new MockPrinterBackend; | 35 | m_backend = new MockPrinterBackend; |
4729 | 34 | m_model = new JobModel(m_backend); | 36 | m_printers = new Printers(m_backend); |
4730 | 37 | |||
4731 | 38 | m_model = static_cast<JobModel *>(m_printers->printJobs()); | ||
4732 | 39 | |||
4733 | 40 | PrinterBackend* backend = new MockPrinterBackend("test-printer"); | ||
4734 | 41 | auto printer = QSharedPointer<Printer>(new Printer(backend)); | ||
4735 | 42 | m_backend->mockPrinterLoaded(printer); | ||
4736 | 35 | } | 43 | } |
4737 | 36 | void cleanup() | 44 | void cleanup() |
4738 | 37 | { | 45 | { |
4741 | 38 | QSignalSpy destroyedSpy(m_model, SIGNAL(destroyed(QObject*))); | 46 | QSignalSpy destroyedSpy(m_printers, SIGNAL(destroyed(QObject*))); |
4742 | 39 | m_model->deleteLater(); | 47 | m_printers->deleteLater(); |
4743 | 40 | QTRY_COMPARE(destroyedSpy.count(), 1); | 48 | QTRY_COMPARE(destroyedSpy.count(), 1); |
4744 | 41 | delete m_backend; | ||
4745 | 42 | } | 49 | } |
4746 | 50 | |||
4747 | 51 | // Tests for adding/removing/changing things in the model | ||
4748 | 52 | |||
4749 | 43 | void testInsert() | 53 | void testInsert() |
4750 | 44 | { | 54 | { |
4751 | 45 | QSignalSpy countSpy(m_model, SIGNAL(countChanged())); | 55 | QSignalSpy countSpy(m_model, SIGNAL(countChanged())); |
4752 | @@ -68,7 +78,7 @@ | |||
4753 | 68 | catchall handler in the model. */ | 78 | catchall handler in the model. */ |
4754 | 69 | QSignalSpy removeSpy(m_model, SIGNAL(rowsRemoved(const QModelIndex&, int, int))); | 79 | QSignalSpy removeSpy(m_model, SIGNAL(rowsRemoved(const QModelIndex&, int, int))); |
4755 | 70 | m_backend->m_jobs.clear(); | 80 | m_backend->m_jobs.clear(); |
4757 | 71 | m_backend->mockJobCreated("", "", "", 1, "", true, 100, 1, "", "", 1); | 81 | m_backend->mockJobCompleted("", "", "", 1, "", true, 100, 1, "", "", 1); |
4758 | 72 | QCOMPARE(removeSpy.count(), 1); | 82 | QCOMPARE(removeSpy.count(), 1); |
4759 | 73 | 83 | ||
4760 | 74 | // Check item was removed | 84 | // Check item was removed |
4761 | @@ -76,44 +86,451 @@ | |||
4762 | 76 | QCOMPARE(args.at(1).toInt(), 0); | 86 | QCOMPARE(args.at(1).toInt(), 0); |
4763 | 77 | QCOMPARE(args.at(2).toInt(), 0); | 87 | QCOMPARE(args.at(2).toInt(), 0); |
4764 | 78 | } | 88 | } |
4765 | 79 | void testMove() | ||
4766 | 80 | { | ||
4767 | 81 | // Add two jobs. | ||
4768 | 82 | auto job1 = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", m_backend, 1)); | ||
4769 | 83 | auto job2 = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", m_backend, 2)); | ||
4770 | 84 | m_backend->m_jobs << job1 << job2; | ||
4771 | 85 | m_backend->mockJobCreated("", "", "", 1, "", true, 100, 1, "", "", 1); | ||
4772 | 86 | |||
4773 | 87 | m_backend->m_jobs.move(0, 1); | ||
4774 | 88 | // Triggers a move. | ||
4775 | 89 | QSignalSpy moveSpy(m_model, SIGNAL(rowsMoved(const QModelIndex&, int, int, const QModelIndex&, int))); | ||
4776 | 90 | m_backend->mockJobCreated("", "", "", 1, "", true, 100, 1, "", "", 1); | ||
4777 | 91 | QCOMPARE(moveSpy.count(), 1); | ||
4778 | 92 | QList<QVariant> args = moveSpy.at(0); | ||
4779 | 93 | QCOMPARE(args.at(1).toInt(), 1); | ||
4780 | 94 | QCOMPARE(args.at(2).toInt(), 1); | ||
4781 | 95 | QCOMPARE(args.at(4).toInt(), 0); | ||
4782 | 96 | } | ||
4783 | 97 | void testModify() | 89 | void testModify() |
4784 | 98 | { | 90 | { |
4785 | 99 | auto jobBefore = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", m_backend, 1)); | 91 | auto jobBefore = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", m_backend, 1)); |
4786 | 92 | int impressions_count = 1; | ||
4787 | 100 | 93 | ||
4788 | 101 | m_backend->m_jobs << jobBefore; | 94 | m_backend->m_jobs << jobBefore; |
4794 | 102 | m_backend->mockJobCreated("", "", "", 1, "", true, 100, 1, "", "", 1); | 95 | m_backend->mockJobCreated("", "", "", 1, "", true, 100, 1, "", "", impressions_count); |
4790 | 103 | |||
4791 | 104 | auto jobAfter = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", m_backend, 1)); | ||
4792 | 105 | jobAfter->setCopies(100); | ||
4793 | 106 | m_backend->m_jobs.replace(0, jobAfter); | ||
4795 | 107 | 96 | ||
4796 | 108 | // Triggers a change. | 97 | // Triggers a change. |
4797 | 109 | QSignalSpy changedSpy(m_model, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&))); | 98 | QSignalSpy changedSpy(m_model, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&))); |
4799 | 110 | m_backend->mockJobCreated("", "", "", 1, "", true, 100, 1, "", "", 1); | 99 | |
4800 | 100 | impressions_count = 5; | ||
4801 | 101 | m_backend->mockJobState("", "", "", 1, "", true, 100, 1, "", "", impressions_count); | ||
4802 | 102 | |||
4803 | 111 | QCOMPARE(changedSpy.count(), 1); | 103 | QCOMPARE(changedSpy.count(), 1); |
4804 | 112 | } | 104 | } |
4805 | 113 | 105 | ||
4806 | 106 | // Tests for the roles in the model exposed to QML | ||
4807 | 107 | |||
4808 | 108 | void testIdRole() | ||
4809 | 109 | { | ||
4810 | 110 | auto job = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", m_backend, 100)); | ||
4811 | 111 | m_backend->m_jobs << job; | ||
4812 | 112 | m_backend->mockJobCreated("", "", "", 1, "", true, 100, 1, "", "", 1); | ||
4813 | 113 | |||
4814 | 114 | QTRY_COMPARE(m_model->count(), 1); | ||
4815 | 115 | QCOMPARE(job->jobId(), 100); | ||
4816 | 116 | QCOMPARE(m_model->data(m_model->index(0), JobModel::IdRole).toInt(), 100); | ||
4817 | 117 | } | ||
4818 | 118 | void testCollateRole() | ||
4819 | 119 | { | ||
4820 | 120 | auto jobA = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", m_backend, 1)); | ||
4821 | 121 | jobA->setCollate(false); | ||
4822 | 122 | |||
4823 | 123 | auto jobB = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", m_backend, 2)); | ||
4824 | 124 | jobB->setCollate(true); | ||
4825 | 125 | |||
4826 | 126 | m_backend->m_jobs << jobA << jobB; | ||
4827 | 127 | m_backend->mockJobCreated("", "", "test-printer", 1, "", true, 1, 1, "", "", 1); | ||
4828 | 128 | m_backend->mockJobCreated("", "", "test-printer", 1, "", true, 2, 1, "", "", 1); | ||
4829 | 129 | |||
4830 | 130 | QTRY_COMPARE(m_model->count(), 2); | ||
4831 | 131 | |||
4832 | 132 | QCOMPARE(m_model->data(m_model->index(0), JobModel::CollateRole).toBool(), false); | ||
4833 | 133 | QCOMPARE(m_model->data(m_model->index(1), JobModel::CollateRole).toBool(), true); | ||
4834 | 134 | } | ||
4835 | 135 | void testColorModelRole() | ||
4836 | 136 | { | ||
4837 | 137 | // FIXME: read comment in JobModel::updateJob | ||
4838 | 138 | QSKIP("We are ignoring colorModel for now as it requires a loaded Printer for the PrinterJob."); | ||
4839 | 139 | |||
4840 | 140 | ColorModel a; | ||
4841 | 141 | a.name = "KGray"; | ||
4842 | 142 | a.text = "Gray"; | ||
4843 | 143 | |||
4844 | 144 | ColorModel b; | ||
4845 | 145 | b.name = "RGB"; | ||
4846 | 146 | b.text = ""; | ||
4847 | 147 | QList<ColorModel> models({a, b}); | ||
4848 | 148 | |||
4849 | 149 | PrinterBackend* backend = new MockPrinterBackend("a-printer"); | ||
4850 | 150 | ((MockPrinterBackend*) backend)->printerOptions["a-printer"].insert( | ||
4851 | 151 | "SupportedColorModels", QVariant::fromValue(models) | ||
4852 | 152 | ); | ||
4853 | 153 | |||
4854 | 154 | auto printer = QSharedPointer<Printer>(new Printer(backend)); | ||
4855 | 155 | m_backend->mockPrinterLoaded(printer); | ||
4856 | 156 | // m_printers->m_printers << printer; | ||
4857 | 157 | |||
4858 | 158 | auto jobA = QSharedPointer<PrinterJob>(new PrinterJob("a-printer", backend, 1)); | ||
4859 | 159 | jobA->setPrinter(printer); | ||
4860 | 160 | jobA->loadDefaults(); | ||
4861 | 161 | jobA->setColorModel(models.indexOf(a)); | ||
4862 | 162 | |||
4863 | 163 | auto jobB = QSharedPointer<PrinterJob>(new PrinterJob("a-printer", backend, 2)); | ||
4864 | 164 | jobB->setPrinter(printer); | ||
4865 | 165 | jobB->loadDefaults(); | ||
4866 | 166 | jobB->setColorModel(models.indexOf(b)); | ||
4867 | 167 | |||
4868 | 168 | m_backend->m_jobs << jobA << jobB; | ||
4869 | 169 | m_backend->mockJobCreated("", "", "a-printer", 1, "", true, 1, 1, "", "", 1); | ||
4870 | 170 | m_backend->mockJobCreated("", "", "a-printer", 1, "", true, 2, 1, "", "", 1); | ||
4871 | 171 | |||
4872 | 172 | QTRY_COMPARE(m_model->count(), 2); | ||
4873 | 173 | QCOMPARE(m_model->data(m_model->index(0), JobModel::ColorModelRole).toString(), | ||
4874 | 174 | a.text); | ||
4875 | 175 | QCOMPARE(m_model->data(m_model->index(1), JobModel::ColorModelRole).toString(), | ||
4876 | 176 | b.name); | ||
4877 | 177 | } | ||
4878 | 178 | void testCompletedTimeRole() | ||
4879 | 179 | { | ||
4880 | 180 | QDateTime dateTimeA = QDateTime::currentDateTime(); | ||
4881 | 181 | QDateTime dateTimeB = QDateTime::currentDateTime().addSecs(100); | ||
4882 | 182 | |||
4883 | 183 | auto jobA = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", m_backend, 1)); | ||
4884 | 184 | jobA->setCompletedTime(dateTimeA); | ||
4885 | 185 | |||
4886 | 186 | auto jobB = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", m_backend, 2)); | ||
4887 | 187 | jobB->setCompletedTime(dateTimeB); | ||
4888 | 188 | |||
4889 | 189 | m_backend->m_jobs << jobA << jobB; | ||
4890 | 190 | m_backend->mockJobCreated("", "", "test-printer", 1, "", true, 1, 1, "", "", 1); | ||
4891 | 191 | m_backend->mockJobCreated("", "", "test-printer", 1, "", true, 2, 1, "", "", 1); | ||
4892 | 192 | |||
4893 | 193 | QTRY_COMPARE(m_model->count(), 2); | ||
4894 | 194 | QCOMPARE(m_model->data(m_model->index(0), JobModel::CompletedTimeRole).toDateTime(), | ||
4895 | 195 | dateTimeA); | ||
4896 | 196 | QCOMPARE(m_model->data(m_model->index(1), JobModel::CompletedTimeRole).toDateTime(), | ||
4897 | 197 | dateTimeB); | ||
4898 | 198 | } | ||
4899 | 199 | void testCopiesRole() | ||
4900 | 200 | { | ||
4901 | 201 | auto jobA = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", m_backend, 1)); | ||
4902 | 202 | jobA->setCopies(2); | ||
4903 | 203 | |||
4904 | 204 | auto jobB = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", m_backend, 2)); | ||
4905 | 205 | jobB->setCopies(5); | ||
4906 | 206 | |||
4907 | 207 | m_backend->m_jobs << jobA << jobB; | ||
4908 | 208 | m_backend->mockJobCreated("", "", "test-printer", 1, "", true, 1, 1, "", "", 1); | ||
4909 | 209 | m_backend->mockJobCreated("", "", "test-printer", 1, "", true, 2, 1, "", "", 1); | ||
4910 | 210 | |||
4911 | 211 | QTRY_COMPARE(m_model->count(), 2); | ||
4912 | 212 | QCOMPARE(m_model->data(m_model->index(0), JobModel::CopiesRole).toInt(), 2); | ||
4913 | 213 | QCOMPARE(m_model->data(m_model->index(1), JobModel::CopiesRole).toInt(), 5); | ||
4914 | 214 | } | ||
4915 | 215 | void testCreationTimeRole() | ||
4916 | 216 | { | ||
4917 | 217 | QDateTime dateTimeA = QDateTime::currentDateTime(); | ||
4918 | 218 | QDateTime dateTimeB = QDateTime::currentDateTime().addSecs(100); | ||
4919 | 219 | |||
4920 | 220 | auto jobA = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", m_backend, 1)); | ||
4921 | 221 | jobA->setCreationTime(dateTimeA); | ||
4922 | 222 | |||
4923 | 223 | auto jobB = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", m_backend, 2)); | ||
4924 | 224 | jobB->setCreationTime(dateTimeB); | ||
4925 | 225 | |||
4926 | 226 | m_backend->m_jobs << jobA << jobB; | ||
4927 | 227 | m_backend->mockJobCreated("", "", "test-printer", 1, "", true, 1, 1, "", "", 1); | ||
4928 | 228 | m_backend->mockJobCreated("", "", "test-printer", 1, "", true, 2, 1, "", "", 1); | ||
4929 | 229 | |||
4930 | 230 | QTRY_COMPARE(m_model->count(), 2); | ||
4931 | 231 | QCOMPARE(m_model->data(m_model->index(0), JobModel::CreationTimeRole).toDateTime(), | ||
4932 | 232 | dateTimeA); | ||
4933 | 233 | QCOMPARE(m_model->data(m_model->index(1), JobModel::CreationTimeRole).toDateTime(), | ||
4934 | 234 | dateTimeB); | ||
4935 | 235 | } | ||
4936 | 236 | void testDuplexRole() | ||
4937 | 237 | { | ||
4938 | 238 | // FIXME: read comment in JobModel::updateJob | ||
4939 | 239 | QSKIP("We are ignoring duplex for now as it requires a loaded Printer for the PrinterJob."); | ||
4940 | 240 | |||
4941 | 241 | QList<PrinterEnum::DuplexMode> modes({ | ||
4942 | 242 | PrinterEnum::DuplexMode::DuplexNone, | ||
4943 | 243 | PrinterEnum::DuplexMode::DuplexLongSide, | ||
4944 | 244 | PrinterEnum::DuplexMode::DuplexShortSide, | ||
4945 | 245 | }); | ||
4946 | 246 | |||
4947 | 247 | ((MockPrinterBackend*) m_backend)->m_supportedDuplexModes = modes; | ||
4948 | 248 | |||
4949 | 249 | PrinterBackend* backend = new MockPrinterBackend("test-printer"); | ||
4950 | 250 | ((MockPrinterBackend*) backend)->m_supportedDuplexModes = modes; | ||
4951 | 251 | |||
4952 | 252 | auto printer = QSharedPointer<Printer>(new Printer(backend)); | ||
4953 | 253 | m_backend->mockPrinterLoaded(printer); | ||
4954 | 254 | |||
4955 | 255 | auto jobA = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", backend, 1)); | ||
4956 | 256 | jobA->setPrinter(printer); | ||
4957 | 257 | jobA->setDuplexMode(modes.indexOf(PrinterEnum::DuplexMode::DuplexLongSide)); | ||
4958 | 258 | |||
4959 | 259 | auto jobB = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", backend, 2)); | ||
4960 | 260 | jobB->setPrinter(printer); | ||
4961 | 261 | jobB->setDuplexMode(modes.indexOf(PrinterEnum::DuplexMode::DuplexNone)); | ||
4962 | 262 | |||
4963 | 263 | m_backend->m_jobs << jobA << jobB; | ||
4964 | 264 | m_backend->mockJobCreated("", "", "test-printer", 1, "", true, 1, 1, "", "", 1); | ||
4965 | 265 | m_backend->mockJobCreated("", "", "test-printer", 1, "", true, 2, 1, "", "", 1); | ||
4966 | 266 | |||
4967 | 267 | QTRY_COMPARE(m_model->count(), 2); | ||
4968 | 268 | QCOMPARE(m_model->data(m_model->index(0), JobModel::DuplexRole).toString(), | ||
4969 | 269 | Utils::duplexModeToUIString(PrinterEnum::DuplexMode::DuplexLongSide)); | ||
4970 | 270 | QCOMPARE(m_model->data(m_model->index(1), JobModel::DuplexRole).toString(), | ||
4971 | 271 | Utils::duplexModeToUIString(PrinterEnum::DuplexMode::DuplexNone)); | ||
4972 | 272 | } | ||
4973 | 273 | void testHeldRole() | ||
4974 | 274 | { | ||
4975 | 275 | auto jobA = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", m_backend, 1)); | ||
4976 | 276 | jobA->setState(PrinterEnum::JobState::Pending); | ||
4977 | 277 | |||
4978 | 278 | auto jobB = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", m_backend, 2)); | ||
4979 | 279 | jobB->setState(PrinterEnum::JobState::Held); | ||
4980 | 280 | |||
4981 | 281 | m_backend->m_jobs << jobA << jobB; | ||
4982 | 282 | m_backend->mockJobCreated("", "", "test-printer", 1, "", true, 1, static_cast<uint>(jobA->state()), "", "", 1); | ||
4983 | 283 | m_backend->mockJobCreated("", "", "test-printer", 1, "", true, 2, static_cast<uint>(jobB->state()), "", "", 1); | ||
4984 | 284 | |||
4985 | 285 | QTRY_COMPARE(m_model->count(), 2); | ||
4986 | 286 | QCOMPARE(m_model->data(m_model->index(0), JobModel::HeldRole).toBool(), false); | ||
4987 | 287 | QCOMPARE(m_model->data(m_model->index(1), JobModel::HeldRole).toBool(), true); | ||
4988 | 288 | } | ||
4989 | 289 | void testImpressionsCompletedRole() | ||
4990 | 290 | { | ||
4991 | 291 | auto jobA = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", m_backend, 1)); | ||
4992 | 292 | jobA->setImpressionsCompleted(2); | ||
4993 | 293 | |||
4994 | 294 | auto jobB = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", m_backend, 2)); | ||
4995 | 295 | jobB->setImpressionsCompleted(5); | ||
4996 | 296 | |||
4997 | 297 | m_backend->m_jobs << jobA << jobB; | ||
4998 | 298 | m_backend->mockJobCreated("", "", "test-printer", 1, "", true, 1, 1, "", "", jobA->impressionsCompleted()); | ||
4999 | 299 | m_backend->mockJobCreated("", "", "test-printer", 1, "", true, 2, 1, "", "", jobB->impressionsCompleted()); | ||
5000 | 300 |
I approve all the changes made by Andrew, which is this whole branch minus my own changes.