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
4#include "qpagesetupdialog.h"
5
6#include "qpagesetupdialog_unix_p.h"
7
8#include <private/qpagesetupdialog_p.h>
9#include <private/qprintdevice_p.h>
10#if QT_CONFIG(cups)
11#include <private/qcups_p.h>
12#endif
13
14#include "qpainter.h"
15#include "qprintdialog.h"
16#include "qstringconverter.h"
17#include "qdialogbuttonbox.h"
18#include <ui_qpagesetupwidget.h>
19
20#include <QtPrintSupport/qprinter.h>
21
22#include <qpa/qplatformprintplugin.h>
23#include <qpa/qplatformprintersupport.h>
24
25QT_BEGIN_NAMESPACE
26
27using namespace Qt::StringLiterals;
28
29extern QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits);
30
31// Disabled until we have support for papersources on unix
32// #define PSD_ENABLE_PAPERSOURCE
33
34#ifdef PSD_ENABLE_PAPERSOURCE
35static const char *paperSourceNames[] = {
36 "Only One",
37 "Lower",
38 "Middle",
39 "Manual",
40 "Envelope",
41 "Envelope manual",
42 "Auto",
43 "Tractor",
44 "Small format",
45 "Large format",
46 "Large capacity",
47 "Cassette",
48 "Form source",
49 0
50};
51
52struct PaperSourceNames
53{
54 PaperSourceNames(const char *nam, QPrinter::PaperSource ps)
55 : paperSource(ps), name(nam) {}
56 QPrinter::PaperSource paperSource;
57 const char *name;
58};
59#endif
60
61
62// QPagePreview
63// - Private widget to display preview of page layout
64// - Embedded in QPageSetupWidget
65
66class QPagePreview : public QWidget
67{
68public:
69 QPagePreview(QWidget *parent) : QWidget(parent)
70 {
71 setSizePolicy(hor: QSizePolicy::Expanding, ver: QSizePolicy::Expanding);
72 setMinimumSize(minw: 50, minh: 50);
73 }
74
75 void setPageLayout(const QPageLayout &layout)
76 {
77 m_pageLayout = layout;
78 update();
79 }
80
81 void setPagePreviewLayout(int columns, int rows)
82 {
83 m_pagePreviewColumns = columns;
84 m_pagePreviewRows = rows;
85 update();
86 }
87
88protected:
89 void paintEvent(QPaintEvent *) override
90 {
91 QSize pageSize = m_pageLayout.fullRectPoints().size();
92 QSizeF scaledSize = pageSize.scaled(w: width() - 10, h: height() - 10, mode: Qt::KeepAspectRatio);
93 QRect pageRect = QRect(QPoint(0,0), scaledSize.toSize());
94 pageRect.moveCenter(p: rect().center());
95 qreal width_factor = scaledSize.width() / pageSize.width();
96 qreal height_factor = scaledSize.height() / pageSize.height();
97 QMarginsF margins = m_pageLayout.margins(units: QPageLayout::Point);
98 int left = qRound(d: margins.left() * width_factor);
99 int top = qRound(d: margins.top() * height_factor);
100 int right = qRound(d: margins.right() * width_factor);
101 int bottom = qRound(d: margins.bottom() * height_factor);
102 QRect marginRect(pageRect.x() + left, pageRect.y() + top,
103 pageRect.width() - (left + right + 1), pageRect.height() - (top + bottom + 1));
104
105 QPainter p(this);
106 QColor shadow(palette().mid().color());
107 for (int i=1; i<6; ++i) {
108 shadow.setAlpha(180-i*30);
109 QRect offset(pageRect.adjusted(xp1: i, yp1: i, xp2: i, yp2: i));
110 p.setPen(shadow);
111 p.drawLine(x1: offset.left(), y1: offset.bottom(), x2: offset.right(), y2: offset.bottom());
112 p.drawLine(x1: offset.right(), y1: offset.top(), x2: offset.right(), y2: offset.bottom()-1);
113 }
114 p.fillRect(pageRect, palette().light());
115
116 if (marginRect.isValid()) {
117 p.setPen(QPen(palette().color(cr: QPalette::Dark), 0, Qt::DotLine));
118 p.drawRect(r: marginRect);
119
120 marginRect.adjust(dx1: 2, dy1: 2, dx2: -1, dy2: -1);
121 p.setClipRect(marginRect);
122 QFont font;
123 font.setPointSizeF(font.pointSizeF()*0.25);
124 p.setFont(font);
125 p.setPen(palette().color(cr: QPalette::Dark));
126 QString text("Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi."_L1);
127 for (int i=0; i<3; ++i)
128 text += text;
129
130 const int spacing = pageRect.width() * 0.1;
131 const int textWidth = (marginRect.width() - (spacing * (m_pagePreviewColumns-1))) / m_pagePreviewColumns;
132 const int textHeight = (marginRect.height() - (spacing * (m_pagePreviewRows-1))) / m_pagePreviewRows;
133
134 for (int x = 0 ; x < m_pagePreviewColumns; ++x) {
135 for (int y = 0 ; y < m_pagePreviewRows; ++y) {
136 QRect textRect(marginRect.left() + x * (textWidth + spacing),
137 marginRect.top() + y * (textHeight + spacing),
138 textWidth, textHeight);
139 p.drawText(r: textRect, flags: Qt::TextWordWrap|Qt::AlignVCenter, text);
140 }
141 }
142 }
143 }
144
145private:
146 // Page Layout
147 QPageLayout m_pageLayout;
148 // Pages Per Sheet / n-up layout
149 int m_pagePreviewColumns, m_pagePreviewRows;
150};
151
152
153// QUnixPageSetupDialogPrivate
154// - Linux / Cups implementation of QPageSetupDialogPrivate
155// - Embeds QPageSetupWidget
156
157class QUnixPageSetupDialogPrivate : public QPageSetupDialogPrivate
158{
159 Q_DECLARE_PUBLIC(QPageSetupDialog)
160
161public:
162 QUnixPageSetupDialogPrivate(QPrinter *printer);
163 ~QUnixPageSetupDialogPrivate();
164 void init();
165
166 QPageSetupWidget *widget;
167};
168
169QUnixPageSetupDialogPrivate::QUnixPageSetupDialogPrivate(QPrinter *printer) : QPageSetupDialogPrivate(printer)
170{
171}
172
173QUnixPageSetupDialogPrivate::~QUnixPageSetupDialogPrivate()
174{
175}
176
177void QUnixPageSetupDialogPrivate::init()
178{
179 Q_Q(QPageSetupDialog);
180
181 widget = new QPageSetupWidget(q);
182 widget->setPrinter(printer, printDevice: nullptr, outputFormat: printer->outputFormat(), printerName: printer->printerName());
183
184 QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok
185 | QDialogButtonBox::Cancel,
186 Qt::Horizontal, q);
187 QObject::connect(sender: buttons, SIGNAL(accepted()), receiver: q, SLOT(accept()));
188 QObject::connect(sender: buttons, SIGNAL(rejected()), receiver: q, SLOT(reject()));
189
190 QVBoxLayout *lay = new QVBoxLayout(q);
191 lay->addWidget(widget);
192 lay->addWidget(buttons);
193}
194
195// QPageSetupWidget
196// - Private widget implementation for Linux / CUPS
197// - Embeds QPagePreview
198// - TODO Could be made public as a stand-alone widget?
199
200QPageSetupWidget::QPageSetupWidget(QWidget *parent)
201 : QWidget(parent),
202 m_pagePreview(nullptr),
203 m_printer(nullptr),
204 m_printDevice(nullptr),
205#if QT_CONFIG(cups)
206 m_pageSizePpdOption(nullptr),
207#endif
208 m_outputFormat(QPrinter::PdfFormat),
209 m_units(QPageLayout::Point),
210 m_savedUnits(QPageLayout::Point),
211 m_savedPagesPerSheet(-1),
212 m_savedPagesPerSheetLayout(-1),
213 m_blockSignals(false),
214 m_realCustomPageSizeIndex(-1)
215{
216 m_ui.setupUi(this);
217
218 QVBoxLayout *lay = new QVBoxLayout(m_ui.preview);
219 m_pagePreview = new QPagePreview(m_ui.preview);
220 m_pagePreview->setPagePreviewLayout(columns: 1, rows: 1);
221
222 lay->addWidget(m_pagePreview);
223
224 setAttribute(Qt::WA_WState_Polished, false);
225
226#ifdef PSD_ENABLE_PAPERSOURCE
227 for (int i=0; paperSourceNames[i]; ++i)
228 m_ui.paperSource->insertItem(paperSourceNames[i]);
229#else
230 m_ui.paperSourceLabel->setVisible(false);
231 m_ui.paperSource->setVisible(false);
232#endif
233
234 m_ui.reverseLandscape->setVisible(false);
235 m_ui.reversePortrait->setVisible(false);
236
237 initUnits();
238 initPagesPerSheet();
239
240 connect(m_ui.unitCombo, &QComboBox::activated, this, &QPageSetupWidget::unitChanged);
241
242 connect(m_ui.pageSizeCombo, &QComboBox::currentIndexChanged, this, &QPageSetupWidget::pageSizeChanged);
243 connect(m_ui.pageWidth, &QDoubleSpinBox::valueChanged, this, &QPageSetupWidget::pageSizeChanged);
244 connect(m_ui.pageHeight, &QDoubleSpinBox::valueChanged, this, &QPageSetupWidget::pageSizeChanged);
245
246 connect(m_ui.leftMargin, &QDoubleSpinBox::valueChanged, this, &QPageSetupWidget::leftMarginChanged);
247 connect(m_ui.topMargin, &QDoubleSpinBox::valueChanged, this, &QPageSetupWidget::topMarginChanged);
248 connect(m_ui.rightMargin, &QDoubleSpinBox::valueChanged, this, &QPageSetupWidget::rightMarginChanged);
249 connect(m_ui.bottomMargin, &QDoubleSpinBox::valueChanged, this, &QPageSetupWidget::bottomMarginChanged);
250
251 connect(m_ui.portrait, &QRadioButton::clicked, this, &QPageSetupWidget::pageOrientationChanged);
252 connect(m_ui.landscape, &QRadioButton::clicked, this, &QPageSetupWidget::pageOrientationChanged);
253
254 connect(m_ui.pagesPerSheetCombo, &QComboBox::currentIndexChanged, this, &QPageSetupWidget::pagesPerSheetChanged);
255}
256
257// Init the Units combo box
258void QPageSetupWidget::initUnits()
259{
260 m_ui.unitCombo->addItem(tr("Millimeters (mm)"), QVariant::fromValue(QPageLayout::Millimeter));
261 m_ui.unitCombo->addItem(tr("Inches (in)"), QVariant::fromValue(QPageLayout::Inch));
262 m_ui.unitCombo->addItem(tr("Points (pt)"), QVariant::fromValue(QPageLayout::Point));
263 m_ui.unitCombo->addItem(tr("Pica (P̸)"), QVariant::fromValue(QPageLayout::Pica));
264 m_ui.unitCombo->addItem(tr("Didot (DD)"), QVariant::fromValue(QPageLayout::Didot));
265 m_ui.unitCombo->addItem(tr("Cicero (CC)"), QVariant::fromValue(QPageLayout::Cicero));
266
267 // Initially default to locale measurement system, mm if metric, in otherwise
268 m_ui.unitCombo->setCurrentIndex(QLocale().measurementSystem() != QLocale::MetricSystem);
269}
270
271// Init the Pages Per Sheet (n-up) combo boxes if using CUPS
272void QPageSetupWidget::initPagesPerSheet()
273{
274#if QT_CONFIG(cups)
275 m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Left to Right, Top to Bottom"),
276 QVariant::fromValue(QCUPSSupport::LeftToRightTopToBottom));
277 m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Left to Right, Bottom to Top"),
278 QVariant::fromValue(QCUPSSupport::LeftToRightBottomToTop));
279 m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Right to Left, Bottom to Top"),
280 QVariant::fromValue(QCUPSSupport::RightToLeftBottomToTop));
281 m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Right to Left, Top to Bottom"),
282 QVariant::fromValue(QCUPSSupport::RightToLeftTopToBottom));
283 m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Bottom to Top, Left to Right"),
284 QVariant::fromValue(QCUPSSupport::BottomToTopLeftToRight));
285 m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Bottom to Top, Right to Left"),
286 QVariant::fromValue(QCUPSSupport::BottomToTopRightToLeft));
287 m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Top to Bottom, Left to Right"),
288 QVariant::fromValue(QCUPSSupport::TopToBottomLeftToRight));
289 m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Top to Bottom, Right to Left"),
290 QVariant::fromValue(QCUPSSupport::TopToBottomRightToLeft));
291
292 m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr("1 (1x1)"),
293 QVariant::fromValue(QCUPSSupport::OnePagePerSheet));
294 m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr("2 (2x1)"),
295 QVariant::fromValue(QCUPSSupport::TwoPagesPerSheet));
296 m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr("4 (2x2)"),
297 QVariant::fromValue(QCUPSSupport::FourPagesPerSheet));
298 m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr("6 (2x3)"),
299 QVariant::fromValue(QCUPSSupport::SixPagesPerSheet));
300 m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr("9 (3x3)"),
301 QVariant::fromValue(QCUPSSupport::NinePagesPerSheet));
302 m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr("16 (4x4)"),
303 QVariant::fromValue(QCUPSSupport::SixteenPagesPerSheet));
304
305 // Set to QCUPSSupport::OnePagePerSheet
306 m_ui.pagesPerSheetCombo->setCurrentIndex(0);
307 // Set to QCUPSSupport::LeftToRightTopToBottom
308 m_ui.pagesPerSheetLayoutCombo->setCurrentIndex(0);
309#else
310 // Disable if CUPS wasn't found
311 m_ui.pagesPerSheetButtonGroup->hide();
312#endif
313}
314
315void QPageSetupWidget::initPageSizes()
316{
317 m_blockSignals = true;
318
319 m_ui.pageSizeCombo->clear();
320
321 m_realCustomPageSizeIndex = -1;
322
323 if (m_outputFormat == QPrinter::NativeFormat && !m_printerName.isEmpty()) {
324 QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
325 if (ps) {
326 QPrintDevice printDevice = ps->createPrintDevice(id: m_printerName);
327 const QPageSize defaultSize = printDevice.defaultPageSize();
328 const auto pageSizes = printDevice.supportedPageSizes();
329 for (const QPageSize &pageSize : pageSizes)
330 m_ui.pageSizeCombo->addItem(pageSize.name(), QVariant::fromValue(pageSize));
331 if (m_ui.pageSizeCombo->count() > 0) {
332 if (printDevice.supportsCustomPageSizes()) {
333 m_ui.pageSizeCombo->addItem(tr("Custom"));
334 m_realCustomPageSizeIndex = m_ui.pageSizeCombo->count() - 1;
335 }
336 m_blockSignals = false;
337
338 // If the defaultSize is index 0, setCurrentIndex won't emit the currentIndexChanged
339 // signal; workaround the issue by initially setting the currentIndex to -1
340 m_ui.pageSizeCombo->setCurrentIndex(-1);
341 m_ui.pageSizeCombo->setCurrentIndex(m_ui.pageSizeCombo->findData(QVariant::fromValue(defaultSize)));
342 return;
343 }
344 }
345 }
346
347 // If PdfFormat or no available printer page sizes, populate with all page sizes
348 for (int id = 0; id < QPageSize::LastPageSize; ++id) {
349 if (QPageSize::PageSizeId(id) == QPageSize::Custom) {
350 m_ui.pageSizeCombo->addItem(tr("Custom"));
351 m_realCustomPageSizeIndex = m_ui.pageSizeCombo->count() - 1;
352 } else {
353 QPageSize pageSize = QPageSize(QPageSize::PageSizeId(id));
354 m_ui.pageSizeCombo->addItem(pageSize.name(), QVariant::fromValue(pageSize));
355 }
356 }
357
358 m_blockSignals = false;
359}
360
361// Set the dialog to use the given QPrinter
362// Usually only called on first creation
363void QPageSetupWidget::setPrinter(QPrinter *printer, QPrintDevice *printDevice,
364 QPrinter::OutputFormat outputFormat, const QString &printerName)
365{
366 m_printer = printer;
367 m_printDevice = printDevice;
368
369#if QT_CONFIG(cups)
370 // find the PageSize cups option
371 m_pageSizePpdOption = m_printDevice ? QCUPSSupport::findPpdOption(optionName: "PageSize", printDevice: m_printDevice) : nullptr;
372#endif
373
374 // Initialize the layout to the current QPrinter layout
375 m_pageLayout = m_printer->pageLayout();
376
377 // Assume if margins are Points then is by default, so set to locale default units
378 if (m_pageLayout.units() == QPageLayout::Point) {
379 if (QLocale().measurementSystem() == QLocale::MetricSystem)
380 m_pageLayout.setUnits(QPageLayout::Millimeter);
381 else
382 m_pageLayout.setUnits(QPageLayout::Inch);
383 }
384 m_units = m_pageLayout.units();
385 m_pagePreview->setPageLayout(m_pageLayout);
386
387 m_outputFormat = outputFormat;
388 m_printerName = printerName;
389 initPageSizes();
390 updateWidget();
391 updateSavedValues();
392
393 if (m_ui.pageSizeCombo->currentIndex() == -1) {
394 // This can happen in raw printers that since they don't have a default
395 // page size none will get selected so just default to the first size (A4)
396 m_ui.pageSizeCombo->setCurrentIndex(0);
397 }
398}
399
400// Update the widget with the current settings
401// TODO Break up into more intelligent chunks?
402void QPageSetupWidget::updateWidget()
403{
404 m_blockSignals = true;
405
406 QString suffix;
407 switch (m_units) {
408 case QPageLayout::Millimeter:
409 //: Unit 'Millimeter'
410 suffix = tr(s: "mm");
411 break;
412 case QPageLayout::Point:
413 //: Unit 'Points'
414 suffix = tr(s: "pt");
415 break;
416 case QPageLayout::Inch:
417 //: Unit 'Inch'
418 suffix = tr(s: "in");
419 break;
420 case QPageLayout::Pica:
421 //: Unit 'Pica'
422 suffix = tr(s: "P̸");
423 break;
424 case QPageLayout::Didot:
425 //: Unit 'Didot'
426 suffix = tr(s: "DD");
427 break;
428 case QPageLayout::Cicero:
429 //: Unit 'Cicero'
430 suffix = tr(s: "CC");
431 break;
432 }
433
434 m_ui.unitCombo->setCurrentIndex(m_ui.unitCombo->findData(QVariant::fromValue(m_units)));
435
436 const bool isCustom = m_ui.pageSizeCombo->currentIndex() == m_realCustomPageSizeIndex && m_realCustomPageSizeIndex != -1;
437 if (!isCustom)
438 m_ui.pageSizeCombo->setCurrentIndex(m_ui.pageSizeCombo->findData(QVariant::fromValue(m_pageLayout.pageSize())));
439
440 QMarginsF min;
441 QMarginsF max;
442
443 if (m_pageLayout.mode() == QPageLayout::FullPageMode) {
444 min = QMarginsF(0.0, 0.0, 0.0, 0.0);
445 max = QMarginsF(9999.9999, 9999.9999, 9999.9999, 9999.9999);
446 } else {
447 min = m_pageLayout.minimumMargins();
448 max = m_pageLayout.maximumMargins();
449 }
450
451 m_ui.leftMargin->setSuffix(suffix);
452 m_ui.leftMargin->setMinimum(min.left());
453 m_ui.leftMargin->setMaximum(max.left());
454 m_ui.leftMargin->setValue(m_pageLayout.margins().left());
455
456 m_ui.rightMargin->setSuffix(suffix);
457 m_ui.rightMargin->setMinimum(min.right());
458 m_ui.rightMargin->setMaximum(max.right());
459 m_ui.rightMargin->setValue(m_pageLayout.margins().right());
460
461 m_ui.topMargin->setSuffix(suffix);
462 m_ui.topMargin->setMinimum(min.top());
463 m_ui.topMargin->setMaximum(max.top());
464 m_ui.topMargin->setValue(m_pageLayout.margins().top());
465
466 m_ui.bottomMargin->setSuffix(suffix);
467 m_ui.bottomMargin->setMinimum(min.bottom());
468 m_ui.bottomMargin->setMaximum(max.bottom());
469 m_ui.bottomMargin->setValue(m_pageLayout.margins().bottom());
470
471 m_ui.pageWidth->setSuffix(suffix);
472 m_ui.pageWidth->setValue(m_pageLayout.fullRect(m_units).width());
473 m_ui.pageWidth->setEnabled(isCustom);
474 m_ui.widthLabel->setEnabled(isCustom);
475
476 m_ui.pageHeight->setSuffix(suffix);
477 m_ui.pageHeight->setValue(m_pageLayout.fullRect(m_units).height());
478 m_ui.pageHeight->setEnabled(isCustom);
479 m_ui.heightLabel->setEnabled(isCustom);
480
481 m_ui.portrait->setChecked(m_pageLayout.orientation() == QPageLayout::Portrait);
482 m_ui.landscape->setChecked(m_pageLayout.orientation() == QPageLayout::Landscape);
483
484 m_ui.pagesPerSheetButtonGroup->setEnabled(m_outputFormat == QPrinter::NativeFormat);
485
486#ifdef PSD_ENABLE_PAPERSOURCE
487 m_ui.paperSource->setCurrentItem(printer->paperSource());
488#endif
489
490 m_blockSignals = false;
491}
492
493// Set the dialog chosen options on the QPrinter
494// Normally only called when the QPrintDialog or QPageSetupDialog OK button is pressed
495void QPageSetupWidget::setupPrinter() const
496{
497 m_printer->setPageLayout(m_pageLayout);
498 m_printer->setPageOrientation(m_pageLayout.orientation());
499#if QT_CONFIG(cups)
500 QCUPSSupport::PagesPerSheet pagesPerSheet = qvariant_cast<QCUPSSupport::PagesPerSheet>(m_ui.pagesPerSheetCombo->currentData()
501);
502 QCUPSSupport::PagesPerSheetLayout pagesPerSheetLayout = qvariant_cast<QCUPSSupport::PagesPerSheetLayout>(m_ui.pagesPerSheetLayoutCombo->currentData()
503);
504 QCUPSSupport::setPagesPerSheetLayout(printer: m_printer, pagesPerSheet, pagesPerSheetLayout);
505#endif
506#ifdef PSD_ENABLE_PAPERSOURCE
507 m_printer->setPaperSource((QPrinter::PaperSource)m_ui.paperSource->currentIndex());
508#endif
509}
510
511void QPageSetupWidget::updateSavedValues()
512{
513 m_savedUnits = m_units;
514 m_savedPageLayout = m_pageLayout;
515 m_savedPagesPerSheet = m_ui.pagesPerSheetCombo->currentIndex();
516 m_savedPagesPerSheetLayout = m_ui.pagesPerSheetLayoutCombo->currentIndex();
517}
518
519void QPageSetupWidget::revertToSavedValues()
520{
521 m_units = m_savedUnits;
522 m_pageLayout = m_savedPageLayout;
523 m_pagePreview->setPageLayout(m_pageLayout);
524
525 updateWidget();
526
527 m_ui.pagesPerSheetCombo->setCurrentIndex(m_savedPagesPerSheet);
528 m_ui.pagesPerSheetLayoutCombo->setCurrentIndex(m_savedPagesPerSheetLayout);
529}
530
531#if QT_CONFIG(cups)
532bool QPageSetupWidget::hasPpdConflict() const
533{
534 if (m_pageSizePpdOption) {
535 if (m_pageSizePpdOption->conflicted) {
536 const QIcon warning = QApplication::style()->standardIcon(standardIcon: QStyle::SP_MessageBoxWarning, option: nullptr, widget: nullptr);
537 const int pixmap_size = m_ui.pageSizeCombo->sizeHint().height() * .75;
538 m_ui.pageSizeWarningLabel->setPixmap(warning.pixmap(pixmap_size, pixmap_size));
539 } else {
540 m_ui.pageSizeWarningLabel->setPixmap(QPixmap());
541 }
542 return m_pageSizePpdOption->conflicted;
543 }
544
545 return false;
546}
547#endif
548
549// Updates size/preview after the combobox has been changed.
550void QPageSetupWidget::pageSizeChanged()
551{
552 QPageSize pageSize;
553 if (m_ui.pageSizeCombo->currentIndex() != m_realCustomPageSizeIndex) {
554 pageSize = qvariant_cast<QPageSize>(m_ui.pageSizeCombo->currentData());
555
556#if QT_CONFIG(cups)
557 if (m_pageSizePpdOption) {
558 ppd_file_t *ppd = qvariant_cast<ppd_file_t*>(v: m_printDevice->property(PDPK_PpdFile));
559 QStringDecoder toUtf16(ppd->lang_encoding, QStringDecoder::Flag::Stateless);
560 if (!toUtf16.isValid()) {
561 qWarning() << "QPrinSupport: Cups uses unsupported encoding" << ppd->lang_encoding;
562 toUtf16 = QStringDecoder(QStringDecoder::Utf8);
563 }
564 for (int i = 0; i < m_pageSizePpdOption->num_choices; ++i) {
565 const ppd_choice_t *choice = &m_pageSizePpdOption->choices[i];
566 if (toUtf16(choice->text) == m_ui.pageSizeCombo->currentText()) {
567 const auto values = QStringList{} << QString::fromLatin1(ba: m_pageSizePpdOption->keyword)
568 << QString::fromLatin1(ba: choice->choice);
569 m_printDevice->setProperty(PDPK_PpdOption, value: values);
570 emit ppdOptionChanged();
571 break;
572 }
573 }
574 }
575#endif
576
577 } else {
578 QSizeF customSize;
579 if (m_pageLayout.orientation() == QPageLayout::Landscape)
580 customSize = QSizeF(m_ui.pageHeight->value(), m_ui.pageWidth->value());
581 else
582 customSize = QSizeF(m_ui.pageWidth->value(), m_ui.pageHeight->value());
583 pageSize = QPageSize(customSize, QPageSize::Unit(m_units));
584
585#if QT_CONFIG(cups)
586 if (m_pageSizePpdOption) {
587 const auto values = QStringList{} << QString::fromLatin1(ba: m_pageSizePpdOption->keyword)
588 << QStringLiteral("Custom");
589 m_printDevice->setProperty(PDPK_PpdOption, value: values);
590 emit ppdOptionChanged();
591 }
592#endif
593 }
594
595 // We always need to update the m_pageSizePpdOption when the page size changes
596 // even if it's from inside updateWidget, so do not move up
597 if (m_blockSignals)
598 return;
599
600 const QMarginsF printable = m_printDevice ? m_printDevice->printableMargins(pageSize, orientation: m_pageLayout.orientation(), resolution: m_printer->resolution())
601 : QMarginsF();
602 m_pageLayout.setPageSize(pageSize, minMargins: qt_convertMargins(margins: printable, fromUnits: QPageLayout::Point, toUnits: m_pageLayout.units()));
603 m_pagePreview->setPageLayout(m_pageLayout);
604
605 updateWidget();
606}
607
608void QPageSetupWidget::pageOrientationChanged()
609{
610 if (m_blockSignals)
611 return;
612 m_pageLayout.setOrientation(m_ui.portrait->isChecked() ? QPageLayout::Portrait : QPageLayout::Landscape);
613 m_pagePreview->setPageLayout(m_pageLayout);
614 updateWidget();
615}
616
617void QPageSetupWidget::pagesPerSheetChanged()
618{
619#if QT_CONFIG(cups)
620 switch (m_ui.pagesPerSheetCombo->currentData().toInt()) {
621 case QCUPSSupport::OnePagePerSheet:
622 m_pagePreview->setPagePreviewLayout(columns: 1, rows: 1);
623 break;
624 case QCUPSSupport::TwoPagesPerSheet:
625 m_pagePreview->setPagePreviewLayout(columns: 1, rows: 2);
626 break;
627 case QCUPSSupport::FourPagesPerSheet:
628 m_pagePreview->setPagePreviewLayout(columns: 2, rows: 2);
629 break;
630 case QCUPSSupport::SixPagesPerSheet:
631 m_pagePreview->setPagePreviewLayout(columns: 3, rows: 2);
632 break;
633 case QCUPSSupport::NinePagesPerSheet:
634 m_pagePreview->setPagePreviewLayout(columns: 3, rows: 3);
635 break;
636 case QCUPSSupport::SixteenPagesPerSheet:
637 m_pagePreview->setPagePreviewLayout(columns: 4, rows: 4);
638 break;
639 }
640#endif
641}
642
643void QPageSetupWidget::unitChanged()
644{
645 if (m_blockSignals)
646 return;
647 m_units = qvariant_cast<QPageLayout::Unit>(m_ui.unitCombo->currentData());
648 m_pageLayout.setUnits(m_units);
649 updateWidget();
650}
651
652void QPageSetupWidget::topMarginChanged(double newValue)
653{
654 if (m_blockSignals)
655 return;
656 m_pageLayout.setTopMargin(newValue);
657 m_pagePreview->setPageLayout(m_pageLayout);
658}
659
660void QPageSetupWidget::bottomMarginChanged(double newValue)
661{
662 if (m_blockSignals)
663 return;
664 m_pageLayout.setBottomMargin(newValue);
665 m_pagePreview->setPageLayout(m_pageLayout);
666}
667
668void QPageSetupWidget::leftMarginChanged(double newValue)
669{
670 if (m_blockSignals)
671 return;
672 m_pageLayout.setLeftMargin(newValue);
673 m_pagePreview->setPageLayout(m_pageLayout);
674}
675
676void QPageSetupWidget::rightMarginChanged(double newValue)
677{
678 if (m_blockSignals)
679 return;
680 m_pageLayout.setRightMargin(newValue);
681 m_pagePreview->setPageLayout(m_pageLayout);
682}
683
684// QPageSetupDialog
685// - Public Linux / CUPS class implementation
686
687QPageSetupDialog::QPageSetupDialog(QPrinter *printer, QWidget *parent)
688 : QDialog(*(new QUnixPageSetupDialogPrivate(printer)), parent)
689{
690 Q_D(QPageSetupDialog);
691 setWindowTitle(QCoreApplication::translate(context: "QPrintPreviewDialog", key: "Page Setup"));
692 static_cast<QUnixPageSetupDialogPrivate *>(d)->init();
693}
694
695QPageSetupDialog::QPageSetupDialog(QWidget *parent)
696 : QDialog(*(new QUnixPageSetupDialogPrivate(nullptr)), parent)
697{
698 Q_D(QPageSetupDialog);
699 setWindowTitle(QCoreApplication::translate(context: "QPrintPreviewDialog", key: "Page Setup"));
700 static_cast<QUnixPageSetupDialogPrivate *>(d)->init();
701}
702
703int QPageSetupDialog::exec()
704{
705 Q_D(QPageSetupDialog);
706
707 int ret = QDialog::exec();
708 if (ret == Accepted) {
709 static_cast <QUnixPageSetupDialogPrivate*>(d)->widget->setupPrinter();
710 static_cast <QUnixPageSetupDialogPrivate*>(d)->widget->updateSavedValues();
711 } else {
712 static_cast <QUnixPageSetupDialogPrivate*>(d)->widget->revertToSavedValues();
713 }
714 return ret;
715}
716
717QT_END_NAMESPACE
718
719#include "moc_qpagesetupdialog_unix_p.cpp"
720
721#include "moc_qpagesetupdialog.cpp"
722

source code of qtbase/src/printsupport/dialogs/qpagesetupdialog_unix.cpp