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 | |
61 | QT_BEGIN_NAMESPACE |
62 | |
63 | extern 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 |
69 | static 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 | |
86 | struct 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 | |
100 | class QPagePreview : public QWidget |
101 | { |
102 | public: |
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 | |
122 | protected: |
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 = 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 | |
179 | private: |
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 | |
191 | class QUnixPageSetupDialogPrivate : public QPageSetupDialogPrivate |
192 | { |
193 | Q_DECLARE_PUBLIC(QPageSetupDialog) |
194 | |
195 | public: |
196 | QUnixPageSetupDialogPrivate(QPrinter *printer); |
197 | ~QUnixPageSetupDialogPrivate(); |
198 | void init(); |
199 | |
200 | QPageSetupWidget *widget; |
201 | }; |
202 | |
203 | QUnixPageSetupDialogPrivate::QUnixPageSetupDialogPrivate(QPrinter *printer) : QPageSetupDialogPrivate(printer) |
204 | { |
205 | } |
206 | |
207 | QUnixPageSetupDialogPrivate::~QUnixPageSetupDialogPrivate() |
208 | { |
209 | } |
210 | |
211 | void 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 | |
234 | QPageSetupWidget::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 |
295 | void 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 |
309 | void 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 | |
352 | void 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 |
400 | void 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? |
439 | void 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 |
532 | void 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 | |
548 | void 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 | |
556 | void 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) |
569 | bool 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. |
587 | void 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 | |
641 | void 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 | |
650 | void 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 | |
676 | void 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 | |
685 | void QPageSetupWidget::topMarginChanged(double newValue) |
686 | { |
687 | if (m_blockSignals) |
688 | return; |
689 | m_pageLayout.setTopMargin(newValue); |
690 | m_pagePreview->setPageLayout(m_pageLayout); |
691 | } |
692 | |
693 | void QPageSetupWidget::bottomMarginChanged(double newValue) |
694 | { |
695 | if (m_blockSignals) |
696 | return; |
697 | m_pageLayout.setBottomMargin(newValue); |
698 | m_pagePreview->setPageLayout(m_pageLayout); |
699 | } |
700 | |
701 | void QPageSetupWidget::leftMarginChanged(double newValue) |
702 | { |
703 | if (m_blockSignals) |
704 | return; |
705 | m_pageLayout.setLeftMargin(newValue); |
706 | m_pagePreview->setPageLayout(m_pageLayout); |
707 | } |
708 | |
709 | void 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 | |
720 | QPageSetupDialog::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 | |
728 | QPageSetupDialog::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 | |
736 | int 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 | |
750 | QT_END_NAMESPACE |
751 | |
752 | #include "moc_qpagesetupdialog.cpp" |
753 | |