Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qcupsprintengine.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
5
6#include <qpa/qplatformprintplugin.h>
7#include <qpa/qplatformprintersupport.h>
8
9#include <qiodevice.h>
10#include <qfile.h>
11#include <qdebug.h>
12#include <qbuffer.h>
13#include "private/qcups_p.h" // Only needed for PPK_CupsOptions
14#include <QtGui/qpagelayout.h>
15
16#include <cups/cups.h>
17
18#include "private/qcore_unix_p.h" // overrides QT_OPEN
19
21
22extern QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits);
23
26{
28 d->changePrinter(deviceId);
30}
31
33{
34}
35
37{
39
40 switch (int(key)) {
41 case PPK_PageSize:
42 d->setPageSize(QPageSize(QPageSize::PageSizeId(value.toInt())));
43 break;
45 d->setPageSize(QPageSize(QPageSize::id(value.toInt())));
46 break;
48 d->setPageSize(QPageSize(value.toSizeF(), QPageSize::Point));
49 break;
50 case PPK_PaperName:
51 // Get the named page size from the printer if supported
52 d->setPageSize(d->m_printDevice.supportedPageSize(value.toString()));
53 break;
54 case PPK_Duplex: {
56 if (d->m_printDevice.supportedDuplexModes().contains(mode)) {
57 d->duplex = mode;
58 d->duplexRequestedExplicitly = true;
59 }
60 break;
61 }
62 case PPK_PrinterName:
63 d->changePrinter(value.toString());
64 break;
65 case PPK_CupsOptions:
66 d->cupsOptions = value.toStringList();
67 break;
68 case PPK_QPageSize:
69 d->setPageSize(qvariant_cast<QPageSize>(value));
70 break;
71 case PPK_QPageLayout: {
72 QPageLayout pageLayout = qvariant_cast<QPageLayout>(value);
73 if (pageLayout.isValid() && (d->m_printDevice.isValidPageLayout(pageLayout, d->resolution)
74 || d->m_printDevice.supportsCustomPageSizes()
75 || d->m_printDevice.supportedPageSizes().isEmpty())) {
76 // supportedPageSizes().isEmpty() because QPageSetupWidget::initPageSizes says
77 // "If no available printer page sizes, populate with all page sizes"
78 d->m_pageLayout = pageLayout;
79 d->setPageSize(pageLayout.pageSize());
80 }
81 break;
82 }
83 default:
85 break;
86 }
87}
88
90{
91 Q_D(const QCupsPrintEngine);
92
94 switch (int(key)) {
96 // CUPS server always supports multiple copies, even if individual m_printDevice doesn't
97 ret = true;
98 break;
100 ret = 1;
101 break;
102 case PPK_CupsOptions:
103 ret = d->cupsOptions;
104 break;
105 case PPK_Duplex:
106 ret = d->duplex;
107 break;
108 default:
110 break;
111 }
112 return ret;
113}
114
115
118 , duplex(QPrint::DuplexNone)
119{
120}
121
123{
124}
125
127{
128 if (outDevice)
129 return false;
130
131 if (!outputFileName.isEmpty()) {
134 delete file;
135 return false;
136 }
137 outDevice = file;
138 } else {
139 char filename[512];
140 fd = cupsTempFd(filename, 512);
141 if (fd < 0) {
142 qWarning("QPdfPrinter: Could not open temporary file to print");
143 return false;
144 }
145 cupsTempFile = QString::fromLocal8Bit(filename);
146 outDevice = new QFile();
147 static_cast<QFile *>(outDevice)->open(fd, QIODevice::WriteOnly);
148 }
149
150 return true;
151}
152
154{
156
157 if (!cupsTempFile.isEmpty()) {
158 QString tempFile = cupsTempFile;
159 cupsTempFile.clear();
160
161 // Should never have got here without a printer, but check anyway
162 if (printerName.isEmpty()) {
163 qWarning("Could not determine printer to print to");
165 return;
166 }
167
168 // Set up print options.
170 QList<cups_option_t> cupsOptStruct;
171
173
174 if (copies > 1)
176
177 if (copies > 1 && collate)
178 options.append(QPair<QByteArray, QByteArray>("Collate", "True"));
179
180 switch (duplex) {
182 options.append(QPair<QByteArray, QByteArray>("sides", "one-sided"));
183 break;
186 options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-long-edge"));
187 else
188 options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-short-edge"));
189 break;
191 options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-long-edge"));
192 break;
194 options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-short-edge"));
195 break;
196 }
197
199 options.append(QPair<QByteArray, QByteArray>("landscape", ""));
200
201 QStringList::const_iterator it = cupsOptions.constBegin();
202 while (it != cupsOptions.constEnd()) {
203 options.append(QPair<QByteArray, QByteArray>((*it).toLocal8Bit(), (*(it+1)).toLocal8Bit()));
204 it += 2;
205 }
206
207 const int numOptions = options.size();
208 cupsOptStruct.reserve(numOptions);
209 for (int c = 0; c < numOptions; ++c) {
210 cups_option_t opt;
211 opt.name = options[c].first.data();
212 opt.value = options[c].second.data();
213 cupsOptStruct.append(opt);
214 }
215
216 // Print the file
217 // Cups expect the printer original name without instance, the full name is used only to retrieve the configuration
218 const auto parts = QStringView{printerName}.split(u'/');
219 const auto printerOriginalName = parts.at(0);
220 cups_option_t* optPtr = cupsOptStruct.size() ? &cupsOptStruct.first() : 0;
221 cupsPrintFile(printerOriginalName.toLocal8Bit().constData(), tempFile.toLocal8Bit().constData(),
222 title.toLocal8Bit().constData(), cupsOptStruct.size(), optPtr);
223
225 }
226}
227
228void QCupsPrintEnginePrivate::changePrinter(const QString &newPrinter)
229{
230 // Don't waste time if same printer name
231 if (newPrinter == printerName)
232 return;
233
234 // Should never have reached here if no plugin available, but check just in case
236 if (!ps)
237 return;
238
239 // Try create the printer, only use it if it returns valid
240 QPrintDevice printDevice = ps->createPrintDevice(newPrinter);
241 if (!printDevice.isValid())
242 return;
243 m_printDevice.swap(printDevice);
244 printerName = m_printDevice.id();
245
246 // in case a duplex value was explicitly set, check if new printer supports current value,
247 // otherwise use device default
248 if (!duplexRequestedExplicitly || !m_printDevice.supportedDuplexModes().contains(duplex)) {
249 duplex = m_printDevice.defaultDuplexMode();
250 duplexRequestedExplicitly = false;
251 }
253 if (!m_printDevice.supportedColorModes().contains(colorMode))
254 grayscale = m_printDevice.defaultColorMode() == QPrint::GrayScale;
255
256 // Get the equivalent page size for this printer as supported names may be different
257 if (m_printDevice.supportedPageSize(m_pageLayout.pageSize()).isValid())
258 setPageSize(m_pageLayout.pageSize());
259 else
261}
262
263void QCupsPrintEnginePrivate::setPageSize(const QPageSize &pageSize)
264{
265 if (pageSize.isValid()) {
266 // Find if the requested page size has a matching printer page size, if so use its defined name instead
267 QPageSize printerPageSize = m_printDevice.supportedPageSize(pageSize);
268 QPageSize usePageSize = printerPageSize.isValid() ? printerPageSize : pageSize;
269 QMarginsF printable = m_printDevice.printableMargins(usePageSize, m_pageLayout.orientation(), resolution);
271 }
272}
273
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:122
QVariant property(PrintEnginePropertyKey key) const override
Returns the print engine's property specified by key.
QCupsPrintEngine(QPrinter::PrinterMode m, const QString &deviceId)
void setProperty(PrintEnginePropertyKey key, const QVariant &value) override
Sets the print engine's property specified by key to the given value.
\inmodule QtCore
Definition qfile.h:93
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:881
bool remove()
Removes the file specified by fileName().
Definition qfile.cpp:419
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
T & first()
Definition qlist.h:628
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
void reserve(qsizetype size)
Definition qlist.h:746
pointer data()
Definition qlist.h:414
void append(parameter_type t)
Definition qlist.h:441
\inmodule QtCore
Definition qmargins.h:274
\inmodule QtGui
Definition qpagelayout.h:20
Unit units() const
Returns the units the page layout is currently defined in.
bool isValid() const
Returns true if this page layout is valid.
Unit
This enum type is used to specify the measurement unit for page layout and margins.
Definition qpagelayout.h:24
Orientation orientation() const
Returns the page orientation of the page layout.
void setPageSize(const QPageSize &pageSize, const QMarginsF &minMargins=QMarginsF(0, 0, 0, 0))
Sets the page size of the page layout to pageSize.
QPageSize pageSize() const
Returns the page size of the page layout.
\inmodule QtGui
Definition qpagesize.h:22
bool isValid() const
Returns true if this page size is valid.
QString key() const
Returns the unique key of the page size.
QSizeF size(Unit units) const
Returns the size of the page in the required units.
PageSizeId id() const
Returns the standard QPageSize::PageSizeId of the page, or QPageSize::Custom.
PageSizeId
This enum type lists the available page sizes as defined in the Postscript PPD standard.
Definition qpagesize.h:25
QString title
Definition qpdf_p.h:254
QPageLayout m_pageLayout
Definition qpdf_p.h:261
QString outputFileName
Definition qpdf_p.h:253
QIODevice * outDevice
Definition qpdf_p.h:249
QPageLayout pageLayout() const
Definition qpdf.cpp:1403
friend class QCupsPrintEnginePrivate
QPrinter::PrinterState state
virtual void setProperty(PrintEnginePropertyKey key, const QVariant &value) override
Sets the print engine's property specified by key to the given value.
virtual QVariant property(PrintEnginePropertyKey key) const override
Returns the print engine's property specified by key.
static QPlatformPrinterSupport * get()
The QPlatformPrinterSupport class provides an abstraction for print support.
virtual QPrintDevice createPrintDevice(const QString &id)
QPageSize supportedPageSize(const QPageSize &pageSize) const
bool isValid() const
void swap(QPrintDevice &other)
QList< QPrint::DuplexMode > supportedDuplexModes() const
QPrint::DuplexMode defaultDuplexMode() const
QList< QPrint::ColorMode > supportedColorModes() const
QPrint::ColorMode defaultColorMode() const
QMarginsF printableMargins(const QPageSize &pageSize, QPageLayout::Orientation orientation, int resolution) const
QString id() const
PrintEnginePropertyKey
This enum is used to communicate properties between the print engine and QPrinter.
@ PPK_SupportsMultipleCopies
PrinterMode
This enum describes the mode the printer should work in.
Definition qprinter.h:31
\inmodule QtCore
Definition qstringview.h:76
Q_CORE_EXPORT QList< QStringView > split(QStringView sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the view into substring views wherever sep occurs, and returns the list of those string views.
Definition qstring.cpp:7987
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5788
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1107
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QByteArray toLocal8Bit() const &
Definition qstring.h:567
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:7822
\inmodule QtCore
Definition qvariant.h:64
QSet< QString >::iterator it
QStyleOptionButton opt
ColorMode
Definition qprint_p.h:71
@ Color
Definition qprint_p.h:73
@ GrayScale
Definition qprint_p.h:72
DuplexMode
Definition qprint_p.h:64
@ DuplexLongSide
Definition qprint_p.h:67
@ DuplexShortSide
Definition qprint_p.h:68
@ DuplexNone
Definition qprint_p.h:65
@ DuplexAuto
Definition qprint_p.h:66
Combined button and popup list for selecting options.
static QT_BEGIN_NAMESPACE const char tempFile[]
std::pair< T1, T2 > QPair
#define PPK_CupsOptions
Definition qcups_p.h:35
QT_BEGIN_NAMESPACE QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qWarning
Definition qlogging.h:162
return ret
GLenum mode
const GLfloat * m
GLuint64 key
GLuint64 GLenum GLint fd
const GLubyte * c
Q_GUI_EXPORT QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits)
static char * toLocal8Bit(char *out, QStringView in, QStringConverter::State *state)
QFile file
[0]
file open(QIODevice::ReadOnly)
bool contains(const AT &t) const noexcept
Definition qlist.h:44