Merge lp:~ahayzen/ubuntu-settings-components/add-job-model into lp:~phablet-team/ubuntu-settings-components/printer-components
- add-job-model
- Merge into printer-components
Proposed by
Andrew Hayzen
Status: | Merged |
---|---|
Approved by: | Jonas G. Drange |
Approved revision: | 227 |
Merged at revision: | 224 |
Proposed branch: | lp:~ahayzen/ubuntu-settings-components/add-job-model |
Merge into: | lp:~phablet-team/ubuntu-settings-components/printer-components |
Prerequisite: | lp:~ahayzen/ubuntu-settings-components/add-cancel-method |
Diff against target: |
823 lines (+527/-12) 16 files modified
examples/PrinterQueue.qml (+113/-0) plugins/Ubuntu/Settings/Printers/CMakeLists.txt (+1/-0) plugins/Ubuntu/Settings/Printers/backend/backend.cpp (+7/-0) plugins/Ubuntu/Settings/Printers/backend/backend.h (+1/-0) plugins/Ubuntu/Settings/Printers/backend/backend_cups.cpp (+17/-0) plugins/Ubuntu/Settings/Printers/backend/backend_cups.h (+1/-0) plugins/Ubuntu/Settings/Printers/cups/cupsfacade.cpp (+18/-0) plugins/Ubuntu/Settings/Printers/cups/cupsfacade.h (+1/-0) plugins/Ubuntu/Settings/Printers/enums.h (+13/-0) plugins/Ubuntu/Settings/Printers/models/jobmodel.cpp (+222/-0) plugins/Ubuntu/Settings/Printers/models/jobmodel.h (+75/-0) plugins/Ubuntu/Settings/Printers/models/printermodel.cpp (+17/-0) plugins/Ubuntu/Settings/Printers/models/printermodel.h (+3/-0) plugins/Ubuntu/Settings/Printers/printer/printerjob.cpp (+24/-8) plugins/Ubuntu/Settings/Printers/printer/printerjob.h (+9/-4) tests/unittests/Printers/mockbackend.h (+5/-0) |
To merge this branch: | bzr merge lp:~ahayzen/ubuntu-settings-components/add-job-model |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jonas G. Drange (community) | Approve | ||
Review via email: mp+316242@code.launchpad.net |
Commit message
* Add JobModel which lists the jobs for a certain printer
* Add JobRole to PrinterModel to access jobs
* Add JobState enum to track enums from cups
* Add example Queue which lists jobs for a printer with their name, id, status and allows you to cancel the job by clicking
Description of the change
* Add JobModel which lists the jobs for a certain printer
* Add JobRole to PrinterModel to access jobs
* Add JobState enum to track enums from cups
* Add example Queue which lists jobs for a printer with their name, id, status and allows you to cancel the job by clicking
To post a comment you must log in.
- 226. By Andrew Hayzen
-
* Remove some tracing
- 227. By Andrew Hayzen
-
* Use QSharedPointer instead of raw pointers for PrinterJob
* Renamed Queue.qml to PrinterQueue.qml
Revision history for this message
Jonas G. Drange (jonas-drange) wrote : | # |
THX! LGTM
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file 'examples/PrinterQueue.qml' |
2 | --- examples/PrinterQueue.qml 1970-01-01 00:00:00 +0000 |
3 | +++ examples/PrinterQueue.qml 2017-02-02 17:23:30 +0000 |
4 | @@ -0,0 +1,113 @@ |
5 | +/* |
6 | + * Copyright 2017 Canonical Ltd. |
7 | + * |
8 | + * This program is free software; you can redistribute it and/or modify |
9 | + * it under the terms of the GNU Lesser General Public License as published by |
10 | + * the Free Software Foundation; version 3. |
11 | + * |
12 | + * This program is distributed in the hope that it will be useful, |
13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | + * GNU Lesser General Public License for more details. |
16 | + * |
17 | + * You should have received a copy of the GNU Lesser General Public License |
18 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | + * |
20 | + * Authored by Jonas G. Drange <jonas.drange@canonical.com> |
21 | + * Andrew Hayzen <andrew.hayzen@canonical.com> |
22 | + */ |
23 | + |
24 | +import QtQuick 2.4 |
25 | +import QtQuick.Layouts 1.1 |
26 | +import Ubuntu.Components 1.3 |
27 | +import Ubuntu.Components.ListItems 1.3 as ListItems |
28 | +import Ubuntu.Settings.Components 0.1 |
29 | +import Ubuntu.Settings.Printers 0.1 |
30 | + |
31 | +MainView { |
32 | + width: units.gu(50) |
33 | + height: units.gu(90) |
34 | + |
35 | + Component { |
36 | + id: queuePage |
37 | + |
38 | + Page { |
39 | + header: PageHeader { |
40 | + title: "Queue: " + printer.name |
41 | + flickable: queueView |
42 | + } |
43 | + visible: false |
44 | + |
45 | + property var printer |
46 | + |
47 | + ListView { |
48 | + id: queueView |
49 | + anchors { |
50 | + fill: parent |
51 | + } |
52 | + delegate: ListItem { |
53 | + height: modelLayout.height + (divider.visible ? divider.height : 0) |
54 | + ListItemLayout { |
55 | + id: modelLayout |
56 | + title.text: displayName |
57 | + subtitle.text: "Job: " + model.id + " State: " + model.state |
58 | + } |
59 | + onClicked: { |
60 | + console.debug("Cancel:", printer.name, model.id); |
61 | + Printers.cancelJob(printer.name, model.id); |
62 | + } |
63 | + } |
64 | + model: printer.jobs |
65 | + |
66 | + Label { |
67 | + anchors { |
68 | + centerIn: parent |
69 | + } |
70 | + text: "Empty queue" |
71 | + visible: queueView.count === 0 |
72 | + } |
73 | + } |
74 | + } |
75 | + } |
76 | + |
77 | + PageStack { |
78 | + id: pageStack |
79 | + |
80 | + Page { |
81 | + id: printersPage |
82 | + header: PageHeader { |
83 | + title: "Printers" |
84 | + flickable: printerList |
85 | + } |
86 | + visible: false |
87 | + |
88 | + ListView { |
89 | + id: printerList |
90 | + anchors { fill: parent } |
91 | + model: Printers.allPrintersWithPdf |
92 | + delegate: ListItem { |
93 | + height: modelLayout.height + (divider.visible ? divider.height : 0) |
94 | + ListItemLayout { |
95 | + id: modelLayout |
96 | + title.text: displayName |
97 | + title.font.bold: model.default |
98 | + subtitle.text: description |
99 | + |
100 | + Icon { |
101 | + id: icon |
102 | + width: height |
103 | + height: units.gu(2.5) |
104 | + name: "printer-symbolic" |
105 | + SlotsLayout.position: SlotsLayout.First |
106 | + } |
107 | + |
108 | + ProgressionSlot {} |
109 | + } |
110 | + onClicked: pageStack.push(queuePage, { printer: model }) |
111 | + } |
112 | + } |
113 | + } |
114 | + |
115 | + Component.onCompleted: push(printersPage) |
116 | + } |
117 | +} |
118 | |
119 | === modified file 'plugins/Ubuntu/Settings/Printers/CMakeLists.txt' |
120 | --- plugins/Ubuntu/Settings/Printers/CMakeLists.txt 2017-01-26 21:47:06 +0000 |
121 | +++ plugins/Ubuntu/Settings/Printers/CMakeLists.txt 2017-02-02 17:23:30 +0000 |
122 | @@ -18,6 +18,7 @@ |
123 | enums.h |
124 | i18n.cpp |
125 | models/drivermodel.cpp |
126 | + models/jobmodel.cpp |
127 | models/printermodel.cpp |
128 | printer/printer.cpp |
129 | printer/printerjob.cpp |
130 | |
131 | === modified file 'plugins/Ubuntu/Settings/Printers/backend/backend.cpp' |
132 | --- plugins/Ubuntu/Settings/Printers/backend/backend.cpp 2017-02-02 17:23:30 +0000 |
133 | +++ plugins/Ubuntu/Settings/Printers/backend/backend.cpp 2017-02-02 17:23:30 +0000 |
134 | @@ -202,6 +202,13 @@ |
135 | return -1; |
136 | } |
137 | |
138 | +QList<QSharedPointer<PrinterJob>> PrinterBackend::printerGetJobs(const QString &name) |
139 | +{ |
140 | + Q_UNUSED(name); |
141 | + |
142 | + return QList<QSharedPointer<PrinterJob>>{}; |
143 | +} |
144 | + |
145 | QString PrinterBackend::printerName() const |
146 | { |
147 | return QString(); |
148 | |
149 | === modified file 'plugins/Ubuntu/Settings/Printers/backend/backend.h' |
150 | --- plugins/Ubuntu/Settings/Printers/backend/backend.h 2017-02-02 17:23:30 +0000 |
151 | +++ plugins/Ubuntu/Settings/Printers/backend/backend.h 2017-02-02 17:23:30 +0000 |
152 | @@ -118,6 +118,7 @@ |
153 | virtual int printFileToDest(const QString &filepath, |
154 | const QString &title, |
155 | const cups_dest_t *dest); |
156 | + virtual QList<QSharedPointer<PrinterJob>> printerGetJobs(const QString &name); |
157 | |
158 | virtual QString printerName() const; |
159 | virtual QString description() const; |
160 | |
161 | === modified file 'plugins/Ubuntu/Settings/Printers/backend/backend_cups.cpp' |
162 | --- plugins/Ubuntu/Settings/Printers/backend/backend_cups.cpp 2017-02-02 17:23:30 +0000 |
163 | +++ plugins/Ubuntu/Settings/Printers/backend/backend_cups.cpp 2017-02-02 17:23:30 +0000 |
164 | @@ -210,6 +210,23 @@ |
165 | return m_cups->printFileToDest(filepath, title, dest); |
166 | } |
167 | |
168 | +QList<QSharedPointer<PrinterJob>> PrinterCupsBackend::printerGetJobs(const QString &name) |
169 | +{ |
170 | + auto jobs = m_cups->printerGetJobs(name); |
171 | + QList<QSharedPointer<PrinterJob>> list; |
172 | + |
173 | + Q_FOREACH(auto job, jobs) { |
174 | + auto newJob = QSharedPointer<PrinterJob>(new PrinterJob(name, this, job->id)); |
175 | + |
176 | + newJob->setState(static_cast<PrinterEnum::JobState>(job->state)); |
177 | + newJob->setTitle(QString::fromLocal8Bit(job->title)); |
178 | + |
179 | + list.append(newJob); |
180 | + } |
181 | + |
182 | + return list; |
183 | +} |
184 | + |
185 | QString PrinterCupsBackend::printerName() const |
186 | { |
187 | return m_info.printerName(); |
188 | |
189 | === modified file 'plugins/Ubuntu/Settings/Printers/backend/backend_cups.h' |
190 | --- plugins/Ubuntu/Settings/Printers/backend/backend_cups.h 2017-02-02 17:23:30 +0000 |
191 | +++ plugins/Ubuntu/Settings/Printers/backend/backend_cups.h 2017-02-02 17:23:30 +0000 |
192 | @@ -97,6 +97,7 @@ |
193 | virtual int printFileToDest(const QString &filepath, |
194 | const QString &title, |
195 | const cups_dest_t *dest) override; |
196 | + virtual QList<QSharedPointer<PrinterJob>> printerGetJobs(const QString &name) override; |
197 | |
198 | virtual QString printerName() const override; |
199 | virtual QString description() const override; |
200 | |
201 | === modified file 'plugins/Ubuntu/Settings/Printers/cups/cupsfacade.cpp' |
202 | --- plugins/Ubuntu/Settings/Printers/cups/cupsfacade.cpp 2017-02-02 17:23:30 +0000 |
203 | +++ plugins/Ubuntu/Settings/Printers/cups/cupsfacade.cpp 2017-02-02 17:23:30 +0000 |
204 | @@ -376,6 +376,24 @@ |
205 | } |
206 | } |
207 | |
208 | +QList<cups_job_t *> CupsFacade::printerGetJobs(const QString &name) |
209 | +{ |
210 | + QList<cups_job_t *> list; |
211 | + cups_job_t *jobs; |
212 | + |
213 | + // Get a list of the jobs that are 'mine' and only active ones |
214 | + // https://www.cups.org/doc/api-cups.html#cupsGetJobs |
215 | + int count = cupsGetJobs(&jobs, name.toLocal8Bit(), 1, CUPS_WHICHJOBS_ACTIVE); |
216 | + |
217 | + for (int i=0; i < count; i++) { |
218 | + list.append(&jobs[i]); |
219 | + } |
220 | + |
221 | + // FIXME: needs to run cupsFreeJobs(); |
222 | + |
223 | + return list; |
224 | +} |
225 | + |
226 | int CupsFacade::printFileToDest(const QString &filepath, const QString &title, |
227 | const cups_dest_t *dest) |
228 | { |
229 | |
230 | === modified file 'plugins/Ubuntu/Settings/Printers/cups/cupsfacade.h' |
231 | --- plugins/Ubuntu/Settings/Printers/cups/cupsfacade.h 2017-02-02 17:23:30 +0000 |
232 | +++ plugins/Ubuntu/Settings/Printers/cups/cupsfacade.h 2017-02-02 17:23:30 +0000 |
233 | @@ -89,6 +89,7 @@ |
234 | QList<PrintQuality> printerGetSupportedQualities(const QString &name) const; |
235 | |
236 | void cancelJob(const QString &name, const int jobId); |
237 | + QList<cups_job_t *> printerGetJobs(const QString &name); |
238 | int printFileToDest(const QString &filepath, const QString &title, |
239 | const cups_dest_t *dest); |
240 | |
241 | |
242 | === modified file 'plugins/Ubuntu/Settings/Printers/enums.h' |
243 | --- plugins/Ubuntu/Settings/Printers/enums.h 2017-01-19 21:00:28 +0000 |
244 | +++ plugins/Ubuntu/Settings/Printers/enums.h 2017-02-02 17:23:30 +0000 |
245 | @@ -93,6 +93,19 @@ |
246 | }; |
247 | Q_ENUM(ErrorPolicy) |
248 | |
249 | + // Match enums from ipp_jstate_t |
250 | + enum class JobState |
251 | + { |
252 | + Pending = 3, |
253 | + Held, |
254 | + Processing, |
255 | + Stopped, |
256 | + Canceled, |
257 | + Aborted, |
258 | + Complete, |
259 | + }; |
260 | + Q_ENUM(JobState) |
261 | + |
262 | enum class OperationPolicy |
263 | { |
264 | DefaultOperation = 0, |
265 | |
266 | === added file 'plugins/Ubuntu/Settings/Printers/models/jobmodel.cpp' |
267 | --- plugins/Ubuntu/Settings/Printers/models/jobmodel.cpp 1970-01-01 00:00:00 +0000 |
268 | +++ plugins/Ubuntu/Settings/Printers/models/jobmodel.cpp 2017-02-02 17:23:30 +0000 |
269 | @@ -0,0 +1,222 @@ |
270 | +/* |
271 | + * Copyright (C) 2017 Canonical, Ltd. |
272 | + * |
273 | + * This program is free software; you can redistribute it and/or modify |
274 | + * it under the terms of the GNU Lesser General Public License as published by |
275 | + * the Free Software Foundation; version 3. |
276 | + * |
277 | + * This program is distributed in the hope that it will be useful, |
278 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
279 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
280 | + * GNU Lesser General Public License for more details. |
281 | + * |
282 | + * You should have received a copy of the GNU Lesser General Public License |
283 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
284 | + */ |
285 | + |
286 | +#include "utils.h" |
287 | + |
288 | +#include "backend/backend_cups.h" |
289 | +#include "cups/cupsfacade.h" |
290 | + |
291 | +#include "models/jobmodel.h" |
292 | + |
293 | +#include <QDebug> |
294 | + |
295 | +JobModel::JobModel(const int updateIntervalMSecs, QObject *parent) |
296 | + : JobModel(QStringLiteral(""), new PrinterCupsBackend, updateIntervalMSecs, parent) |
297 | +{ |
298 | +} |
299 | + |
300 | +JobModel::JobModel(const QString &printerName, PrinterBackend *backend, |
301 | + const int updateIntervalMSecs, |
302 | + QObject *parent) |
303 | + : QAbstractListModel(parent) |
304 | + , m_backend(backend) |
305 | + , m_printer_name(printerName) |
306 | +{ |
307 | + update(); |
308 | + startUpdateTimer(updateIntervalMSecs); |
309 | +} |
310 | + |
311 | +JobModel::~JobModel() |
312 | +{ |
313 | +} |
314 | + |
315 | +void JobModel::startUpdateTimer(const int &msecs) |
316 | +{ |
317 | + // Start a timer to poll for changes in the printers |
318 | + m_update_timer.setParent(this); |
319 | + connect(&m_update_timer, SIGNAL(timeout()), this, SLOT(update())); |
320 | + m_update_timer.start(msecs); |
321 | +} |
322 | + |
323 | +void JobModel::update() |
324 | +{ |
325 | + // Store the old count and get the new printers |
326 | + int oldCount = m_jobs.size(); |
327 | + QList<QSharedPointer<PrinterJob>> newJobs = m_backend->printerGetJobs(m_printer_name); |
328 | + |
329 | + /* If any printers returned from the backend are irrelevant, we delete |
330 | + them. This a list of indices that corresponds to printers scheduled for |
331 | + deletion in newPrinters. */ |
332 | + QList<uint> forDeletion; |
333 | + |
334 | + // Go through the old model |
335 | + for (int i=0; i < m_jobs.count(); i++) { |
336 | + // Determine if the old printer exists in the new model |
337 | + bool exists = false; |
338 | + |
339 | + Q_FOREACH(QSharedPointer<PrinterJob> p, newJobs) { |
340 | + // TODO: update status here |
341 | + if (p->jobId() == m_jobs.at(i)->jobId()) { |
342 | + exists = true; |
343 | + break; |
344 | + } |
345 | + } |
346 | + |
347 | + // If it doesn't exist then remove it from the old model |
348 | + if (!exists) { |
349 | + beginRemoveRows(QModelIndex(), i, i); |
350 | + QSharedPointer<PrinterJob> p = m_jobs.takeAt(i); |
351 | + p->deleteLater(); |
352 | + endRemoveRows(); |
353 | + |
354 | + i--; // as we have removed an item decrement |
355 | + } |
356 | + } |
357 | + |
358 | + // Go through the new model |
359 | + for (int i=0; i < newJobs.count(); i++) { |
360 | + // Determine if the new printer exists in the old model |
361 | + bool exists = false; |
362 | + int j; |
363 | + |
364 | + for (j=0; j < m_jobs.count(); j++) { |
365 | + if (m_jobs.at(j)->jobId() == newJobs.at(i)->jobId()) { |
366 | + exists = true; |
367 | + forDeletion << i; |
368 | + break; |
369 | + } |
370 | + } |
371 | + |
372 | + if (exists) { |
373 | + if (j == i) { // New printer exists and in correct position |
374 | + continue; |
375 | + } else { |
376 | + // New printer does exist but needs to be moved in old model |
377 | + beginMoveRows(QModelIndex(), j, 1, QModelIndex(), i); |
378 | + m_jobs.move(j, i); |
379 | + endMoveRows(); |
380 | + } |
381 | + |
382 | + // We can safely delete the newPrinter as it already exists. |
383 | + forDeletion << i; |
384 | + } else { |
385 | + // New printer does not exist insert into model |
386 | + beginInsertRows(QModelIndex(), i, i); |
387 | + m_jobs.insert(i, newJobs.at(i)); |
388 | + endInsertRows(); |
389 | + } |
390 | + } |
391 | + |
392 | + Q_FOREACH(const int &index, forDeletion) { |
393 | + newJobs.at(index)->deleteLater(); |
394 | + } |
395 | + |
396 | + if (oldCount != m_jobs.size()) { |
397 | + Q_EMIT countChanged(); |
398 | + } |
399 | +} |
400 | + |
401 | +int JobModel::rowCount(const QModelIndex &parent) const |
402 | +{ |
403 | + Q_UNUSED(parent); |
404 | + return m_jobs.size(); |
405 | +} |
406 | + |
407 | +int JobModel::count() const |
408 | +{ |
409 | + return rowCount(); |
410 | +} |
411 | + |
412 | +QVariant JobModel::data(const QModelIndex &index, int role) const |
413 | +{ |
414 | + QVariant ret; |
415 | + |
416 | + if ((0<=index.row()) && (index.row()<m_jobs.size())) { |
417 | + |
418 | + auto job = m_jobs[index.row()]; |
419 | + |
420 | + switch (role) { |
421 | + case IdRole: |
422 | + ret = job->jobId(); |
423 | + break; |
424 | + case OwnerRole: |
425 | + ret = m_printer_name; |
426 | + break; |
427 | + case StateRole: |
428 | + // TODO: improve, for now have a switch |
429 | + switch (job->state()) { |
430 | + case PrinterEnum::JobState::Aborted: |
431 | + ret = "Aborted"; |
432 | + break; |
433 | + case PrinterEnum::JobState::Canceled: |
434 | + ret = "Canceled"; |
435 | + break; |
436 | + case PrinterEnum::JobState::Complete: |
437 | + ret = "Compelete"; |
438 | + break; |
439 | + case PrinterEnum::JobState::Held: |
440 | + ret = "Held"; |
441 | + break; |
442 | + case PrinterEnum::JobState::Pending: |
443 | + ret = "Pending"; |
444 | + break; |
445 | + case PrinterEnum::JobState::Processing: |
446 | + ret = "Processing"; |
447 | + break; |
448 | + case PrinterEnum::JobState::Stopped: |
449 | + ret = "Stopped"; |
450 | + break; |
451 | + } |
452 | + break; |
453 | + case Qt::DisplayRole: |
454 | + case TitleRole: |
455 | + ret = job->title(); |
456 | + break; |
457 | + } |
458 | + } |
459 | + |
460 | + return ret; |
461 | +} |
462 | + |
463 | +QHash<int, QByteArray> JobModel::roleNames() const |
464 | +{ |
465 | + static QHash<int,QByteArray> names; |
466 | + |
467 | + if (Q_UNLIKELY(names.empty())) { |
468 | + names[Qt::DisplayRole] = "displayName"; |
469 | + names[IdRole] = "id"; |
470 | + names[OwnerRole] = "owner"; |
471 | + names[StateRole] = "state"; |
472 | + names[TitleRole] = "title"; |
473 | + names[LastStateMessageRole] = "lastStateMessage"; |
474 | + } |
475 | + |
476 | + return names; |
477 | +} |
478 | + |
479 | +QVariantMap JobModel::get(const int row) const |
480 | +{ |
481 | + QHashIterator<int, QByteArray> iterator(roleNames()); |
482 | + QVariantMap result; |
483 | + QModelIndex modelIndex = index(row, 0); |
484 | + |
485 | + while (iterator.hasNext()) { |
486 | + iterator.next(); |
487 | + result[iterator.value()] = modelIndex.data(iterator.key()); |
488 | + } |
489 | + |
490 | + return result; |
491 | +} |
492 | |
493 | === added file 'plugins/Ubuntu/Settings/Printers/models/jobmodel.h' |
494 | --- plugins/Ubuntu/Settings/Printers/models/jobmodel.h 1970-01-01 00:00:00 +0000 |
495 | +++ plugins/Ubuntu/Settings/Printers/models/jobmodel.h 2017-02-02 17:23:30 +0000 |
496 | @@ -0,0 +1,75 @@ |
497 | +/* |
498 | + * Copyright (C) 2017 Canonical, Ltd. |
499 | + * |
500 | + * This program is free software; you can redistribute it and/or modify |
501 | + * it under the terms of the GNU Lesser General Public License as published by |
502 | + * the Free Software Foundation; version 3. |
503 | + * |
504 | + * This program is distributed in the hope that it will be useful, |
505 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
506 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
507 | + * GNU Lesser General Public License for more details. |
508 | + * |
509 | + * You should have received a copy of the GNU Lesser General Public License |
510 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
511 | + */ |
512 | + |
513 | +#ifndef USC_JOB_MODEL_H |
514 | +#define USC_JOB_MODEL_H |
515 | + |
516 | +#include "printers_global.h" |
517 | + |
518 | +#include "printer/printer.h" |
519 | + |
520 | +#include <QAbstractListModel> |
521 | +#include <QByteArray> |
522 | +#include <QModelIndex> |
523 | +#include <QObject> |
524 | +#include <QSortFilterProxyModel> |
525 | +#include <QTimer> |
526 | +#include <QVariant> |
527 | + |
528 | +class PRINTERS_DECL_EXPORT JobModel : public QAbstractListModel |
529 | +{ |
530 | + Q_OBJECT |
531 | + |
532 | + Q_PROPERTY(int count READ count NOTIFY countChanged) |
533 | +public: |
534 | + explicit JobModel(const int updateIntervalMSecs=5000, QObject *parent = Q_NULLPTR); |
535 | + explicit JobModel(const QString &printerName, PrinterBackend *backend, const int updateIntervalMSecs=5000, |
536 | + QObject *parent = Q_NULLPTR); |
537 | + ~JobModel(); |
538 | + |
539 | + enum Roles |
540 | + { |
541 | + // Qt::DisplayRole holds job title |
542 | + IdRole = Qt::UserRole, |
543 | + OwnerRole, |
544 | + StateRole, |
545 | + TitleRole, |
546 | + LastStateMessageRole, |
547 | + LastRole = LastStateMessageRole, |
548 | + }; |
549 | + |
550 | + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; |
551 | + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; |
552 | + virtual QHash<int, QByteArray> roleNames() const override; |
553 | + |
554 | + int count() const; |
555 | + |
556 | + Q_INVOKABLE QVariantMap get(const int row) const; |
557 | +private: |
558 | + QTimer m_update_timer; |
559 | + PrinterBackend *m_backend; |
560 | + QString m_printer_name; |
561 | + |
562 | + QList<QSharedPointer<PrinterJob>> m_jobs; |
563 | +private Q_SLOTS: |
564 | + void startUpdateTimer(const int &msecs); |
565 | + void update(); |
566 | + |
567 | +Q_SIGNALS: |
568 | + void countChanged(); |
569 | +}; |
570 | + |
571 | +#endif // USC_JOB_MODEL_H |
572 | |
573 | === modified file 'plugins/Ubuntu/Settings/Printers/models/printermodel.cpp' |
574 | --- plugins/Ubuntu/Settings/Printers/models/printermodel.cpp 2017-01-22 19:31:39 +0000 |
575 | +++ plugins/Ubuntu/Settings/Printers/models/printermodel.cpp 2017-02-02 17:23:30 +0000 |
576 | @@ -18,9 +18,11 @@ |
577 | |
578 | #include "backend/backend_cups.h" |
579 | #include "cups/cupsfacade.h" |
580 | +#include "models/jobmodel.h" |
581 | #include "models/printermodel.h" |
582 | |
583 | #include <QDebug> |
584 | +#include <QQmlEngine> |
585 | |
586 | PrinterModel::PrinterModel(const int updateIntervalMSecs, QObject *parent) |
587 | : PrinterModel(new PrinterCupsBackend, updateIntervalMSecs, parent) |
588 | @@ -76,7 +78,11 @@ |
589 | if (!exists) { |
590 | beginRemoveRows(QModelIndex(), i, i); |
591 | Printer *p = m_printers.takeAt(i); |
592 | + JobModel *jobModel = m_job_models.take(p->name()); |
593 | + |
594 | p->deleteLater(); |
595 | + jobModel->deleteLater(); |
596 | + |
597 | endRemoveRows(); |
598 | |
599 | i--; // as we have removed an item decrement |
600 | @@ -112,7 +118,13 @@ |
601 | } else { |
602 | // New printer does not exist insert into model |
603 | beginInsertRows(QModelIndex(), i, i); |
604 | + |
605 | m_printers.insert(i, newPrinters.at(i)); |
606 | + |
607 | + JobModel *model = new JobModel(newPrinters.at(i)->name(), m_backend, 5000, this); |
608 | + QQmlEngine::setObjectOwnership(model, QQmlEngine::CppOwnership); |
609 | + m_job_models.insert(newPrinters.at(i)->name(), model); |
610 | + |
611 | endInsertRows(); |
612 | } |
613 | } |
614 | @@ -226,6 +238,10 @@ |
615 | case IsPdfRole: |
616 | ret = printer->isPdf(); |
617 | break; |
618 | + case JobRole: { |
619 | + ret = QVariant::fromValue(m_job_models.value(printer->name())); |
620 | + break; |
621 | + } |
622 | // case LastStateMessageRole: |
623 | // ret = printer->lastStateMessage(); |
624 | // break; |
625 | @@ -311,6 +327,7 @@ |
626 | names[StateRole] = "state"; |
627 | names[PrinterRole] = "printer"; |
628 | names[IsPdfRole] = "isPdf"; |
629 | + names[JobRole] = "jobs"; |
630 | names[LastStateMessageRole] = "lastStateMessage"; |
631 | } |
632 | |
633 | |
634 | === modified file 'plugins/Ubuntu/Settings/Printers/models/printermodel.h' |
635 | --- plugins/Ubuntu/Settings/Printers/models/printermodel.h 2017-01-22 14:21:11 +0000 |
636 | +++ plugins/Ubuntu/Settings/Printers/models/printermodel.h 2017-02-02 17:23:30 +0000 |
637 | @@ -19,6 +19,7 @@ |
638 | |
639 | #include "printers_global.h" |
640 | |
641 | +#include "models/jobmodel.h" |
642 | #include "printer/printer.h" |
643 | |
644 | #include <QAbstractListModel> |
645 | @@ -64,6 +65,7 @@ |
646 | PrinterRole, |
647 | LastStateMessageRole, |
648 | IsPdfRole, |
649 | + JobRole, |
650 | LastRole = LastStateMessageRole, |
651 | }; |
652 | |
653 | @@ -84,6 +86,7 @@ |
654 | /* FIXME: there's currently no need to share the Printer obj with QML, so |
655 | this should be normal pointers that are deletedLater. */ |
656 | QList<Printer*> m_printers; |
657 | + QMap<QString, JobModel *> m_job_models; |
658 | |
659 | private Q_SLOTS: |
660 | void startUpdateTimer(const int &msecs); |
661 | |
662 | === modified file 'plugins/Ubuntu/Settings/Printers/printer/printerjob.cpp' |
663 | --- plugins/Ubuntu/Settings/Printers/printer/printerjob.cpp 2017-02-02 17:23:30 +0000 |
664 | +++ plugins/Ubuntu/Settings/Printers/printer/printerjob.cpp 2017-02-02 17:23:30 +0000 |
665 | @@ -40,18 +40,33 @@ |
666 | , m_backend(backend) |
667 | , m_duplex_mode(0) |
668 | , m_is_two_sided(false) |
669 | + , m_job_id(-1) |
670 | , m_printer(printer) |
671 | , m_printer_name(QStringLiteral("")) |
672 | , m_print_range(QStringLiteral("")) |
673 | , m_print_range_mode(PrinterEnum::PrintRange::AllPages) |
674 | , m_quality(0) |
675 | - , m_state(PrinterEnum::State::IdleState) |
676 | + , m_state(PrinterEnum::JobState::Pending) |
677 | , m_reverse(false) |
678 | , m_title(QStringLiteral("")) |
679 | { |
680 | + if (m_printer) { |
681 | + m_printer_name = printer->name(); |
682 | + } |
683 | + |
684 | loadDefaults(); |
685 | } |
686 | |
687 | +PrinterJob::PrinterJob(const QString &name, PrinterBackend *backend, int jobId, QObject *parent) |
688 | + : QObject(parent) |
689 | + , m_backend(backend) |
690 | + , m_job_id(jobId) |
691 | +{ |
692 | + setPrinterName(name); |
693 | + |
694 | + // TODO: load other options from job |
695 | +} |
696 | + |
697 | |
698 | PrinterJob::~PrinterJob() |
699 | { |
700 | @@ -115,6 +130,11 @@ |
701 | return m_is_two_sided; |
702 | } |
703 | |
704 | +int PrinterJob::jobId() const |
705 | +{ |
706 | + return m_job_id; |
707 | +} |
708 | + |
709 | bool PrinterJob::landscape() const |
710 | { |
711 | return m_landscape; |
712 | @@ -143,11 +163,7 @@ |
713 | void PrinterJob::printFile(const QUrl &url) |
714 | { |
715 | if (m_printer) { |
716 | - int jobId = m_printer->printFile(url.toLocalFile(), this); |
717 | - |
718 | - // TODO: should we track the job and state of it here? |
719 | - // so then we can do cancel() and show in the UI when the job is done? |
720 | - Q_UNUSED(jobId); |
721 | + m_job_id = m_printer->printFile(url.toLocalFile(), this); |
722 | } else { |
723 | qWarning() << "No valid printer in PrinterJob"; |
724 | } |
725 | @@ -173,7 +189,7 @@ |
726 | return m_reverse; |
727 | } |
728 | |
729 | -PrinterEnum::State PrinterJob::state() const |
730 | +PrinterEnum::JobState PrinterJob::state() const |
731 | { |
732 | return m_state; |
733 | } |
734 | @@ -311,7 +327,7 @@ |
735 | } |
736 | } |
737 | |
738 | -void PrinterJob::setState(const PrinterEnum::State &state) |
739 | +void PrinterJob::setState(const PrinterEnum::JobState &state) |
740 | { |
741 | if (m_state != state) { |
742 | m_state = state; |
743 | |
744 | === modified file 'plugins/Ubuntu/Settings/Printers/printer/printerjob.h' |
745 | --- plugins/Ubuntu/Settings/Printers/printer/printerjob.h 2017-02-02 17:23:30 +0000 |
746 | +++ plugins/Ubuntu/Settings/Printers/printer/printerjob.h 2017-02-02 17:23:30 +0000 |
747 | @@ -47,13 +47,16 @@ |
748 | Q_PROPERTY(PrinterEnum::PrintRange printRangeMode READ printRangeMode WRITE setPrintRangeMode NOTIFY printRangeModeChanged) |
749 | Q_PROPERTY(int quality READ quality WRITE setQuality NOTIFY qualityChanged) |
750 | Q_PROPERTY(bool reverse READ reverse WRITE setReverse NOTIFY reverseChanged) |
751 | - Q_PROPERTY(PrinterEnum::State state READ state NOTIFY stateChanged) |
752 | + Q_PROPERTY(PrinterEnum::JobState state READ state NOTIFY stateChanged) |
753 | Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged) |
754 | + |
755 | + friend class PrinterCupsBackend; |
756 | public: |
757 | explicit PrinterJob(QObject *parent=Q_NULLPTR); |
758 | explicit PrinterJob(Printer *printer, QObject *parent=Q_NULLPTR); |
759 | explicit PrinterJob(Printer *printer, PrinterBackend *backend, |
760 | QObject *parent=Q_NULLPTR); |
761 | + explicit PrinterJob(const QString &name, PrinterBackend *backend, int jobId, QObject *parent=Q_NULLPTR); |
762 | ~PrinterJob(); |
763 | |
764 | bool collate() const; |
765 | @@ -62,6 +65,7 @@ |
766 | int copies() const; |
767 | int duplexMode() const; |
768 | bool isTwoSided() const; |
769 | + int jobId() const; // TODO: implement |
770 | bool landscape() const; |
771 | // Printer *printer() const; |
772 | QString printerName() const; |
773 | @@ -69,7 +73,7 @@ |
774 | PrinterEnum::PrintRange printRangeMode() const; |
775 | int quality() const; |
776 | bool reverse() const; |
777 | - PrinterEnum::State state() const; |
778 | + PrinterEnum::JobState state() const; |
779 | QString title() const; |
780 | public Q_SLOTS: |
781 | PrinterEnum::DuplexMode getDuplexMode() const; |
782 | @@ -91,7 +95,7 @@ |
783 | private Q_SLOTS: |
784 | void loadDefaults(); |
785 | void setIsTwoSided(const bool isTwoSided); |
786 | - void setState(const PrinterEnum::State &state); |
787 | + void setState(const PrinterEnum::JobState &state); |
788 | Q_SIGNALS: |
789 | void collateChanged(); |
790 | void colorModelChanged(); |
791 | @@ -115,6 +119,7 @@ |
792 | PrinterBackend *m_backend; // TODO: Maybe use the printer's backend? |
793 | int m_duplex_mode; |
794 | bool m_is_two_sided; |
795 | + int m_job_id; |
796 | bool m_landscape; |
797 | Printer *m_printer; |
798 | QString m_printer_name; |
799 | @@ -122,7 +127,7 @@ |
800 | PrinterEnum::PrintRange m_print_range_mode; |
801 | int m_quality; |
802 | bool m_reverse; |
803 | - PrinterEnum::State m_state; |
804 | + PrinterEnum::JobState m_state; |
805 | QString m_title; |
806 | }; |
807 | |
808 | |
809 | === modified file 'tests/unittests/Printers/mockbackend.h' |
810 | --- tests/unittests/Printers/mockbackend.h 2017-02-02 17:23:30 +0000 |
811 | +++ tests/unittests/Printers/mockbackend.h 2017-02-02 17:23:30 +0000 |
812 | @@ -222,6 +222,11 @@ |
813 | |
814 | } |
815 | |
816 | + virtual QList<QSharedPointer<PrinterJob>> printerGetJobs(const QString &name) override |
817 | + { |
818 | + |
819 | + } |
820 | + |
821 | |
822 | virtual QString printerName() const override |
823 | { |
Added a couple of comments.