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

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