Merge lp:~ahayzen/ubuntu-ui-extras/printer-components-job-hold-release into lp:~phablet-team/ubuntu-ui-extras/printer-staging

Proposed by Andrew Hayzen
Status: Merged
Approved by: Jonas G. Drange
Approved revision: 139
Merged at revision: 138
Proposed branch: lp:~ahayzen/ubuntu-ui-extras/printer-components-job-hold-release
Merge into: lp:~phablet-team/ubuntu-ui-extras/printer-staging
Diff against target: 441 lines (+193/-43)
14 files modified
modules/Ubuntu/Components/Extras/Example/PrinterQueue.qml (+24/-5)
modules/Ubuntu/Components/Extras/Printers/backend/backend.cpp (+12/-0)
modules/Ubuntu/Components/Extras/Printers/backend/backend.h (+2/-0)
modules/Ubuntu/Components/Extras/Printers/backend/backend_cups.cpp (+14/-0)
modules/Ubuntu/Components/Extras/Printers/backend/backend_cups.h (+2/-0)
modules/Ubuntu/Components/Extras/Printers/cups/ippclient.cpp (+27/-4)
modules/Ubuntu/Components/Extras/Printers/cups/ippclient.h (+2/-0)
modules/Ubuntu/Components/Extras/Printers/models/jobmodel.cpp (+5/-24)
modules/Ubuntu/Components/Extras/Printers/models/jobmodel.h (+1/-0)
modules/Ubuntu/Components/Extras/Printers/printer/printerjob.h (+8/-10)
modules/Ubuntu/Components/Extras/Printers/printers/printers.cpp (+10/-0)
modules/Ubuntu/Components/Extras/Printers/printers/printers.h (+2/-0)
tests/unittests/Printers/mockbackend.h (+32/-0)
tests/unittests/Printers/tst_printers.cpp (+52/-0)
To merge this branch: bzr merge lp:~ahayzen/ubuntu-ui-extras/printer-components-job-hold-release
Reviewer Review Type Date Requested Status
Jonas G. Drange Pending
Review via email: mp+318626@code.launchpad.net

Commit message

* 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

Description of the change

