Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qcups.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include "qcups_p.h"
6
8#include "qprintengine.h"
9
11
12using namespace Qt::StringLiterals;
13
14QT_IMPL_METATYPE_EXTERN_TAGGED(QCUPSSupport::JobHoldUntil,
15 QCUPSSupport__JobHoldUntil)
16QT_IMPL_METATYPE_EXTERN_TAGGED(QCUPSSupport::BannerPage,
17 QCUPSSupport__BannerPage)
18QT_IMPL_METATYPE_EXTERN_TAGGED(QCUPSSupport::PageSet, QCUPSSupport__PageSet)
19QT_IMPL_METATYPE_EXTERN_TAGGED(QCUPSSupport::PagesPerSheetLayout,
20 QCUPSSupport__PagesPerSheetLayout)
21QT_IMPL_METATYPE_EXTERN_TAGGED(QCUPSSupport::PagesPerSheet,
22 QCUPSSupport__PagesPerSheet)
23
24static QStringList cupsOptionsList(QPrinter *printer) noexcept
25{
26 return printer->printEngine()->property(PPK_CupsOptions).toStringList();
27}
28
29void setCupsOptions(QPrinter *printer, const QStringList &cupsOptions) noexcept
30{
31 printer->printEngine()->setProperty(PPK_CupsOptions, QVariant(cupsOptions));
32}
33
34void QCUPSSupport::setCupsOption(QPrinter *printer, const QString &option, const QString &value)
35{
36 QStringList cupsOptions = cupsOptionsList(printer);
37 if (cupsOptions.contains(option)) {
38 cupsOptions.replace(cupsOptions.indexOf(option) + 1, value);
39 } else {
40 cupsOptions.append(option);
41 cupsOptions.append(value);
42 }
43 setCupsOptions(printer, cupsOptions);
44}
45
46void QCUPSSupport::clearCupsOption(QPrinter *printer, const QString &option)
47{
48 QStringList cupsOptions = cupsOptionsList(printer);
49 // ### use const_iterator once QList::erase takes them
50 const QStringList::iterator it = std::find(cupsOptions.begin(), cupsOptions.end(), option);
51 if (it != cupsOptions.end()) {
52 Q_ASSERT(it + 1 < cupsOptions.end());
53 cupsOptions.erase(it, it+1);
54 setCupsOptions(printer, cupsOptions);
55 }
56}
57
58void QCUPSSupport::clearCupsOptions(QPrinter *printer)
59{
60 setCupsOptions(printer, QStringList());
61}
62
63static inline QString jobHoldToString(const QCUPSSupport::JobHoldUntil jobHold, QTime holdUntilTime)
64{
65 switch (jobHold) {
66 case QCUPSSupport::Indefinite:
67 return QStringLiteral("indefinite");
68 case QCUPSSupport::DayTime:
69 return QStringLiteral("day-time");
70 case QCUPSSupport::Night:
71 return QStringLiteral("night");
72 case QCUPSSupport::SecondShift:
73 return QStringLiteral("second-shift");
74 case QCUPSSupport::ThirdShift:
75 return QStringLiteral("third-shift");
76 case QCUPSSupport::Weekend:
77 return QStringLiteral("weekend");
78 case QCUPSSupport::SpecificTime:
79 if (!holdUntilTime.isNull()) {
80 // CUPS expects the time in UTC, user has entered in local time, so get the UTS equivalent
81 QDateTime localDateTime = QDateTime::currentDateTime();
82 // Check if time is for tomorrow in case of DST change overnight
83 if (holdUntilTime < localDateTime.time())
84 localDateTime = localDateTime.addDays(1);
85 localDateTime.setTime(holdUntilTime);
86 return localDateTime.toUTC().time().toString(u"HH:mm");
87 }
88 // else fall through:
89 Q_FALLTHROUGH();
90 case QCUPSSupport::NoHold:
91 return QString();
92 }
93 Q_UNREACHABLE_RETURN(QString());
94}
95
96QCUPSSupport::JobHoldUntilWithTime QCUPSSupport::parseJobHoldUntil(const QString &jobHoldUntil)
97{
98 if (jobHoldUntil == "indefinite"_L1) {
99 return { QCUPSSupport::Indefinite, QTime() };
100 } else if (jobHoldUntil == "day-time"_L1) {
101 return { QCUPSSupport::DayTime, QTime() };
102 } else if (jobHoldUntil == "night"_L1) {
103 return { QCUPSSupport::Night, QTime() };
104 } else if (jobHoldUntil == "second-shift"_L1) {
105 return { QCUPSSupport::SecondShift, QTime() };
106 } else if (jobHoldUntil == "third-shift"_L1) {
107 return { QCUPSSupport::ThirdShift, QTime() };
108 } else if (jobHoldUntil == "weekend"_L1) {
109 return { QCUPSSupport::Weekend, QTime() };
110 }
111
112
113 QTime parsedTime = QTime::fromString(jobHoldUntil, u"h:m:s");
114 if (!parsedTime.isValid())
115 parsedTime = QTime::fromString(jobHoldUntil, u"h:m");
116 if (parsedTime.isValid()) {
117 // CUPS time is in UTC, user expects local time, so get the equivalent
118 QDateTime dateTimeUtc = QDateTime::currentDateTimeUtc();
119 dateTimeUtc.setTime(parsedTime);
120 return { QCUPSSupport::SpecificTime, dateTimeUtc.toLocalTime().time() };
121 }
122
123 return { QCUPSSupport::NoHold, QTime() };
124}
125
126ppd_option_t *QCUPSSupport::findPpdOption(const char *optionName, QPrintDevice *printDevice)
127{
128 ppd_file_t *ppd = qvariant_cast<ppd_file_t*>(printDevice->property(PDPK_PpdFile));
129
130 if (ppd) {
131 for (int i = 0; i < ppd->num_groups; ++i) {
132 ppd_group_t *group = &ppd->groups[i];
133
134 for (int i = 0; i < group->num_options; ++i) {
135 ppd_option_t *option = &group->options[i];
136
137 if (qstrcmp(option->keyword, optionName) == 0)
138 return option;
139 }
140 }
141 }
142
143 return nullptr;
144}
145
146void QCUPSSupport::setJobHold(QPrinter *printer, const JobHoldUntil jobHold, QTime holdUntilTime)
147{
148 const QString jobHoldUntilArgument = jobHoldToString(jobHold, holdUntilTime);
149 if (!jobHoldUntilArgument.isEmpty()) {
150 setCupsOption(printer,
151 QStringLiteral("job-hold-until"),
152 jobHoldUntilArgument);
153 } else {
154 clearCupsOption(printer, QStringLiteral("job-hold-until"));
155 }
156}
157
158void QCUPSSupport::setJobBilling(QPrinter *printer, const QString &jobBilling)
159{
160 setCupsOption(printer, QStringLiteral("job-billing"), jobBilling);
161}
162
163void QCUPSSupport::setJobPriority(QPrinter *printer, int priority)
164{
165 setCupsOption(printer, QStringLiteral("job-priority"), QString::number(priority));
166}
167
168static inline QString bannerPageToString(const QCUPSSupport::BannerPage bannerPage)
169{
170 switch (bannerPage) {
171 case QCUPSSupport::NoBanner: return QStringLiteral("none");
172 case QCUPSSupport::Standard: return QStringLiteral("standard");
173 case QCUPSSupport::Unclassified: return QStringLiteral("unclassified");
174 case QCUPSSupport::Confidential: return QStringLiteral("confidential");
175 case QCUPSSupport::Classified: return QStringLiteral("classified");
176 case QCUPSSupport::Secret: return QStringLiteral("secret");
177 case QCUPSSupport::TopSecret: return QStringLiteral("topsecret");
178 }
179 Q_UNREACHABLE_RETURN(QString());
180}
181
182static inline QCUPSSupport::BannerPage stringToBannerPage(const QString &bannerPage)
183{
184 if (bannerPage == "none"_L1) return QCUPSSupport::NoBanner;
185 else if (bannerPage == "standard"_L1) return QCUPSSupport::Standard;
186 else if (bannerPage == "unclassified"_L1) return QCUPSSupport::Unclassified;
187 else if (bannerPage == "confidential"_L1) return QCUPSSupport::Confidential;
188 else if (bannerPage == "classified"_L1) return QCUPSSupport::Classified;
189 else if (bannerPage == "secret"_L1) return QCUPSSupport::Secret;
190 else if (bannerPage == "topsecret"_L1) return QCUPSSupport::TopSecret;
191
192 return QCUPSSupport::NoBanner;
193}
194
195QCUPSSupport::JobSheets QCUPSSupport::parseJobSheets(const QString &jobSheets)
196{
197 JobSheets result;
198
199 const QStringList parts = jobSheets.split(u',');
200 if (parts.size() == 2) {
201 result.startBannerPage = stringToBannerPage(parts[0]);
202 result.endBannerPage = stringToBannerPage(parts[1]);
203 }
204
205 return result;
206}
207
208void QCUPSSupport::setBannerPages(QPrinter *printer, const BannerPage startBannerPage, const BannerPage endBannerPage)
209{
210 const QString startBanner = bannerPageToString(startBannerPage);
211 const QString endBanner = bannerPageToString(endBannerPage);
212
213 setCupsOption(printer, QStringLiteral("job-sheets"), startBanner + u',' + endBanner);
214}
215
216void QCUPSSupport::setPageSet(QPrinter *printer, const PageSet pageSet)
217{
218 QString pageSetString;
219
220 switch (pageSet) {
221 case OddPages:
222 pageSetString = QStringLiteral("odd");
223 break;
224 case EvenPages:
225 pageSetString = QStringLiteral("even");
226 break;
227 case AllPages:
228 pageSetString = QStringLiteral("all");
229 break;
230 }
231
232 setCupsOption(printer, QStringLiteral("page-set"), pageSetString);
233}
234
235void QCUPSSupport::setPagesPerSheetLayout(QPrinter *printer, const PagesPerSheet pagesPerSheet,
236 const PagesPerSheetLayout pagesPerSheetLayout)
237{
238 // WARNING: the following trick (with a [2]-extent) only works as
239 // WARNING: long as there's only one two-digit number in the list
240 // WARNING: and it is the last one (before the "\0")!
241 static const char pagesPerSheetData[][2] = { "1", "2", "4", "6", "9", {'1', '6'}, "\0" };
242 static const char pageLayoutData[][5] = {"lrtb", "lrbt", "rlbt", "rltb", "btlr", "btrl", "tblr", "tbrl"};
243 setCupsOption(printer, QStringLiteral("number-up"), QLatin1StringView(pagesPerSheetData[pagesPerSheet]));
244 setCupsOption(printer, QStringLiteral("number-up-layout"), QLatin1StringView(pageLayoutData[pagesPerSheetLayout]));
245}
246
247void QCUPSSupport::setPageRange(QPrinter *printer, int pageFrom, int pageTo)
248{
249 setPageRange(printer, QStringLiteral("%1-%2").arg(pageFrom).arg(pageTo));
250}
251
252void QCUPSSupport::setPageRange(QPrinter *printer, const QString &pageRange)
253{
254 setCupsOption(printer, QStringLiteral("page-ranges"), pageRange);
255}
256
257QT_END_NAMESPACE
Combined button and popup list for selecting options.
static QCUPSSupport::BannerPage stringToBannerPage(const QString &bannerPage)
Definition qcups.cpp:182
static QString bannerPageToString(const QCUPSSupport::BannerPage bannerPage)
Definition qcups.cpp:168
static QString jobHoldToString(const QCUPSSupport::JobHoldUntil jobHold, QTime holdUntilTime)
Definition qcups.cpp:63
#define PDPK_PpdFile
Definition qcups_p.h:38
#define PPK_CupsOptions
Definition qcups_p.h:36