6#include <qpa/qplatformprintplugin.h>
7#include <qpa/qplatformprintersupport.h>
13#include "private/qcups_p.h"
14#include <QtGui/qpagelayout.h>
18#include "private/qcore_unix_p.h"
22extern QMarginsF qt_convertMargins(
const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits);
25 : QPdfPrintEngine(*
new QCupsPrintEnginePrivate(m))
27 Q_D(QCupsPrintEngine);
28 d->changePrinter(deviceId);
29 state = QPrinter::Idle;
38 Q_D(QCupsPrintEngine);
42 d->setPageSize(QPageSize(QPageSize::PageSizeId(value.toInt())));
44 case PPK_WindowsPageSize:
45 d->setPageSize(QPageSize(QPageSize::id(value.toInt())));
47 case PPK_CustomPaperSize:
48 d->setPageSize(QPageSize(value.toSizeF(), QPageSize::Point));
52 d->setPageSize(d->m_printDevice.supportedPageSize(value.toString()));
55 QPrint::DuplexMode mode = QPrint::DuplexMode(value.toInt());
56 if (d->m_printDevice.supportedDuplexModes().contains(mode)) {
58 d->duplexRequestedExplicitly =
true;
63 d->changePrinter(value.toString());
66 d->cupsOptions = value.toStringList();
67 if (d->cupsOptions.size() % 2 == 1) {
68 qWarning(
"%s: malformed value for key = PPK_CupsOptions "
69 "(odd number of elements in the string-list; "
70 "appending an empty entry)", Q_FUNC_INFO);
71 d->cupsOptions.emplace_back();
75 d->setPageSize(qvariant_cast<QPageSize>(value));
77 case PPK_QPageLayout: {
78 QPageLayout pageLayout = qvariant_cast<QPageLayout>(value);
79 if (pageLayout.isValid() && (d->m_printDevice.isValidPageLayout(pageLayout, d->resolution)
80 || d->m_printDevice.supportsCustomPageSizes()
81 || d->m_printDevice.supportedPageSizes().isEmpty())) {
84 d->m_pageLayout = pageLayout;
85 d->setPageSize(pageLayout.pageSize());
90 QPdfPrintEngine::setProperty(key, value);
97 Q_D(
const QCupsPrintEngine);
101 case PPK_SupportsMultipleCopies:
105 case PPK_NumberOfCopies:
108 case PPK_CupsOptions:
109 ret = d->cupsOptions;
115 ret = QPdfPrintEngine::property(key);
123 : QPdfPrintEnginePrivate(m)
124 , duplex(QPrint::DuplexNone)
137 if (!outputFileName.isEmpty()) {
138 QFile *file =
new QFile(outputFileName);
139 if (! file->open(QFile::WriteOnly|QFile::Truncate)) {
146 fd = cupsTempFd(filename, 512);
148 qWarning(
"QPdfPrinter: Could not open temporary file to print");
151 cupsTempFile = QString::fromLocal8Bit(filename);
152 outDevice =
new QFile();
153 if (!
static_cast<QFile *>(outDevice)->open(fd, QIODevice::WriteOnly)) {
154 qWarning(
"QPdfPrinter: Could not open CUPS temporary file descriptor: %s",
155 qPrintable(outDevice->errorString()));
159#if defined(Q_OS_WIN) && defined(Q_CC_MSVC)
174 QPdfPrintEnginePrivate::closePrintDevice();
176 if (!cupsTempFile.isEmpty()) {
177 QString tempFile = cupsTempFile;
178 cupsTempFile.clear();
181 if (printerName.isEmpty()) {
182 qWarning(
"Could not determine printer to print to");
183 QFile::remove(tempFile);
188 QList<std::pair<QByteArray, QByteArray> > options;
189 QList<cups_option_t> cupsOptStruct;
191 options.emplace_back(
"media", m_pageLayout.pageSize().key().toLocal8Bit());
194 options.emplace_back(
"copies", QString::number(copies).toLocal8Bit());
196 if (copies > 1 && collate)
197 options.emplace_back(
"Collate",
"True");
200 case QPrint::DuplexNone:
201 options.emplace_back(
"sides",
"one-sided");
203 case QPrint::DuplexAuto:
204 if (m_pageLayout.orientation() == QPageLayout::Portrait)
205 options.emplace_back(
"sides",
"two-sided-long-edge");
207 options.emplace_back(
"sides",
"two-sided-short-edge");
209 case QPrint::DuplexLongSide:
210 options.emplace_back(
"sides",
"two-sided-long-edge");
212 case QPrint::DuplexShortSide:
213 options.emplace_back(
"sides",
"two-sided-short-edge");
217 if (m_pageLayout.orientation() == QPageLayout::Landscape)
218 options.emplace_back(
"landscape",
"true");
220 QStringList::const_iterator it = cupsOptions.constBegin();
221 Q_ASSERT(cupsOptions.size() % 2 == 0);
222 while (it != cupsOptions.constEnd()) {
223 options.emplace_back((*it).toLocal8Bit(), (*(it+1)).toLocal8Bit());
227 const int numOptions = options.size();
228 cupsOptStruct.reserve(numOptions);
229 for (
int c = 0; c < numOptions; ++c) {
231 opt.name = options[c].first.data();
232 opt.value = options[c].second.data();
233 cupsOptStruct.append(opt);
238 const auto parts = QStringView{printerName}.split(u'/');
239 const auto printerOriginalName = parts.at(0);
240 cups_option_t* optPtr = cupsOptStruct.size() ? &cupsOptStruct.first() : 0;
241 cupsPrintFile(printerOriginalName.toLocal8Bit().constData(), tempFile.toLocal8Bit().constData(),
242 title.toLocal8Bit().constData(), cupsOptStruct.size(), optPtr);
244 QFile::remove(tempFile);
251 if (newPrinter == printerName)
255 QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
260 QPrintDevice printDevice = ps->createPrintDevice(newPrinter);
261 if (!printDevice.isValid())
263 m_printDevice.swap(printDevice);
264 printerName = m_printDevice.id();
268 if (!duplexRequestedExplicitly || !m_printDevice.supportedDuplexModes().contains(duplex)) {
269 duplex = m_printDevice.defaultDuplexMode();
270 duplexRequestedExplicitly =
false;
272 QPrint::ColorMode colorMode =
static_cast<QPrint::ColorMode>(printerColorMode());
273 if (!m_printDevice.supportedColorModes().contains(colorMode)) {
274 colorModel = (m_printDevice.defaultColorMode() == QPrint::GrayScale)
275 ? QPdfEngine::ColorModel::Grayscale
276 : QPdfEngine::ColorModel::RGB;
280 if (m_printDevice.supportedPageSize(m_pageLayout.pageSize()).isValid())
281 setPageSize(m_pageLayout.pageSize());
283 setPageSize(QPageSize(m_pageLayout.pageSize().size(QPageSize::Point), QPageSize::Point));
288 if (pageSize.isValid()) {
290 QPageSize printerPageSize = m_printDevice.supportedPageSize(pageSize);
291 QPageSize usePageSize = printerPageSize.isValid() ? printerPageSize : pageSize;
292 QMarginsF printable = m_printDevice.printableMargins(usePageSize, m_pageLayout.orientation(), resolution);
293 m_pageLayout.setPageSize(usePageSize, qt_convertMargins(printable, QPageLayout::Point, m_pageLayout.units()));
~QCupsPrintEnginePrivate()
bool openPrintDevice() override
void closePrintDevice() override
QVariant property(PrintEnginePropertyKey key) const override
Returns the print engine's property specified by key.
virtual ~QCupsPrintEngine()
void setProperty(PrintEnginePropertyKey key, const QVariant &value) override
Sets the print engine's property specified by key to the given value.