* 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

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'modules/Ubuntu/Components/Extras/Example/PrinterQueue.qml'
2--- modules/Ubuntu/Components/Extras/Example/PrinterQueue.qml 2017-02-21 11:31:44 +0000
3+++ modules/Ubuntu/Components/Extras/Example/PrinterQueue.qml 2017-03-01 15:31:37 +0000
4@@ -46,20 +46,39 @@
5 }
6 delegate: ListItem {
7 height: modelLayout.height + (divider.visible ? divider.height : 0)
8+ trailingActions: ListItemActions {
9+ actions: [
10+ Action {
11+ iconName: model.held ? "media-playback-start" : "media-playback-pause"
12+ text: model.held ? "Release" : "Hold"
13+
14+ onTriggered: {
15+ if (model.held) {
16+ Printers.releaseJob(printer.name, model.id);
17+ } else {
18+ Printers.holdJob(printer.name, model.id);
19+ }
20+ }
21+ },
22+ Action {
23+ iconName: "cancel"
24+ text: "Cancel"
25+
26+ onTriggered: Printers.cancelJob(printer.name, model.id);
27+ }
28+ ]
29+ }
30+
31 ListItemLayout {
32 id: modelLayout
33 title.text: displayName
34- subtitle.text: "Job: " + model.id + " State: " + model.state
35+ subtitle.text: model.title + " (" + model.id + ") State: " + model.state
36 + " Color: " + model.colorModel + " CreationTime: "
37 + model.creationTime + " PageRange: "
38 + model.printRange + " Messages: " + model.messages;
39 subtitle.wrapMode: Text.WrapAtWordBoundaryOrAnywhere
40 subtitle.maximumLineCount: 3
41 }
42- onClicked: {
43- console.debug("Cancel:", printer.name, model.id);
44- Printers.cancelJob(printer.name, model.id);
45- }
46 }
47 model: printer.jobs
48
49
50=== modified file 'modules/Ubuntu/Components/Extras/Printers/backend/backend.cpp'
51--- modules/Ubuntu/Components/Extras/Printers/backend/backend.cpp 2017-02-23 14:04:26 +0000
52+++ modules/Ubuntu/Components/Extras/Printers/backend/backend.cpp 2017-03-01 15:31:37 +0000
53@@ -139,6 +139,18 @@
54 Q_UNUSED(name);
55 }
56
57+void PrinterBackend::holdJob(const QString &name, const int jobId)
58+{
59+ Q_UNUSED(jobId);
60+ Q_UNUSED(name);
61+}
62+
63+void PrinterBackend::releaseJob(const QString &name, const int jobId)
64+{
65+ Q_UNUSED(jobId);
66+ Q_UNUSED(name);
67+}
68+
69 int PrinterBackend::printFileToDest(const QString &filepath,
70 const QString &title,
71 const cups_dest_t *dest)
72
73=== modified file 'modules/Ubuntu/Components/Extras/Printers/backend/backend.h'
74--- modules/Ubuntu/Components/Extras/Printers/backend/backend.h 2017-02-23 14:04:26 +0000
75+++ modules/Ubuntu/Components/Extras/Printers/backend/backend.h 2017-03-01 15:31:37 +0000
76@@ -77,6 +77,8 @@
77 const PrinterJob *options);
78
79 virtual void cancelJob(const QString &name, const int jobId);
80+ virtual void holdJob(const QString &name, const int jobId);
81+ virtual void releaseJob(const QString &name, const int jobId);
82 virtual int printFileToDest(const QString &filepath,
83 const QString &title,
84 const cups_dest_t *dest);
85
86=== modified file 'modules/Ubuntu/Components/Extras/Printers/backend/backend_cups.cpp'
87--- modules/Ubuntu/Components/Extras/Printers/backend/backend_cups.cpp 2017-02-24 12:53:34 +0000
88+++ modules/Ubuntu/Components/Extras/Printers/backend/backend_cups.cpp 2017-03-01 15:31:37 +0000
89@@ -347,6 +347,20 @@
90 }
91 }
92
93+void PrinterCupsBackend::holdJob(const QString &name, const int jobId)
94+{
95+ if (!m_client->printerHoldJob(name, jobId)) {
96+ qWarning() << "Failed to hold job:" << jobId << "for" << name;
97+ }
98+}
99+
100+void PrinterCupsBackend::releaseJob(const QString &name, const int jobId)
101+{
102+ if (!m_client->printerReleaseJob(name, jobId)) {
103+ qWarning() << "Failed to release job:" << jobId << "for" << name;
104+ }
105+}
106+
107 int PrinterCupsBackend::printFileToDest(const QString &filepath,
108 const QString &title,
109 const cups_dest_t *dest)
110
111=== modified file 'modules/Ubuntu/Components/Extras/Printers/backend/backend_cups.h'
112--- modules/Ubuntu/Components/Extras/Printers/backend/backend_cups.h 2017-02-24 12:53:34 +0000
113+++ modules/Ubuntu/Components/Extras/Printers/backend/backend_cups.h 2017-03-01 15:31:37 +0000
114@@ -71,6 +71,8 @@
115 const PrinterJob *options) override;
116
117 virtual void cancelJob(const QString &name, const int jobId) override;
118+ virtual void holdJob(const QString &name, const int jobId) override;
119+ virtual void releaseJob(const QString &name, const int jobId) override;
120 virtual int printFileToDest(const QString &filepath,
121 const QString &title,
122 const cups_dest_t *dest) override;
123
124=== modified file 'modules/Ubuntu/Components/Extras/Printers/cups/ippclient.cpp'
125--- modules/Ubuntu/Components/Extras/Printers/cups/ippclient.cpp 2017-02-21 10:46:29 +0000
126+++ modules/Ubuntu/Components/Extras/Printers/cups/ippclient.cpp 2017-03-01 15:31:37 +0000
127@@ -173,6 +173,30 @@
128 return postRequest(request, ppdFileName.toUtf8(), CupsResourceAdmin);
129 }
130
131+bool IppClient::printerHoldJob(const QString &printerName, const int jobId)
132+{
133+ ipp_t *request = ippNewRequest(IPP_HOLD_JOB);
134+ addPrinterUri(request, printerName);
135+ addRequestingUsername(request, NULL);
136+
137+ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER,
138+ "job-id", jobId);
139+
140+ return sendRequest(request, CupsResourceJobs);
141+}
142+
143+bool IppClient::printerReleaseJob(const QString &printerName, const int jobId)
144+{
145+ ipp_t *request = ippNewRequest(IPP_RELEASE_JOB);
146+ addPrinterUri(request, printerName);
147+ addRequestingUsername(request, NULL);
148+
149+ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER,
150+ "job-id", jobId);
151+
152+ return sendRequest(request, CupsResourceJobs);
153+}
154+
155 bool IppClient::printerSetDefault(const QString &printerName)
156 {
157 return sendNewSimpleRequest(CUPS_SET_DEFAULT, printerName.toUtf8(),
158@@ -343,11 +367,10 @@
159
160 // Construct request
161 request = ippNewRequest(IPP_GET_JOB_ATTRIBUTES);
162+
163 QString uri = QStringLiteral("ipp://localhost/jobs/") + QString::number(jobId);
164- qDebug() << "URI:" << uri;
165-
166- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri.toStdString().data());
167-
168+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
169+ "job-uri", NULL, uri.toStdString().data());
170
171 // Send request and construct reply
172 ipp_t *reply;
173
174=== modified file 'modules/Ubuntu/Components/Extras/Printers/cups/ippclient.h'
175--- modules/Ubuntu/Components/Extras/Printers/cups/ippclient.h 2017-02-21 10:46:29 +0000
176+++ modules/Ubuntu/Components/Extras/Printers/cups/ippclient.h 2017-03-01 15:31:37 +0000
177@@ -51,6 +51,8 @@
178 const QString &ppdFileName,
179 const QString &info,
180 const QString &location);
181+ bool printerHoldJob(const QString &printerName, const int jobId);
182+ bool printerReleaseJob(const QString &printerName, const int jobId);
183 bool printerSetDefault(const QString &printerName);
184 bool printerSetEnabled(const QString &printerName, const bool enabled);
185 bool printerSetAcceptJobs(const QString &printerName, const bool accept,
186
187=== modified file 'modules/Ubuntu/Components/Extras/Printers/models/jobmodel.cpp'
188--- modules/Ubuntu/Components/Extras/Printers/models/jobmodel.cpp 2017-02-23 14:04:26 +0000
189+++ modules/Ubuntu/Components/Extras/Printers/models/jobmodel.cpp 2017-03-01 15:31:37 +0000
190@@ -194,6 +194,9 @@
191 case IdRole:
192 ret = job->jobId();
193 break;
194+ case HeldRole:
195+ ret = job->state() == PrinterEnum::JobState::Held;
196+ break;
197 case ImpressionsCompletedRole:
198 ret = job->impressionsCompleted();
199 break;
200@@ -231,30 +234,7 @@
201 ret = job->size();
202 break;
203 case StateRole:
204- // TODO: improve, for now have a switch
205- switch (job->state()) {
206- case PrinterEnum::JobState::Aborted:
207- ret = "Aborted";
208- break;
209- case PrinterEnum::JobState::Canceled:
210- ret = "Canceled";
211- break;
212- case PrinterEnum::JobState::Complete:
213- ret = "Compelete";
214- break;
215- case PrinterEnum::JobState::Held:
216- ret = "Held";
217- break;
218- case PrinterEnum::JobState::Pending:
219- ret = "Pending";
220- break;
221- case PrinterEnum::JobState::Processing:
222- ret = "Processing";
223- break;
224- case PrinterEnum::JobState::Stopped:
225- ret = "Stopped";
226- break;
227- }
228+ ret = QVariant::fromValue<PrinterEnum::JobState>(job->state());
229 break;
230 case Qt::DisplayRole:
231 case TitleRole:
232@@ -283,6 +263,7 @@
233 names[CreationTimeRole] = "creationTime";
234 names[DuplexRole] = "duplexMode";
235 names[ImpressionsCompletedRole] = "impressionsCompleted";
236+ names[HeldRole] = "held";
237 names[LandscapeRole] = "landscape";
238 names[MessagesRole] = "messages";
239 names[PrinterNameRole] = "printerName";
240
241=== modified file 'modules/Ubuntu/Components/Extras/Printers/models/jobmodel.h'
242--- modules/Ubuntu/Components/Extras/Printers/models/jobmodel.h 2017-02-21 10:46:29 +0000
243+++ modules/Ubuntu/Components/Extras/Printers/models/jobmodel.h 2017-03-01 15:31:37 +0000
244@@ -51,6 +51,7 @@
245 CopiesRole,
246 CreationTimeRole,
247 DuplexRole,
248+ HeldRole,
249 ImpressionsCompletedRole,
250 LandscapeRole,
251 MessagesRole,
252
253=== modified file 'modules/Ubuntu/Components/Extras/Printers/printer/printerjob.h'
254--- modules/Ubuntu/Components/Extras/Printers/printer/printerjob.h 2017-02-23 14:04:26 +0000
255+++ modules/Ubuntu/Components/Extras/Printers/printer/printerjob.h 2017-03-01 15:31:37 +0000
256@@ -58,8 +58,6 @@
257 Q_PROPERTY(PrinterEnum::JobState state READ state NOTIFY stateChanged)
258 Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
259 Q_PROPERTY(QString user READ user NOTIFY userChanged)
260-
261- friend class PrinterCupsBackend;
262 public:
263 explicit PrinterJob(QString dest,
264 PrinterBackend *backend,
265@@ -100,28 +98,28 @@
266 Q_INVOKABLE void printFile(const QUrl &url);
267 void setCollate(const bool collate);
268 void setColorModel(const int colorModel);
269+ void setCompletedTime(const QDateTime &completedTime);
270 void setCopies(const int copies);
271+ void setCreationTime(const QDateTime &creationTime);
272 void setDuplexMode(const int duplexMode);
273 void setImpressionsCompleted(const int &impressionsCompleted);
274+ void setIsTwoSided(const bool isTwoSided);
275 void setLandscape(const bool landscape);
276+ void setMessages(const QStringList &messages);
277 void setPrinter(QSharedPointer<Printer> printer);
278 void setPrintRange(const QString &printRange);
279 void setPrintRangeMode(const PrinterEnum::PrintRange printRangeMode);
280+ void setProcessingTime(const QDateTime &processingTime);
281 void setQuality(const int quality);
282 void setReverse(const bool reverse);
283+ void setSize(const int size);
284+ void setState(const PrinterEnum::JobState &state);
285 void setTitle(const QString &title);
286+ void setUser(const QString &user);
287
288 void updateFrom(QSharedPointer<PrinterJob> other);
289 private Q_SLOTS:
290 void loadDefaults();
291- void setCompletedTime(const QDateTime &completedTime);
292- void setCreationTime(const QDateTime &creationTime);
293- void setIsTwoSided(const bool isTwoSided);
294- void setMessages(const QStringList &messages);
295- void setProcessingTime(const QDateTime &processingTime);
296- void setSize(const int size);
297- void setState(const PrinterEnum::JobState &state);
298- void setUser(const QString &user);
299 Q_SIGNALS:
300 void collateChanged();
301 void colorModelChanged();
302
303=== modified file 'modules/Ubuntu/Components/Extras/Printers/printers/printers.cpp'
304--- modules/Ubuntu/Components/Extras/Printers/printers/printers.cpp 2017-02-24 13:14:13 +0000
305+++ modules/Ubuntu/Components/Extras/Printers/printers/printers.cpp 2017-03-01 15:31:37 +0000
306@@ -148,6 +148,16 @@
307 m_backend->cancelJob(printerName, jobId);
308 }
309
310+void Printers::holdJob(const QString &printerName, const int jobId)
311+{
312+ m_backend->holdJob(printerName, jobId);
313+}
314+
315+void Printers::releaseJob(const QString &printerName, const int jobId)
316+{
317+ m_backend->releaseJob(printerName, jobId);
318+}
319+
320 void Printers::setDefaultPrinterName(const QString &name)
321 {
322 QString reply = m_backend->printerSetDefault(name);
323
324=== modified file 'modules/Ubuntu/Components/Extras/Printers/printers/printers.h'
325--- modules/Ubuntu/Components/Extras/Printers/printers/printers.h 2017-02-24 12:20:07 +0000
326+++ modules/Ubuntu/Components/Extras/Printers/printers/printers.h 2017-03-01 15:31:37 +0000
327@@ -63,6 +63,8 @@
328 public Q_SLOTS:
329 PrinterJob* createJob(const QString &printerName);
330 void cancelJob(const QString &printerName, const int jobId);
331+ void holdJob(const QString &printerName, const int jobId);
332+ void releaseJob(const QString &printerName, const int jobId);
333
334 /* Instructs us to start loading drivers and what have you. In most cases,
335 the user is likely to merely configure existing printers/jobs. Loading
336
337=== modified file 'tests/unittests/Printers/mockbackend.h'
338--- tests/unittests/Printers/mockbackend.h 2017-02-24 12:20:07 +0000
339+++ tests/unittests/Printers/mockbackend.h 2017-03-01 15:31:37 +0000
340@@ -163,6 +163,38 @@
341 }
342 }
343
344+ virtual void holdJob(const QString &name, const int jobId) override
345+ {
346+ for (int i=0; i < m_jobs.count(); i++) {
347+ QSharedPointer<PrinterJob> job = m_jobs[i];
348+
349+ if (job->printerName() == name && job->jobId() == jobId) {
350+ auto jobHeld = QSharedPointer<PrinterJob>(new PrinterJob(job->printerName(), this, jobId));
351+ jobHeld->setState(PrinterEnum::JobState::Held);
352+ m_jobs.replace(0, jobHeld);
353+
354+ Q_EMIT jobState(job->title(), "", job->printerName(), 1, "", true, job->jobId(), 4, "", "", 1);
355+ break;
356+ }
357+ }
358+ }
359+
360+ virtual void releaseJob(const QString &name, const int jobId) override
361+ {
362+ for (int i=0; i < m_jobs.count(); i++) {
363+ QSharedPointer<PrinterJob> job = m_jobs[i];
364+
365+ if (job->printerName() == name && job->jobId() == jobId) {
366+ auto jobRelease = QSharedPointer<PrinterJob>(new PrinterJob(job->printerName(), this, jobId));
367+ jobRelease->setState(PrinterEnum::JobState::Pending);
368+ m_jobs.replace(0, jobRelease);
369+
370+ Q_EMIT jobState(job->title(), "", job->printerName(), 1, "", true, job->jobId(), 4, "", "", 1);
371+ break;
372+ }
373+ }
374+ }
375+
376 virtual int printFileToDest(const QString &filepath,
377 const QString &title,
378 const cups_dest_t *dest) override
379
380=== modified file 'tests/unittests/Printers/tst_printers.cpp'
381--- tests/unittests/Printers/tst_printers.cpp 2017-02-24 12:20:07 +0000
382+++ tests/unittests/Printers/tst_printers.cpp 2017-03-01 15:31:37 +0000
383@@ -139,6 +139,58 @@
384 QCOMPARE(args.at(1).toInt(), 0);
385 QCOMPARE(args.at(2).toInt(), 0);
386 }
387+ void testHoldJob()
388+ {
389+ MockPrinterBackend *backend = new MockPrinterBackend;
390+ JobModel *model = new JobModel(backend);
391+ Printers p(backend);
392+
393+ // Add one.
394+ QSharedPointer<PrinterJob> job = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", backend));
395+ backend->m_jobs << job;
396+ backend->mockJobCreated("", "", "", 1, "", true, 100, 1, "", "", 1);
397+
398+ // Check it was added
399+ QCOMPARE(model->count(), 1);
400+ QCOMPARE(job->state(), PrinterEnum::JobState::Pending);
401+
402+ // Setup the spy
403+ QSignalSpy dataChangedSpy(model, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)));
404+
405+ // Hold the job
406+ p.holdJob(job->printerName(), job->jobId());
407+
408+ // Check item was removed
409+ QTRY_COMPARE(dataChangedSpy.count(), 1);
410+ QCOMPARE(job->state(), PrinterEnum::JobState::Held);
411+ }
412+ void testReleaseJob()
413+ {
414+ MockPrinterBackend *backend = new MockPrinterBackend;
415+ JobModel *model = new JobModel(backend);
416+ Printers p(backend);
417+
418+ // Add one.
419+ QSharedPointer<PrinterJob> job = QSharedPointer<PrinterJob>(new PrinterJob("test-printer", backend));
420+ backend->m_jobs << job;
421+ backend->mockJobCreated("", "", "", 1, "", true, 100, 1, "", "", 1);
422+
423+ p.holdJob(job->printerName(), job->jobId());
424+
425+ // Check it was added and is in held state
426+ QCOMPARE(model->count(), 1);
427+ QCOMPARE(job->state(), PrinterEnum::JobState::Held);
428+
429+ // Setup the spy
430+ QSignalSpy dataChangedSpy(model, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)));
431+
432+ // Release the job
433+ p.releaseJob(job->printerName(), job->jobId());
434+
435+ // Check item was removed
436+ QTRY_COMPARE(dataChangedSpy.count(), 1);
437+ QCOMPARE(job->state(), PrinterEnum::JobState::Pending);
438+ }
439 void testPrinterRemove()
440 {
441 // Load the backend with a printer

Subscribers

People subscribed via source and target branches