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 "qstringconverter.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(QSizePolicy::Expanding, QSizePolicy::Expanding);
106 setMinimumSize(50, 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(width() - 10, height() - 10, Qt::KeepAspectRatio);
127 QRect pageRect = QRect(QPoint(0,0), scaledSize.toSize());
128 pageRect.moveCenter(rect().center());
129 qreal width_factor = scaledSize.width() / pageSize.width();
130 qreal height_factor = scaledSize.height() / pageSize.height();
131 QMarginsF margins = m_pageLayout.margins(QPageLayout::Point);
132 int left = qRound(margins.left() * width_factor);
133 int top = qRound(margins.top() * height_factor);
134 int right = qRound(margins.right() * width_factor);
135 int bottom = qRound(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(i, i, i, i));
144 p.setPen(shadow);
145 p.drawLine(offset.left(), offset.bottom(), offset.right(), offset.bottom());
146 p.drawLine(offset.right(), offset.top(), offset.right(), offset.bottom()-1);
147 }
148 p.fillRect(pageRect, palette().light());
149
150 if (marginRect.isValid()) {
151 p.setPen(QPen(palette().color(QPalette::Dark), 0, Qt::DotLine));
152 p.drawRect(marginRect);
153
154 marginRect.adjust(2, 2, -1, -1);
155 p.setClipRect(marginRect);
156 QFont font;
157 font.setPointSizeF(font.pointSizeF()*0.25);
158 p.setFont(font);
159 p.setPen(palette().color(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(textRect, 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, nullptr, printer->outputFormat(), printer->printerName());
217
218 QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok
219 | QDialogButtonBox::Cancel,
220 Qt::Horizontal, q);
221 QObject::connect(buttons, SIGNAL(accepted()), q, SLOT(accept()));
222 QObject::connect(buttons, SIGNAL(rejected()), 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 QVBoxLayout *lay = new QVBoxLayout(m_ui.preview);
253 m_pagePreview = new QPagePreview(m_ui.preview);
254 m_pagePreview->setPagePreviewLayout(1, 1);
255
256 lay->addWidget(m_pagePreview);
257
258 setAttribute(Qt::WA_WState_Polished, false);
259
260#ifdef PSD_ENABLE_PAPERSOURCE
261 for (int i=0; paperSourceNames[i]; ++i)
262 m_ui.paperSource->insertItem(paperSourceNames[i]);
263#else
264 m_ui.paperSourceLabel->setVisible(false);
265 m_ui.paperSource->setVisible(false);
266#endif
267
268 m_ui.reverseLandscape->setVisible(false);
269 m_ui.reversePortrait->setVisible(false);
270
271 initUnits();
272 initPagesPerSheet();
273
274 connect(m_ui.unitCombo, &QComboBox::activated, this, &QPageSetupWidget::unitChanged);
275
276 connect(m_ui.pageSizeCombo, &QComboBox::currentIndexChanged, this, &QPageSetupWidget::pageSizeChanged);
277 connect(m_ui.pageWidth, &QDoubleSpinBox::valueChanged, this, &QPageSetupWidget::pageSizeChanged);
278 connect(m_ui.pageHeight, &QDoubleSpinBox::valueChanged, this, &QPageSetupWidget::pageSizeChanged);
279
280 connect(m_ui.leftMargin, &QDoubleSpinBox::valueChanged, this, &QPageSetupWidget::leftMarginChanged);
281 connect(m_ui.topMargin, &QDoubleSpinBox::valueChanged, this, &QPageSetupWidget::topMarginChanged);
282 connect(m_ui.rightMargin, &QDoubleSpinBox::valueChanged, this, &QPageSetupWidget::rightMarginChanged);
283 connect(m_ui.bottomMargin, &QDoubleSpinBox::valueChanged, this, &QPageSetupWidget::bottomMarginChanged);
284
285 connect(m_ui.portrait, &QRadioButton::clicked, this, &QPageSetupWidget::pageOrientationChanged);
286 connect(m_ui.landscape, &QRadioButton::clicked, this, &QPageSetupWidget::pageOrientationChanged);
287
288 connect(m_ui.pagesPerSheetCombo, &QComboBox::currentIndexChanged, this, &QPageSetupWidget::pagesPerSheetChanged);
289}
290
291// Init the Units combo box
292void QPageSetupWidget::initUnits()
293{
294 m_ui.unitCombo->addItem(tr("Millimeters (mm)"), QVariant::fromValue(QPageLayout::Millimeter));
295 m_ui.unitCombo->addItem(tr("Inches (in)"), QVariant::fromValue(QPageLayout::Inch));
296 m_ui.unitCombo->addItem(tr("Points (pt)"), QVariant::fromValue(QPageLayout::Point));
297 m_ui.unitCombo->addItem(tr("Pica (P̸)"), QVariant::fromValue(QPageLayout::Pica));
298 m_ui.unitCombo->addItem(tr("Didot (DD)"), QVariant::fromValue(QPageLayout::Didot));
299 m_ui.unitCombo->addItem(tr("Cicero (CC)"), QVariant::fromValue(QPageLayout::Cicero));
300
301 // Initailly default to locale measurement system, mm if metric, in otherwise
302 m_ui.unitCombo->setCurrentIndex(QLocale().measurementSystem() != QLocale::MetricSystem);
303}
304
305// Init the Pages Per Sheet (n-up) combo boxes if using CUPS
306void QPageSetupWidget::initPagesPerSheet()
307{
308#if QT_CONFIG(cups)
309 m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Left to Right, Top to Bottom"),
310 QVariant::fromValue(QCUPSSupport::LeftToRightTopToBottom));
311 m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Left to Right, Bottom to Top"),
312 QVariant::fromValue(QCUPSSupport::LeftToRightBottomToTop));
313 m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Right to Left, Bottom to Top"),
314 QVariant::fromValue(QCUPSSupport::RightToLeftBottomToTop));
315 m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Right to Left, Top to Bottom"),
316 QVariant::fromValue(QCUPSSupport::RightToLeftTopToBottom));
317 m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Bottom to Top, Left to Right"),
318 QVariant::fromValue(QCUPSSupport::BottomToTopLeftToRight));
319 m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Bottom to Top, Right to Left"),
320 QVariant::fromValue(QCUPSSupport::BottomToTopRightToLeft));
321 m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Top to Bottom, Left to Right"),
322 QVariant::fromValue(QCUPSSupport::TopToBottomLeftToRight));
323 m_ui.pagesPerSheetLayoutCombo->addItem(QPrintDialog::tr("Top to Bottom, Right to Left"),
324 QVariant::fromValue(QCUPSSupport::TopToBottomRightToLeft));
325
326 m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr("1 (1x1)"),
327 QVariant::fromValue(QCUPSSupport::OnePagePerSheet));
328 m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr("2 (2x1)"),
329 QVariant::fromValue(QCUPSSupport::TwoPagesPerSheet));
330 m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr("4 (2x2)"),
331 QVariant::fromValue(QCUPSSupport::FourPagesPerSheet));
332 m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr("6 (2x3)"),
333 QVariant::fromValue(QCUPSSupport::SixPagesPerSheet));
334 m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr("9 (3x3)"),
335 QVariant::fromValue(QCUPSSupport::NinePagesPerSheet));
336 m_ui.pagesPerSheetCombo->addItem(QPrintDialog::tr("16 (4x4)"),
337 QVariant::fromValue(QCUPSSupport::SixteenPagesPerSheet));
338
339 // Set to QCUPSSupport::OnePagePerSheet
340 m_ui.pagesPerSheetCombo->setCurrentIndex(0);
341 // Set to QCUPSSupport::LeftToRightTopToBottom
342 m_ui.pagesPerSheetLayoutCombo->setCurrentIndex(0);
343#else
344 // Disable if CUPS wasn't found
345 m_ui.pagesPerSheetButtonGroup->hide();
346#endif
347}
348
349void QPageSetupWidget::initPageSizes()
350{
351 m_blockSignals = true;
352
353 m_ui.pageSizeCombo->clear();
354
355 m_realCustomPageSizeIndex = -1;
356
357 if (m_outputFormat == QPrinter::NativeFormat && !m_printerName.isEmpty()) {
358 QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
359 if (ps) {
360 QPrintDevice printDevice = ps->createPrintDevice(m_printerName);
361 const QPageSize defaultSize = printDevice.defaultPageSize();
362 const auto pageSizes = printDevice.supportedPageSizes();
363 for (const QPageSize &pageSize : pageSizes)
364 m_ui.pageSizeCombo->addItem(pageSize.name(), QVariant::fromValue(pageSize));
365 if (m_ui.pageSizeCombo->count() > 0) {
366 if (printDevice.supportsCustomPageSizes()) {
367 m_ui.pageSizeCombo->addItem(tr("Custom"));
368 m_realCustomPageSizeIndex = m_ui.pageSizeCombo->count() - 1;
369 }
370 m_blockSignals = false;
371
372 // If the defaultSize is index 0, setCurrentIndex won't emit the currentIndexChanged
373 // signal; workaround the issue by initially setting the currentIndex to -1
374 m_ui.pageSizeCombo->setCurrentIndex(-1);
375 m_ui.pageSizeCombo->setCurrentIndex(m_ui.pageSizeCombo->findData(QVariant::fromValue(defaultSize)));
376 return;
377 }
378 }
379 }
380
381 // If PdfFormat or no available printer page sizes, populate with all page sizes
382 for (int id = 0; id < QPageSize::LastPageSize; ++id) {
383 if (QPageSize::PageSizeId(id) == QPageSize::Custom) {
384 m_ui.pageSizeCombo->addItem(tr("Custom"));
385 m_realCustomPageSizeIndex = m_ui.pageSizeCombo->count() - 1;
386 } else {
387 QPageSize pageSize = QPageSize(QPageSize::PageSizeId(id));
388 m_ui.pageSizeCombo->addItem(pageSize.name(), QVariant::fromValue(pageSize));
389 }
390 }
391
392 m_blockSignals = false;
393}
394
395// Set the dialog to use the given QPrinter
396// Usually only called on first creation
397void QPageSetupWidget::setPrinter(QPrinter *printer, QPrintDevice *printDevice,
398 QPrinter::OutputFormat outputFormat, const QString &printerName)
399{
400 m_printer = printer;
401 m_printDevice = printDevice;
402
403#if QT_CONFIG(cups)
404 // find the PageSize cups option
405 m_pageSizePpdOption = m_printDevice ? QCUPSSupport::findPpdOption("PageSize", m_printDevice) : nullptr;
406#endif
407
408 // Initialize the layout to the current QPrinter layout
409 m_pageLayout = m_printer->pageLayout();
410
411 // Assume if margins are Points then is by default, so set to locale default units
412 if (m_pageLayout.units() == QPageLayout::Point) {
413 if (QLocale().measurementSystem() == QLocale::MetricSystem)
414 m_pageLayout.setUnits(QPageLayout::Millimeter);
415 else
416 m_pageLayout.setUnits(QPageLayout::Inch);
417 }
418 m_units = m_pageLayout.units();
419 m_pagePreview->setPageLayout(m_pageLayout);
420
421 m_outputFormat = outputFormat;
422 m_printerName = printerName;
423 initPageSizes();
424 updateWidget();
425 updateSavedValues();
426
427 if (m_ui.pageSizeCombo->currentIndex() == -1) {
428 // This can happen in raw printers that since they don't have a default
429 // page size none will get selected so just default to the first size (A4)
430 m_ui.pageSizeCombo->setCurrentIndex(0);
431 }
432}
433
434// Update the widget with the current settings
435// TODO Break up into more intelligent chunks?
436void QPageSetupWidget::updateWidget()
437{
438 m_blockSignals = true;
439
440 QString suffix;
441 switch (m_units) {
442 case QPageLayout::Millimeter:
443 //: Unit 'Millimeter'
444 suffix = tr("mm");
445 break;
446 case QPageLayout::Point:
447 //: Unit 'Points'
448 suffix = tr("pt");
449 break;
450 case QPageLayout::Inch:
451 //: Unit 'Inch'
452 suffix = tr("in");
453 break;
454 case QPageLayout::Pica:
455 //: Unit 'Pica'
456 suffix = tr("P̸");
457 break;
458 case QPageLayout::Didot:
459 //: Unit 'Didot'
460 suffix = tr("DD");
461 break;
462 case QPageLayout::Cicero:
463 //: Unit 'Cicero'
464 suffix = tr("CC");
465 break;
466 }
467
468 m_ui.unitCombo->setCurrentIndex(m_ui.unitCombo->findData(QVariant::fromValue(m_units)));
469
470 const bool isCustom = m_ui.pageSizeCombo->currentIndex() == m_realCustomPageSizeIndex && m_realCustomPageSizeIndex != -1;
471 if (!isCustom)
472 m_ui.pageSizeCombo->setCurrentIndex(m_ui.pageSizeCombo->findData(QVariant::fromValue(m_pageLayout.pageSize())));
473
474 QMarginsF min;
475 QMarginsF max;
476
477 if (m_pageLayout.mode() == QPageLayout::FullPageMode) {
478 min = QMarginsF(0.0, 0.0, 0.0, 0.0);
479 max = QMarginsF(9999.9999, 9999.9999, 9999.9999, 9999.9999);
480 } else {
481 min = m_pageLayout.minimumMargins();
482 max = m_pageLayout.maximumMargins();
483 }
484
485 m_ui.leftMargin->setSuffix(suffix);
486 m_ui.leftMargin->setMinimum(min.left());
487 m_ui.leftMargin->setMaximum(max.left());
488 m_ui.leftMargin->setValue(m_pageLayout.margins().left());
489
490 m_ui.rightMargin->setSuffix(suffix);
491 m_ui.rightMargin->setMinimum(min.right());
492 m_ui.rightMargin->setMaximum(max.right());
493 m_ui.rightMargin->setValue(m_pageLayout.margins().right());
494
495 m_ui.topMargin->setSuffix(suffix);
496 m_ui.topMargin->setMinimum(min.top());
497 m_ui.topMargin->setMaximum(max.top());
498 m_ui.topMargin->setValue(m_pageLayout.margins().top());
499
500 m_ui.bottomMargin->setSuffix(suffix);
501 m_ui.bottomMargin->setMinimum(min.bottom());
502 m_ui.bottomMargin->setMaximum(max.bottom());
503 m_ui.bottomMargin->setValue(m_pageLayout.margins().bottom());
504
505 m_ui.pageWidth->setSuffix(suffix);
506 m_ui.pageWidth->setValue(m_pageLayout.fullRect(m_units).width());
507 m_ui.pageWidth->setEnabled(isCustom);
508 m_ui.widthLabel->setEnabled(isCustom);
509
510 m_ui.pageHeight->setSuffix(suffix);
511 m_ui.pageHeight->setValue(m_pageLayout.fullRect(m_units).height());
512 m_ui.pageHeight->setEnabled(isCustom);
513 m_ui.heightLabel->setEnabled(isCustom);
514
515 m_ui.portrait->setChecked(m_pageLayout.orientation() == QPageLayout::Portrait);
516 m_ui.landscape->setChecked(m_pageLayout.orientation() == QPageLayout::Landscape);
517
518 m_ui.pagesPerSheetButtonGroup->setEnabled(m_outputFormat == QPrinter::NativeFormat);
519
520#ifdef PSD_ENABLE_PAPERSOURCE
521 m_ui.paperSource->setCurrentItem(printer->paperSource());
522#endif
523
524 m_blockSignals = false;
525}
526
527// Set the dialog chosen options on the QPrinter
528// Normally only called when the QPrintDialog or QPageSetupDialog OK button is pressed
529void QPageSetupWidget::setupPrinter() const
530{
531 m_printer->setPageLayout(m_pageLayout);
532#if QT_CONFIG(cups)
533 QCUPSSupport::PagesPerSheet pagesPerSheet = qvariant_cast<QCUPSSupport::PagesPerSheet>(m_ui.pagesPerSheetCombo->currentData()
534);
535 QCUPSSupport::PagesPerSheetLayout pagesPerSheetLayout = qvariant_cast<QCUPSSupport::PagesPerSheetLayout>(m_ui.pagesPerSheetLayoutCombo->currentData()
536);
537 QCUPSSupport::setPagesPerSheetLayout(m_printer, pagesPerSheet, pagesPerSheetLayout);
538#endif
539#ifdef PSD_ENABLE_PAPERSOURCE
540 m_printer->setPaperSource((QPrinter::PaperSource)m_ui.paperSource->currentIndex());
541#endif
542}
543
544void QPageSetupWidget::updateSavedValues()
545{
546 m_savedUnits = m_units;
547 m_savedPageLayout = m_pageLayout;
548 m_savedPagesPerSheet = m_ui.pagesPerSheetCombo->currentIndex();
549 m_savedPagesPerSheetLayout = m_ui.pagesPerSheetLayoutCombo->currentIndex();
550}
551
552void QPageSetupWidget::revertToSavedValues()
553{
554 m_units = m_savedUnits;
555 m_pageLayout = m_savedPageLayout;
556 m_pagePreview->setPageLayout(m_pageLayout);
557
558 updateWidget();
559
560 m_ui.pagesPerSheetCombo->setCurrentIndex(m_savedPagesPerSheet);
561 m_ui.pagesPerSheetLayoutCombo->setCurrentIndex(m_savedPagesPerSheetLayout);
562}
563
564#if QT_CONFIG(cups)
565bool QPageSetupWidget::hasPpdConflict() const
566{
567 if (m_pageSizePpdOption) {
568 if (m_pageSizePpdOption->conflicted) {
569 const QIcon warning = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, nullptr);
570 const int pixmap_size = m_ui.pageSizeCombo->sizeHint().height() * .75;
571 m_ui.pageSizeWarningLabel->setPixmap(warning.pixmap(pixmap_size, pixmap_size));
572 } else {
573 m_ui.pageSizeWarningLabel->setPixmap(QPixmap());
574 }
575 return m_pageSizePpdOption->conflicted;
576 }
577
578 return false;
579}
580#endif
581
582// Updates size/preview after the combobox has been changed.
583void QPageSetupWidget::pageSizeChanged()
584{
585 QPageSize pageSize;
586 if (m_ui.pageSizeCombo->currentIndex() != m_realCustomPageSizeIndex) {
587 pageSize = qvariant_cast<QPageSize>(m_ui.pageSizeCombo->currentData());
588
589#if QT_CONFIG(cups)
590 if (m_pageSizePpdOption) {
591 ppd_file_t *ppd = qvariant_cast<ppd_file_t*>(m_printDevice->property(PDPK_PpdFile));
592 QStringDecoder toUtf16(ppd->lang_encoding, QStringDecoder::Flag::Stateless);
593 if (!toUtf16.isValid()) {
594 qWarning() << "QPrinSupport: Cups uses unsupported encoding" << ppd->lang_encoding;
595 toUtf16 = QStringDecoder(QStringDecoder::Utf8);
596 }
597 for (int i = 0; i < m_pageSizePpdOption->num_choices; ++i) {
598 const ppd_choice_t *choice = &m_pageSizePpdOption->choices[i];
599 if (toUtf16(choice->text) == m_ui.pageSizeCombo->currentText()) {
600 const auto values = QStringList{} << QString::fromLatin1(m_pageSizePpdOption->keyword)
601 << QString::fromLatin1(choice->choice);
602 m_printDevice->setProperty(PDPK_PpdOption, 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(m_pageSizePpdOption->keyword)
621 << QStringLiteral("Custom");
622 m_printDevice->setProperty(PDPK_PpdOption, 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, m_pageLayout.orientation(), m_printer->resolution())
634 : QMarginsF();
635 m_pageLayout.setPageSize(pageSize, qt_convertMargins(printable, QPageLayout::Point, 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(1, 1);
656 break;
657 case QCUPSSupport::TwoPagesPerSheet:
658 m_pagePreview->setPagePreviewLayout(1, 2);
659 break;
660 case QCUPSSupport::FourPagesPerSheet:
661 m_pagePreview->setPagePreviewLayout(2, 2);
662 break;
663 case QCUPSSupport::SixPagesPerSheet:
664 m_pagePreview->setPagePreviewLayout(3, 2);
665 break;
666 case QCUPSSupport::NinePagesPerSheet:
667 m_pagePreview->setPagePreviewLayout(3, 3);
668 break;
669 case QCUPSSupport::SixteenPagesPerSheet:
670 m_pagePreview->setPagePreviewLayout(4, 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>(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("QPrintPreviewDialog", "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("QPrintPreviewDialog", "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