Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qprintdialog_unix.cpp
Go to the documentation of this file.
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// Qt-Security score:significant reason:default
4
5#include "qplatformdefs.h"
6#include <QtPrintSupport/private/qtprintsupportglobal_p.h>
7
8#include "private/qabstractprintdialog_p.h"
9#if QT_CONFIG(messagebox)
10#include <QtWidgets/qmessagebox.h>
11#endif
12#include "qprintdialog.h"
13#if QT_CONFIG(filedialog)
14#include "qfiledialog.h"
15#endif
16#include <QtCore/qdebug.h>
17#include <QtCore/qdir.h>
18#include <QtCore/qglobal.h>
19#include <QtCore/qstringconverter.h>
20#include <QtGui/qevent.h>
21#if QT_CONFIG(filesystemmodel)
22#include <QtGui/qfilesystemmodel.h>
23#endif
24#include <QtWidgets/qstyleditemdelegate.h>
25#include <QtWidgets/qformlayout.h>
26#include <QtPrintSupport/qprinter.h>
27
28#include <qpa/qplatformprintplugin.h>
29#include <qpa/qplatformprintersupport.h>
30
31#include <private/qprintdevice_p.h>
32
33#include <QtWidgets/qdialogbuttonbox.h>
34
35#if QT_CONFIG(regularexpression)
36#include <qregularexpression.h>
37#endif
38
39#if QT_CONFIG(completer)
40#include <private/qcompleter_p.h>
41#endif
42#include "ui_qprintpropertieswidget.h"
43#include "ui_qprintsettingsoutput.h"
44#include "ui_qprintwidget.h"
45
46#if QT_CONFIG(cups)
48#include <private/qcups_p.h>
49#if QT_CONFIG(cupsjobwidget)
50#include "qcupsjobwidget_p.h"
51#endif
52#endif
53
54/*
55
56Print dialog class declarations
57
58 QPrintDialog: The main Print Dialog, nothing really held here.
59
60 QUnixPrintWidget:
61 QUnixPrintWidgetPrivate: The real Unix Print Dialog implementation.
62
63 Directly includes the upper half of the Print Dialog
64 containing the Printer Selection widgets and
65 Properties button.
66
67 Embeds the Properties pop-up dialog from
68 QPrintPropertiesDialog
69
70 Embeds the lower half from separate widget class
71 QPrintDialogPrivate
72
73 Layout in qprintwidget.ui
74
75 QPrintDialogPrivate: The lower half of the Print Dialog containing the
76 Copies and Options tabs that expands when the
77 Options button is selected.
78
79 Layout in qprintsettingsoutput.ui
80
81 QPrintPropertiesDialog: Dialog displayed when clicking on Properties button to
82 allow editing of Page and Advanced tabs.
83
84 Layout in qprintpropertieswidget.ui
85*/
86
88{
89 Q_INIT_RESOURCE(qprintdialog);
90}
91
92QT_BEGIN_NAMESPACE
93
94using namespace Qt::StringLiterals;
95
97{
99public:
104
105 void setupPrinter() const;
106
107private slots:
110
111private:
112 void showEvent(QShowEvent *event) override;
113
115#if QT_CONFIG(cups)
117#endif
118 Ui::QPrintPropertiesWidget widget;
119 QDialogButtonBox *m_buttons;
120#if QT_CONFIG(cupsjobwidget)
122#endif
123
124#if QT_CONFIG(cups)
129 bool anyPpdOptionConflict() const;
130 bool anyAdvancedOptionConflict() const;
131
133
136#endif
137};
138
140
142{
144
145public:
149
150private:
151 friend class QPrintDialog;
155 Q_PRIVATE_SLOT(d, void _q_printerChanged(int))
158};
159
193
195{
196 Q_DECLARE_PUBLIC(QPrintDialog)
198public:
201
202 void init();
203
204 void selectPrinter(const QPrinter::OutputFormat outputFormat);
205
207#if QT_CONFIG(messagebox)
208 void _q_checkFields();
209#endif
211
212#if QT_CONFIG(cups)
214#endif
217
218 virtual void setTabs(const QList<QWidget*> &tabs) override;
219
224 QPushButton *collapseButton;
226private:
227 void setExplicitDuplexMode(QPrint::DuplexMode duplexMode);
228 // duplex mode explicitly set by user, QPrint::DuplexAuto otherwise
229 QPrint::DuplexMode explicitDuplexMode;
230};
231
232////////////////////////////////////////////////////////////////////////////////
233////////////////////////////////////////////////////////////////////////////////
234
235/*
236
237 QPrintPropertiesDialog
238
239 Dialog displayed when clicking on Properties button to allow editing of Page
240 and Advanced tabs.
241
242*/
243
244QPrintPropertiesDialog::QPrintPropertiesDialog(QPrinter *printer, QPrintDevice *currentPrintDevice,
245 QPrinter::OutputFormat outputFormat, const QString &printerName,
246 QAbstractPrintDialog *parent)
247 : QDialog(parent)
248#if QT_CONFIG(cups)
249 , m_printer(printer)
250#endif
251{
252 setWindowTitle(tr("Printer Properties"));
253 QVBoxLayout *lay = new QVBoxLayout(this);
254 QWidget *content = new QWidget(this);
255 widget.setupUi(content);
256 m_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
257 lay->addWidget(content);
258 lay->addWidget(m_buttons);
259
260 connect(m_buttons->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &QPrintPropertiesDialog::accept);
261 connect(m_buttons->button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &QPrintPropertiesDialog::reject);
262
263 widget.pageSetup->setPrinter(printer, currentPrintDevice, outputFormat, printerName);
264
265#if QT_CONFIG(cupsjobwidget)
266 m_jobOptions = new QCupsJobWidget(printer, currentPrintDevice);
267 widget.tabs->insertTab(1, m_jobOptions, tr("Job Options"));
268#endif
269
270 const int advancedTabIndex = widget.tabs->indexOf(widget.cupsPropertiesPage);
271#if QT_CONFIG(cups)
272 m_currentPrintDevice = currentPrintDevice;
273 const bool anyWidgetCreated = createAdvancedOptionsWidget();
274
275 widget.tabs->setTabEnabled(advancedTabIndex, anyWidgetCreated);
276
277 connect(widget.pageSetup, &QPageSetupWidget::ppdOptionChanged, this, [this] {
278 widget.conflictsLabel->setVisible(anyPpdOptionConflict());
279 });
280
281#else
282 Q_UNUSED(currentPrintDevice);
283 widget.tabs->setTabEnabled(advancedTabIndex, false);
284#endif
285}
286
290
292{
293#if QT_CONFIG(cups)
294 QCUPSSupport::clearCupsOptions(m_printer);
295#endif
296
297 widget.pageSetup->setupPrinter();
298#if QT_CONFIG(cupsjobwidget)
299 m_jobOptions->setupPrinter();
300#endif
301
302#if QT_CONFIG(cups)
303 // Set Color by default, that will change if the "ColorModel" property is available
304 m_printer->setColorMode(QPrinter::Color);
305
306 setPrinterAdvancedCupsOptions();
307#endif
308}
309
311{
312 widget.pageSetup->revertToSavedValues();
313
314#if QT_CONFIG(cupsjobwidget)
315 m_jobOptions->revertToSavedValues();
316#endif
317
318#if QT_CONFIG(cups)
319 revertAdvancedOptionsToSavedValues();
320#endif
321 QDialog::reject();
322}
323
325{
326#if QT_CONFIG(cups) && QT_CONFIG(messagebox)
327 if (widget.pageSetup->hasPpdConflict()) {
328 widget.tabs->setCurrentWidget(widget.tabPage);
329 const QMessageBox::StandardButton answer = QMessageBox::warning(this, tr("Page Setup Conflicts"),
330 tr("There are conflicts in page setup options. Do you want to fix them?"),
331 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
332 if (answer != QMessageBox::No)
333 return;
334 } else if (anyAdvancedOptionConflict()) {
335 widget.tabs->setCurrentWidget(widget.cupsPropertiesPage);
336 const QMessageBox::StandardButton answer = QMessageBox::warning(this, tr("Advanced Option Conflicts"),
337 tr("There are conflicts in some advanced options. Do you want to fix them?"),
338 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
339 if (answer != QMessageBox::No)
340 return;
341 }
342 advancedOptionsUpdateSavedValues();
343#endif
344
345#if QT_CONFIG(cupsjobwidget)
346 m_jobOptions->updateSavedValues();
347#endif
348
349 widget.pageSetup->updateSavedValues();
350
351 QDialog::accept();
352}
353
354void QPrintPropertiesDialog::showEvent(QShowEvent *event)
355{
356#if QT_CONFIG(cups)
357 widget.conflictsLabel->setVisible(anyPpdOptionConflict());
358#endif
359 QDialog::showEvent(event);
360}
361
362#if QT_CONFIG(cups)
363
364// Used to store the ppd_option_t for each QComboBox that represents an advanced option
365static const char *ppdOptionProperty = "_q_ppd_option";
366
367// Used to store the originally selected choice index for each QComboBox that represents an advanced option
368static const char *ppdOriginallySelectedChoiceProperty = "_q_ppd_originally_selected_choice";
369
370// Used to store the warning label pointer for each QComboBox that represents an advanced option
371static const char *warningLabelProperty = "_q_warning_label";
372
373static bool isBlacklistedGroup(const ppd_group_t *group) noexcept
374{
375 return qstrcmp(group->name, "InstallableOptions") == 0;
376};
377
378static bool isBlacklistedOption(const char *keyword) noexcept
379{
380 // We already let the user set these options elsewhere
381 const char *cupsOptionBlacklist[] = {
382 "Collate",
383 "Copies",
384 "OutputOrder",
385 "PageRegion",
386 "PageSize",
387 "Duplex" // handled by the main dialog
388 };
389 auto equals = [](const char *keyword) {
390 return [keyword](const char *candidate) {
391 return qstrcmp(keyword, candidate) == 0;
392 };
393 };
394 return std::any_of(std::begin(cupsOptionBlacklist), std::end(cupsOptionBlacklist), equals(keyword));
395};
396
397bool QPrintPropertiesDialog::createAdvancedOptionsWidget()
398{
399 bool anyWidgetCreated = false;
400
401 ppd_file_t *ppd = qvariant_cast<ppd_file_t*>(m_currentPrintDevice->property(PDPK_PpdFile));
402
403 if (ppd) {
404 toUnicode = QStringDecoder(ppd->lang_encoding, QStringDecoder::Flag::Stateless);
405 if (!toUnicode.isValid()) {
406 qWarning() << "QPrinSupport: Cups uses unsupported encoding" << ppd->lang_encoding;
407 toUnicode = QStringDecoder(QStringDecoder::Utf8, QStringDecoder::Flag::Stateless);
408 }
409
410 QWidget *holdingWidget = new QWidget();
411 QVBoxLayout *layout = new QVBoxLayout(holdingWidget);
412
413 for (int i = 0; i < ppd->num_groups; ++i) {
414 const ppd_group_t *group = &ppd->groups[i];
415
416 if (!isBlacklistedGroup(group)) {
417 QFormLayout *groupLayout = new QFormLayout();
418
419 for (int i = 0; i < group->num_options; ++i) {
420 const ppd_option_t *option = &group->options[i];
421
422 if (!isBlacklistedOption(option->keyword)) {
423 QComboBox *choicesCb = new QComboBox();
424
425 const auto setPpdOptionFromCombo = [this, choicesCb, option] {
426 // We can't use choicesCb->currentIndex() to know the index of the option in the choices[] array
427 // because some of them may not be present in the list because they conflict with the
428 // installable options so use the index passed on addItem
429 const int selectedChoiceIndex = choicesCb->currentData().toInt();
430 const auto values = QStringList{} << QString::fromLatin1(option->keyword)
431 << QString::fromLatin1(option->choices[selectedChoiceIndex].choice);
432 m_currentPrintDevice->setProperty(PDPK_PpdOption, values);
433 widget.conflictsLabel->setVisible(anyPpdOptionConflict());
434 };
435
436 bool foundMarkedChoice = false;
437 bool markedChoiceNotAvailable = false;
438 for (int i = 0; i < option->num_choices; ++i) {
439 const ppd_choice_t *choice = &option->choices[i];
440 const auto values = QStringList{} << QString::fromLatin1(option->keyword) << QString::fromLatin1(choice->choice);
441 const bool choiceIsInstallableConflict = m_currentPrintDevice->isFeatureAvailable(PDPK_PpdChoiceIsInstallableConflict, values);
442 if (choiceIsInstallableConflict && static_cast<int>(choice->marked) == 1) {
443 markedChoiceNotAvailable = true;
444 } else if (!choiceIsInstallableConflict) {
445 choicesCb->addItem(toUnicode(choice->text), i);
446 if (static_cast<int>(choice->marked) == 1) {
447 choicesCb->setCurrentIndex(choicesCb->count() - 1);
448 choicesCb->setProperty(ppdOriginallySelectedChoiceProperty, QVariant(i));
449 foundMarkedChoice = true;
450 } else if (!foundMarkedChoice && qstrcmp(choice->choice, option->defchoice) == 0) {
451 choicesCb->setCurrentIndex(choicesCb->count() - 1);
452 choicesCb->setProperty(ppdOriginallySelectedChoiceProperty, QVariant(i));
453 }
454 }
455 }
456
457 if (markedChoiceNotAvailable) {
458 // If the user default option is not available because of it conflicting with
459 // the installed options, we need to set the internal ppd value to the value
460 // being shown in the combo
461 setPpdOptionFromCombo();
462 }
463
464 if (choicesCb->count() > 1) {
465
466 connect(choicesCb, &QComboBox::currentIndexChanged, this, setPpdOptionFromCombo);
467
468 // We need an extra label at the end to show the conflict warning
469 QWidget *choicesCbWithLabel = new QWidget();
470 QHBoxLayout *choicesCbWithLabelLayout = new QHBoxLayout(choicesCbWithLabel);
471 choicesCbWithLabelLayout->setContentsMargins(0, 0, 0, 0);
472 QLabel *warningLabel = new QLabel();
473 choicesCbWithLabelLayout->addWidget(choicesCb);
474 choicesCbWithLabelLayout->addWidget(warningLabel);
475
476 QLabel *optionLabel = new QLabel(toUnicode(option->text));
477 optionLabel->setBuddy(choicesCb);
478 groupLayout->addRow(optionLabel, choicesCbWithLabel);
479 anyWidgetCreated = true;
480 choicesCb->setProperty(ppdOptionProperty, QVariant::fromValue(option));
481 choicesCb->setProperty(warningLabelProperty, QVariant::fromValue(warningLabel));
482 m_advancedOptionsCombos << choicesCb;
483 } else {
484 delete choicesCb;
485 }
486 }
487 }
488
489 if (groupLayout->rowCount() > 0) {
490 QGroupBox *groupBox = new QGroupBox(toUnicode(group->text));
491 groupBox->setLayout(groupLayout);
492 layout->addWidget(groupBox);
493 } else {
494 delete groupLayout;
495 }
496 }
497 }
498
499 layout->addStretch();
500 widget.scrollArea->setWidget(holdingWidget);
501 }
502
503 return anyWidgetCreated;
504}
505
506void QPrintPropertiesDialog::setPrinterAdvancedCupsOptions() const
507{
508 for (const QComboBox *choicesCb : m_advancedOptionsCombos) {
509 const ppd_option_t *option = qvariant_cast<const ppd_option_t *>(choicesCb->property(ppdOptionProperty));
510
511 // We can't use choicesCb->currentIndex() to know the index of the option in the choices[] array
512 // because some of them may not be present in the list because they conflict with the
513 // installable options so use the index passed on addItem
514 const int selectedChoiceIndex = choicesCb->currentData().toInt();
515 const char *selectedChoice = option->choices[selectedChoiceIndex].choice;
516
517 if (qstrcmp(option->keyword, "ColorModel") == 0)
518 m_printer->setColorMode(qstrcmp(selectedChoice, "Gray") == 0 ? QPrinter::GrayScale : QPrinter::Color);
519
520 if (qstrcmp(option->defchoice, selectedChoice) != 0)
521 QCUPSSupport::setCupsOption(m_printer, QString::fromLatin1(option->keyword), QString::fromLatin1(selectedChoice));
522 }
523}
524
525void QPrintPropertiesDialog::revertAdvancedOptionsToSavedValues() const
526{
527 for (QComboBox *choicesCb : m_advancedOptionsCombos) {
528 const int originallySelectedChoice = qvariant_cast<int>(choicesCb->property(ppdOriginallySelectedChoiceProperty));
529 const int newComboIndexToSelect = choicesCb->findData(originallySelectedChoice);
530 choicesCb->setCurrentIndex(newComboIndexToSelect);
531 // The currentIndexChanged lambda takes care of resetting the ppd option
532 }
533 widget.conflictsLabel->setVisible(anyPpdOptionConflict());
534}
535
536void QPrintPropertiesDialog::advancedOptionsUpdateSavedValues() const
537{
538 for (QComboBox *choicesCb : m_advancedOptionsCombos)
539 choicesCb->setProperty(ppdOriginallySelectedChoiceProperty, choicesCb->currentData());
540}
541
542bool QPrintPropertiesDialog::anyPpdOptionConflict() const
543{
544 // we need to execute both since besides returning true/false they update the warning icons
545 const bool pageSetupConflicts = widget.pageSetup->hasPpdConflict();
546 const bool advancedOptionConflicts = anyAdvancedOptionConflict();
547 return pageSetupConflicts || advancedOptionConflicts;
548}
549
550bool QPrintPropertiesDialog::anyAdvancedOptionConflict() const
551{
552 const QIcon warning = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, nullptr);
553
554 bool anyConflicted = false;
555
556 for (const QComboBox *choicesCb : m_advancedOptionsCombos) {
557 const ppd_option_t *option = qvariant_cast<const ppd_option_t *>(choicesCb->property(ppdOptionProperty));
558 QLabel *warningLabel = qvariant_cast<QLabel *>(choicesCb->property(warningLabelProperty));
559 if (option->conflicted) {
560 anyConflicted = true;
561 const int pixmap_size = choicesCb->sizeHint().height() * .75;
562 warningLabel->setPixmap(warning.pixmap(pixmap_size, pixmap_size));
563 } else {
564 warningLabel->setPixmap(QPixmap());
565 }
566 }
567
568 return anyConflicted;
569}
570
571#endif
572
573
574////////////////////////////////////////////////////////////////////////////////
575////////////////////////////////////////////////////////////////////////////////
576
577/*
578
579 QPrintDialogPrivate
580
581 The lower half of the Print Dialog containing the Copies and Options
582 tabs that expands when the Options button is selected.
583
584*/
585QPrintDialogPrivate::QPrintDialogPrivate()
586 : top(nullptr), bottom(nullptr), buttons(nullptr), collapseButton(nullptr),
587 explicitDuplexMode(QPrint::DuplexAuto)
588{
590}
591
595
597{
598 Q_Q(QPrintDialog);
599
600 top = new QUnixPrintWidget(q->printer(), q);
601 bottom = new QWidget(q);
602 options.setupUi(bottom);
603 options.color->setIconSize(QSize(32, 32));
604 options.color->setIcon(QIcon(":/qt-project.org/dialogs/qprintdialog/images/status-color.png"_L1));
605 options.grayscale->setIconSize(QSize(32, 32));
606 options.grayscale->setIcon(QIcon(":/qt-project.org/dialogs/qprintdialog/images/status-gray-scale.png"_L1));
607
608#if QT_CONFIG(cups)
609 // Add Page Set widget if CUPS is available
610 options.pageSetCombo->addItem(tr("All Pages"), QVariant::fromValue(QCUPSSupport::AllPages));
611 options.pageSetCombo->addItem(tr("Odd Pages"), QVariant::fromValue(QCUPSSupport::OddPages));
612 options.pageSetCombo->addItem(tr("Even Pages"), QVariant::fromValue(QCUPSSupport::EvenPages));
613#else
614 delete options.pagesRadioButton;
615 delete options.pagesLineEdit;
616 options.pagesRadioButton = nullptr;
617 options.pagesLineEdit = nullptr;
618#endif
619
621
622 buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, q);
623 collapseButton = new QPushButton(QPrintDialog::tr("&Options >>"), buttons);
624 buttons->addButton(collapseButton, QDialogButtonBox::ResetRole);
625 bottom->setVisible(false);
626
627 QPushButton *printButton = buttons->button(QDialogButtonBox::Ok);
628 printButton->setText(QPrintDialog::tr("&Print"));
629 printButton->setDefault(true);
630
631 QVBoxLayout *lay = new QVBoxLayout(q);
632 lay->addWidget(top);
633 lay->addWidget(bottom);
634 lay->addWidget(buttons);
635
636#if !QT_CONFIG(messagebox)
637 QObject::connect(buttons, SIGNAL(accepted()), q, SLOT(accept()));
638#else
639 QObject::connect(buttons, SIGNAL(accepted()), q, SLOT(_q_checkFields()));
640#endif
641 QObject::connect(buttons, SIGNAL(rejected()), q, SLOT(reject()));
642
643 QObject::connect(options.printSelection, SIGNAL(toggled(bool)),
644 q, SLOT(_q_togglePageSetCombo(bool)));
645
646 QObject::connect(options.printCurrentPage, SIGNAL(toggled(bool)),
647 q, SLOT(_q_togglePageSetCombo(bool)));
648
649 QObject::connect(collapseButton, SIGNAL(released()), q, SLOT(_q_collapseOrExpandDialog()));
650
651 QObject::connect(options.noDuplex, &QAbstractButton::clicked, q, [this] { setExplicitDuplexMode(QPrint::DuplexNone); });
652 QObject::connect(options.duplexLong, &QAbstractButton::clicked, q, [this] { setExplicitDuplexMode(QPrint::DuplexLongSide); });
653 QObject::connect(options.duplexShort, &QAbstractButton::clicked, q, [this] { setExplicitDuplexMode(QPrint::DuplexShortSide); });
654
655#if QT_CONFIG(cups)
656 QObject::connect(options.noDuplex, &QAbstractButton::toggled, q, [this] { updatePpdDuplexOption(options.noDuplex); });
657 QObject::connect(options.duplexLong, &QAbstractButton::toggled, q, [this] { updatePpdDuplexOption(options.duplexLong); });
658 QObject::connect(options.duplexShort, &QAbstractButton::toggled, q, [this] { updatePpdDuplexOption(options.duplexShort); });
659#endif
660}
661
662// initialize printer options
663void QPrintDialogPrivate::selectPrinter(const QPrinter::OutputFormat outputFormat)
664{
665 Q_Q(QPrintDialog);
666 QPrinter *p = q->printer();
667 printerOutputFormat = outputFormat;
668
669 // printer supports duplex mode?
670 const auto supportedDuplexMode = top->d->m_currentPrintDevice.supportedDuplexModes();
671 options.duplexLong->setEnabled(supportedDuplexMode.contains(QPrint::DuplexLongSide));
672 options.duplexShort->setEnabled(supportedDuplexMode.contains(QPrint::DuplexShortSide));
673
674 if (p->colorMode() == QPrinter::Color)
675 options.color->setChecked(true);
676 else
677 options.grayscale->setChecked(true);
678
679 // duplex priorities to be as follows:
680 // 1) a user-selected duplex value in the dialog has highest priority
681 // 2) duplex value set in the QPrinter
682 QPrint::DuplexMode duplex;
683 if (explicitDuplexMode != QPrint::DuplexAuto && supportedDuplexMode.contains(explicitDuplexMode))
684 duplex = explicitDuplexMode;
685 else
686 duplex = static_cast<QPrint::DuplexMode>(p->duplex());
687 switch (duplex) {
688 case QPrint::DuplexNone:
689 options.noDuplex->setChecked(true); break;
690 case QPrint::DuplexLongSide:
691 case QPrint::DuplexAuto:
692 options.duplexLong->setChecked(true); break;
693 case QPrint::DuplexShortSide:
694 options.duplexShort->setChecked(true); break;
695 }
696 options.copies->setValue(p->copyCount());
697 options.collate->setChecked(p->collateCopies());
698 options.reverse->setChecked(p->pageOrder() == QPrinter::LastPageFirst);
699
700 if (outputFormat == QPrinter::PdfFormat || options.printSelection->isChecked()
701 || options.printCurrentPage->isChecked())
702
703 options.pageSetCombo->setEnabled(false);
704 else
705 options.pageSetCombo->setEnabled(true);
706
707#if QT_CONFIG(cups)
708 // Disable complex page ranges widget when printing to pdf
709 // It doesn't work since it relies on cups to do the heavy lifting and cups
710 // is not used when printing to PDF
711 options.pagesRadioButton->setEnabled(outputFormat != QPrinter::PdfFormat);
712
713 // Disable color options on main dialog if not printing to file, it will be handled by CUPS advanced dialog
714 options.colorMode->setVisible(outputFormat == QPrinter::PdfFormat);
715#endif
716}
717
718#if QT_CONFIG(cups)
719
720void QPrintDialogPrivate::updatePpdDuplexOption(QRadioButton *radio)
721{
722 const bool checked = radio->isChecked();
723 if (checked) {
724 if (radio == options.noDuplex) top->d->setPpdDuplex(QPrinter::DuplexNone);
725 else if (radio == options.duplexLong) top->d->setPpdDuplex(QPrinter::DuplexLongSide);
726 else if (radio == options.duplexShort) top->d->setPpdDuplex(QPrinter::DuplexShortSide);
727 }
728 const bool conflict = checked && top->d->m_duplexPpdOption && top->d->m_duplexPpdOption->conflicted;
729 radio->setIcon(conflict ? QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, nullptr) : QIcon());
730}
731
732#endif
733
734void QPrintDialogPrivate::setExplicitDuplexMode(const QPrint::DuplexMode duplexMode)
735{
736 explicitDuplexMode = duplexMode;
737}
738
740{
741 // First setup the requested OutputFormat, Printer and Page Size first
743
744 // Then setup Print Job options
745 Q_Q(QPrintDialog);
746 QPrinter* p = q->printer();
747
748 if (options.duplex->isEnabled()) {
749 if (options.noDuplex->isChecked())
750 p->setDuplex(QPrinter::DuplexNone);
751 else if (options.duplexLong->isChecked())
752 p->setDuplex(QPrinter::DuplexLongSide);
753 else
754 p->setDuplex(QPrinter::DuplexShortSide);
755 }
756
757#if QT_CONFIG(cups)
758 // When printing to a device the colorMode will be set by the advanced panel
759 if (p->outputFormat() == QPrinter::PdfFormat)
760#endif
761 p->setColorMode(options.color->isChecked() ? QPrinter::Color : QPrinter::GrayScale);
762
763 p->setPageOrder(options.reverse->isChecked() ? QPrinter::LastPageFirst : QPrinter::FirstPageFirst);
764
765 // print range
766 if (options.printAll->isChecked()) {
767 p->setPrintRange(QPrinter::AllPages);
768 p->setPageRanges(QPageRanges());
769 } else if (options.printSelection->isChecked()) {
770 p->setPrintRange(QPrinter::Selection);
771 p->setPageRanges(QPageRanges());
772 } else if (options.printCurrentPage->isChecked()) {
773 p->setPrintRange(QPrinter::CurrentPage);
774 p->setPageRanges(QPageRanges());
775 } else if (options.printRange->isChecked()) {
776 if (q->testOption(QPrintDialog::PrintPageRange)) {
777 p->setPrintRange(QPrinter::PageRange);
778 p->setFromTo(options.from->value(), qMax(options.from->value(), options.to->value()));
779 } else {
780 // This case happens when CUPS server-side page range is enabled
781 // Setting the range to the printer occurs below
782 p->setPrintRange(QPrinter::AllPages);
783 p->setPageRanges(QPageRanges());
784 }
785 }
786
787#if QT_CONFIG(cups)
788 if (options.pagesRadioButton->isChecked()) {
789 const QPageRanges ranges = QPageRanges::fromString(options.pagesLineEdit->text());
790 p->setPrintRange(QPrinter::AllPages);
791 p->setPageRanges(QPageRanges());
792
793 // server-side page filtering
794 QCUPSSupport::setPageRange(p, ranges.toString());
795 }
796
797 // page set
798 if (p->printRange() == QPrinter::AllPages || p->printRange() == QPrinter::PageRange) {
799 //If the application is selecting pages and the first page number is even then need to adjust the odd-even accordingly
800 QCUPSSupport::PageSet pageSet = qvariant_cast<QCUPSSupport::PageSet>(options.pageSetCombo->itemData(options.pageSetCombo->currentIndex()));
801 if (q->testOption(QPrintDialog::PrintPageRange)
802 && p->printRange() == QPrinter::PageRange
803 && (q->fromPage() % 2 == 0)) {
804
805 switch (pageSet) {
806 case QCUPSSupport::AllPages:
807 break;
808 case QCUPSSupport::OddPages:
809 QCUPSSupport::setPageSet(p, QCUPSSupport::EvenPages);
810 break;
811 case QCUPSSupport::EvenPages:
812 QCUPSSupport::setPageSet(p, QCUPSSupport::OddPages);
813 break;
814 }
815 } else if (pageSet != QCUPSSupport::AllPages) {
816 QCUPSSupport::setPageSet(p, pageSet);
817 }
818
819 // server-side page range, since we set the page range on the printer to 0-0/AllPages above,
820 // we need to take the values directly from the widget as q->fromPage() will return 0
821 if (!q->testOption(QPrintDialog::PrintPageRange) && options.printRange->isChecked())
822 QCUPSSupport::setPageRange(p, options.from->value(), qMax(options.from->value(), options.to->value()));
823 }
824#endif
825
826 // copies
827 p->setCopyCount(options.copies->value());
828 p->setCollateCopies(options.collate->isChecked());
829}
830
832{
833 if (printerOutputFormat == QPrinter::PdfFormat)
834 return;
835
836 options.pageSetCombo->setDisabled(checked);
837}
838
840{
841 int collapseHeight = 0;
842 Q_Q(QPrintDialog);
843 QWidget *widgetToHide = bottom;
844 if (widgetToHide->isVisible()) {
845 collapseButton->setText(QPrintDialog::tr("&Options >>"));
846 collapseHeight = widgetToHide->y() + widgetToHide->height() - (top->y() + top->height());
847 }
848 else
849 collapseButton->setText(QPrintDialog::tr("&Options <<"));
850 widgetToHide->setVisible(! widgetToHide->isVisible());
851 if (! widgetToHide->isVisible()) { // make it shrink
852 q->layout()->activate();
853 q->resize( QSize(q->width(), q->height() - collapseHeight) );
854 }
855}
856
857#if QT_CONFIG(messagebox)
858void QPrintDialogPrivate::_q_checkFields()
859{
860 Q_Q(QPrintDialog);
861 if (top->d->checkFields())
862 q->accept();
863}
864#endif // QT_CONFIG(messagebox)
865
866
868{
869 Q_Q(QPrintDialog);
870 options.gbPrintRange->setVisible(q->testOption(QPrintDialog::PrintPageRange) ||
871 q->testOption(QPrintDialog::PrintSelection) ||
872 q->testOption(QPrintDialog::PrintCurrentPage));
873
874 options.printRange->setEnabled(q->testOption(QPrintDialog::PrintPageRange));
875 options.printSelection->setVisible(q->testOption(QPrintDialog::PrintSelection));
876 options.printCurrentPage->setVisible(q->testOption(QPrintDialog::PrintCurrentPage));
877 options.collate->setVisible(q->testOption(QPrintDialog::PrintCollateCopies));
878
879#if QT_CONFIG(cups)
880 // Don't display Page Set if only Selection or Current Page are enabled
881 if (!q->testOption(QPrintDialog::PrintPageRange)
882 && (q->testOption(QPrintDialog::PrintSelection) || q->testOption(QPrintDialog::PrintCurrentPage))) {
883 options.pageSetCombo->setVisible(false);
884 options.pageSetLabel->setVisible(false);
885 } else {
886 options.pageSetCombo->setVisible(true);
887 options.pageSetLabel->setVisible(true);
888 }
889
890 if (!q->testOption(QPrintDialog::PrintPageRange)) {
891 // If we can do CUPS server side pages selection,
892 // display the page range widgets
893 options.gbPrintRange->setVisible(true);
894 options.printRange->setEnabled(true);
895 }
896#endif
897
898 switch (q->printRange()) {
899 case QPrintDialog::AllPages:
900 options.printAll->setChecked(true);
901 options.pageSetCombo->setEnabled(true);
902 break;
903 case QPrintDialog::Selection:
904 options.printSelection->setChecked(true);
905 options.pageSetCombo->setEnabled(false);
906 break;
907 case QPrintDialog::PageRange:
908 options.printRange->setChecked(true);
909 options.pageSetCombo->setEnabled(true);
910 break;
911 case QPrintDialog::CurrentPage:
912 if (q->testOption(QPrintDialog::PrintCurrentPage)) {
913 options.printCurrentPage->setChecked(true);
914 options.pageSetCombo->setEnabled(false);
915 }
916 break;
917 default:
918 break;
919 }
920 const int minPage = qMax(1, qMin(q->minPage() , q->maxPage()));
921 const int maxPage = qMax(1, q->maxPage() == INT_MAX ? 9999 : q->maxPage());
922
923 options.from->setMinimum(minPage);
924 options.to->setMinimum(minPage);
925 options.from->setMaximum(maxPage);
926 options.to->setMaximum(maxPage);
927
928 options.from->setValue(q->fromPage());
929 options.to->setValue(q->toPage());
931}
932
933void QPrintDialogPrivate::setTabs(const QList<QWidget*> &tabWidgets)
934{
935 QList<QWidget*>::ConstIterator iter = tabWidgets.begin();
936 while(iter != tabWidgets.constEnd()) {
937 QWidget *tab = *iter;
938 options.tabs->addTab(tab, tab->windowTitle());
939 ++iter;
940 }
941}
942
943////////////////////////////////////////////////////////////////////////////////
944////////////////////////////////////////////////////////////////////////////////
945
946/*
947
948 QPrintDialog
949
950 The main Print Dialog.
951
952*/
953
954QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent)
955 : QAbstractPrintDialog(*(new QPrintDialogPrivate), printer, parent)
956{
957 Q_D(QPrintDialog);
958 d->init();
959}
960
961/*!
962 Constructs a print dialog with the given \a parent.
963*/
964QPrintDialog::QPrintDialog(QWidget *parent)
965 : QAbstractPrintDialog(*(new QPrintDialogPrivate), nullptr, parent)
966{
967 Q_D(QPrintDialog);
968 d->init();
969}
970
971QPrintDialog::~QPrintDialog()
972{
973}
974
975void QPrintDialog::setVisible(bool visible)
976{
977 Q_D(QPrintDialog);
978
979 if (visible)
980 d->updateWidgets();
981
982 QAbstractPrintDialog::setVisible(visible);
983}
984
985int QPrintDialog::exec()
986{
987 return QAbstractPrintDialog::exec();
988}
989
990void QPrintDialog::accept()
991{
992 Q_D(QPrintDialog);
993#if QT_CONFIG(cups) && QT_CONFIG(messagebox)
994 if (d->options.pagesRadioButton->isChecked()) {
995 const QString rangesText = d->options.pagesLineEdit->text();
996 if (rangesText.isEmpty() || QPageRanges::fromString(rangesText).isEmpty()) {
997 QMessageBox::critical(this, tr("Invalid Pages Definition"),
998 tr("%1 does not follow the correct syntax. Please use ',' to separate "
999 "ranges and pages, '-' to define ranges and make sure ranges do "
1000 "not intersect with each other.").arg(rangesText),
1001 QMessageBox::Ok, QMessageBox::Ok);
1002 return;
1003 }
1004 }
1005 if (d->top->d->m_duplexPpdOption && d->top->d->m_duplexPpdOption->conflicted) {
1006 const QMessageBox::StandardButton answer = QMessageBox::warning(this, tr("Duplex Settings Conflicts"),
1007 tr("There are conflicts in duplex settings. Do you want to fix them?"),
1008 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
1009 if (answer != QMessageBox::No)
1010 return;
1011 }
1012#endif
1013 d->setupPrinter();
1014 QDialog::accept();
1015}
1016
1017////////////////////////////////////////////////////////////////////////////////
1018////////////////////////////////////////////////////////////////////////////////
1019
1020/*
1021
1022 QUnixPrintWidget && QUnixPrintWidgetPrivate
1023
1024 The upper half of the Print Dialog containing the Printer Selection widgets
1025
1026*/
1027
1028#if defined (Q_OS_UNIX)
1029
1030/*! \internal
1031*/
1032QUnixPrintWidgetPrivate::QUnixPrintWidgetPrivate(QUnixPrintWidget *p, QPrinter *prn)
1033 : parent(p), propertiesDialog(nullptr), printer(prn),
1034#if QT_CONFIG(cups)
1035 m_duplexPpdOption(nullptr),
1036#endif
1037 optionsPane(nullptr), filePrintersAdded(false)
1038{
1039 q = nullptr;
1040 if (parent)
1041 q = qobject_cast<QPrintDialog*> (parent->parent());
1042
1043 widget.setupUi(parent);
1044
1045 int currentPrinterIndex = 0;
1046 QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
1047 if (ps) {
1048 const QStringList printers = ps->availablePrintDeviceIds();
1049 const QString defaultPrinter = ps->defaultPrintDeviceId();
1050
1051 widget.printers->addItems(printers);
1052
1053 const QString selectedPrinter = prn && !prn->printerName().isEmpty() ? prn->printerName() : defaultPrinter;
1054 const int idx = printers.indexOf(selectedPrinter);
1055
1056 if (idx >= 0)
1057 currentPrinterIndex = idx;
1058 }
1059 widget.properties->setEnabled(true);
1060
1061#if QT_CONFIG(filesystemmodel) && QT_CONFIG(completer)
1062 QFileSystemModel *fsm = new QFileSystemModel(widget.filename);
1063 fsm->setRootPath(QDir::homePath());
1064 widget.filename->setCompleter(new QCompleter(fsm, widget.filename));
1065#endif
1066 _q_printerChanged(currentPrinterIndex);
1067
1068 QObject::connect(widget.printers, SIGNAL(currentIndexChanged(int)),
1069 parent, SLOT(_q_printerChanged(int)));
1070 QObject::connect(widget.fileBrowser, SIGNAL(clicked()), parent, SLOT(_q_btnBrowseClicked()));
1071 QObject::connect(widget.properties, SIGNAL(clicked()), parent, SLOT(_q_btnPropertiesClicked()));
1072
1073 // disable features that QPrinter does not yet support.
1074 widget.preview->setVisible(false);
1075}
1076
1077void QUnixPrintWidgetPrivate::updateWidget()
1078{
1079 const bool printToFile = q == nullptr || q->testOption(QPrintDialog::PrintToFile);
1080 if (printToFile && !filePrintersAdded) {
1081 if (widget.printers->count())
1082 widget.printers->insertSeparator(widget.printers->count());
1083 widget.printers->addItem(QPrintDialog::tr("Print to File (PDF)"));
1084 filePrintersAdded = true;
1085 if (widget.printers->count() == 1)
1086 _q_printerChanged(0);
1087 }
1088 if (!printToFile && filePrintersAdded) {
1089 widget.printers->removeItem(widget.printers->count()-1);
1090 widget.printers->removeItem(widget.printers->count()-1);
1091 if (widget.printers->count())
1092 widget.printers->removeItem(widget.printers->count()-1); // remove separator
1093 filePrintersAdded = false;
1094 }
1095 if (printer && filePrintersAdded && (printer->outputFormat() != QPrinter::NativeFormat
1096 || printer->printerName().isEmpty()))
1097 {
1098 if (printer->outputFormat() == QPrinter::PdfFormat)
1099 widget.printers->setCurrentIndex(widget.printers->count() - 1);
1100 widget.filename->setEnabled(true);
1101 widget.lOutput->setEnabled(true);
1102 }
1103
1104 widget.filename->setVisible(printToFile);
1105 widget.lOutput->setVisible(printToFile);
1106 widget.fileBrowser->setVisible(printToFile);
1107
1108 if (q)
1109 widget.properties->setVisible(q->testOption(QAbstractPrintDialog::PrintShowPageSize));
1110}
1111
1112QUnixPrintWidgetPrivate::~QUnixPrintWidgetPrivate()
1113{
1114}
1115
1116void QUnixPrintWidgetPrivate::_q_printerChanged(int index)
1117{
1118 if (index < 0)
1119 return;
1120 const int printerCount = widget.printers->count();
1121 widget.filename->setEnabled(false);
1122 widget.lOutput->setEnabled(false);
1123
1124 // Reset properties dialog when printer is changed
1125 if (propertiesDialog){
1126 delete propertiesDialog;
1127 propertiesDialog = nullptr;
1128 }
1129
1130#if QT_CONFIG(cups)
1131 m_duplexPpdOption = nullptr;
1132#endif
1133
1134 if (filePrintersAdded) {
1135 Q_ASSERT(index != printerCount - 2); // separator
1136 if (index == printerCount - 1) { // PDF
1137 widget.location->setText(QPrintDialog::tr("Local file"));
1138 widget.type->setText(QPrintDialog::tr("Write PDF file"));
1139 widget.properties->setEnabled(true);
1140 widget.filename->setEnabled(true);
1141 QString filename = widget.filename->text();
1142 widget.filename->setText(filename);
1143 widget.lOutput->setEnabled(true);
1144 printer->setOutputFormat(QPrinter::PdfFormat);
1145 m_currentPrintDevice = QPrintDevice();
1146 if (optionsPane)
1147 optionsPane->selectPrinter(QPrinter::PdfFormat);
1148 return;
1149 }
1150 }
1151
1152 if (printer) {
1153 printer->setOutputFormat(QPrinter::NativeFormat);
1154
1155 QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
1156 if (ps)
1157 m_currentPrintDevice = ps->createPrintDevice(widget.printers->itemText(index));
1158 else
1159 m_currentPrintDevice = QPrintDevice();
1160
1161 printer->setPrinterName(m_currentPrintDevice.id());
1162
1163 widget.location->setText(m_currentPrintDevice.location());
1164 widget.type->setText(m_currentPrintDevice.makeAndModel());
1165 if (optionsPane)
1166 optionsPane->selectPrinter(QPrinter::NativeFormat);
1167 }
1168
1169#if QT_CONFIG(cups)
1170 m_duplexPpdOption = QCUPSSupport::findPpdOption("Duplex", &m_currentPrintDevice);
1171#endif
1172}
1173
1174void QUnixPrintWidgetPrivate::setOptionsPane(QPrintDialogPrivate *pane)
1175{
1176 optionsPane = pane;
1177 if (optionsPane)
1178 optionsPane->selectPrinter(QPrinter::NativeFormat);
1179}
1180
1181void QUnixPrintWidgetPrivate::_q_btnBrowseClicked()
1182{
1183 QString filename = widget.filename->text();
1184#if QT_CONFIG(filedialog)
1185 filename = QFileDialog::getSaveFileName(parent, QPrintDialog::tr("Print To File ..."), filename,
1186 QString(), nullptr, QFileDialog::DontConfirmOverwrite);
1187#else
1188 filename.clear();
1189#endif
1190 if (!filename.isEmpty()) {
1191 widget.filename->setText(filename);
1192 widget.printers->setCurrentIndex(widget.printers->count() - 1); // the pdf one
1193 }
1194}
1195
1196#if QT_CONFIG(messagebox)
1197bool QUnixPrintWidgetPrivate::checkFields()
1198{
1199 if (widget.filename->isEnabled()) {
1200 QString file = widget.filename->text();
1201 QFile f(file);
1202 QFileInfo fi(f);
1203 bool exists = fi.exists();
1204 bool opened = false;
1205 if (exists && fi.isDir()) {
1206 QMessageBox::warning(q, q->windowTitle(),
1207 QPrintDialog::tr("%1 is a directory.\nPlease choose a different file name.").arg(file));
1208 return false;
1209 } else if ((exists && !fi.isWritable()) || !(opened = f.open(QFile::Append))) {
1210 QMessageBox::warning(q, q->windowTitle(),
1211 QPrintDialog::tr("File %1 is not writable.\nPlease choose a different file name.").arg(file));
1212 return false;
1213 } else if (exists) {
1214 int ret = QMessageBox::question(q, q->windowTitle(),
1215 QPrintDialog::tr("%1 already exists.\nDo you want to overwrite it?").arg(file),
1216 QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
1217 if (ret == QMessageBox::No)
1218 return false;
1219 }
1220 if (opened) {
1221 f.close();
1222 if (!exists)
1223 f.remove();
1224 }
1225 }
1226
1227#if QT_CONFIG(cups)
1228 if (propertiesDialog) {
1229 QCUPSSupport::PagesPerSheet pagesPerSheet = qvariant_cast<QCUPSSupport::PagesPerSheet>(propertiesDialog->widget.pageSetup->m_ui.pagesPerSheetCombo
1230 ->currentData());
1231
1232 QCUPSSupport::PageSet pageSet = qvariant_cast<QCUPSSupport::PageSet>(optionsPane->options.pageSetCombo->currentData());
1233
1234
1235 if (pagesPerSheet != QCUPSSupport::OnePagePerSheet
1236 && pageSet != QCUPSSupport::AllPages) {
1237 QMessageBox::warning(q, q->windowTitle(),
1238 QPrintDialog::tr("Options 'Pages Per Sheet' and 'Page Set' cannot be used together.\nPlease turn one of those options off."));
1239 return false;
1240 }
1241 }
1242#endif
1243
1244 // Every test passed. Accept the dialog.
1245 return true;
1246}
1247#endif // QT_CONFIG(messagebox)
1248
1249void QUnixPrintWidgetPrivate::setupPrinterProperties()
1250{
1251 delete propertiesDialog;
1252
1253 QPrinter::OutputFormat outputFormat;
1254 QString printerName;
1255
1256 if (q->testOption(QPrintDialog::PrintToFile)
1257 && (widget.printers->currentIndex() == widget.printers->count() - 1)) {// PDF
1258 outputFormat = QPrinter::PdfFormat;
1259 } else {
1260 outputFormat = QPrinter::NativeFormat;
1261 printerName = widget.printers->currentText();
1262 }
1263
1264 propertiesDialog = new QPrintPropertiesDialog(q->printer(), &m_currentPrintDevice, outputFormat, printerName, q);
1265}
1266
1267#if QT_CONFIG(cups)
1268void QUnixPrintWidgetPrivate::setPpdDuplex(QPrinter::DuplexMode mode)
1269{
1270 auto values = QStringList{} << QStringLiteral("Duplex");
1271 if (mode == QPrinter::DuplexNone) values << QStringLiteral("None");
1272 else if (mode == QPrinter::DuplexLongSide) values << QStringLiteral("DuplexNoTumble");
1273 else if (mode == QPrinter::DuplexShortSide) values << QStringLiteral("DuplexTumble");
1274
1275 m_currentPrintDevice.setProperty(PDPK_PpdOption, values);
1276}
1277#endif
1278
1279void QUnixPrintWidgetPrivate::_q_btnPropertiesClicked()
1280{
1281 if (!propertiesDialog)
1282 setupPrinterProperties();
1283 propertiesDialog->exec();
1284
1285#if QT_CONFIG(cups)
1286 // update the warning icon on the duplex options if needed
1287 optionsPane->updatePpdDuplexOption(optionsPane->options.noDuplex);
1288 optionsPane->updatePpdDuplexOption(optionsPane->options.duplexLong);
1289 optionsPane->updatePpdDuplexOption(optionsPane->options.duplexShort);
1290#endif
1291}
1292
1293void QUnixPrintWidgetPrivate::setupPrinter()
1294{
1295 const int printerCount = widget.printers->count();
1296 const int index = widget.printers->currentIndex();
1297
1298 if (filePrintersAdded && index == printerCount - 1) { // PDF
1299 printer->setPrinterName(QString());
1300 Q_ASSERT(index != printerCount - 2); // separator
1301 printer->setOutputFormat(QPrinter::PdfFormat);
1302 QString path = widget.filename->text();
1303 if (QDir::isRelativePath(path))
1304 path = QDir::homePath() + QDir::separator() + path;
1305 printer->setOutputFileName(path);
1306 }
1307 else {
1308 printer->setPrinterName(widget.printers->currentText());
1309 printer->setOutputFileName(QString());
1310 }
1311
1312 if (!propertiesDialog)
1313 setupPrinterProperties();
1314
1315 propertiesDialog->setupPrinter();
1316}
1317
1318/*! \internal
1319*/
1320QUnixPrintWidget::QUnixPrintWidget(QPrinter *printer, QWidget *parent)
1321 : QWidget(parent), d(new QUnixPrintWidgetPrivate(this, printer))
1322{
1323 if (printer == nullptr)
1324 return;
1325 if (printer->outputFileName().isEmpty()) {
1326 QString home = QDir::homePath();
1327 QString cur = QDir::currentPath();
1328 if (!home.endsWith(u'/'))
1329 home += u'/';
1330 if (!cur.startsWith(home))
1331 cur = home;
1332 else if (!cur.endsWith(u'/'))
1333 cur += u'/';
1334 if (QGuiApplication::platformName() == "xcb"_L1) {
1335 if (printer->docName().isEmpty()) {
1336 cur += "print.pdf"_L1;
1337 } else {
1338#if QT_CONFIG(regularexpression)
1339 const QRegularExpression re(QStringLiteral("(.*)\\.\\S+"));
1340 auto match = re.match(printer->docName());
1341 if (match.hasMatch())
1342 cur += match.captured(1);
1343 else
1344#endif
1345 cur += printer->docName();
1346 cur += ".pdf"_L1;
1347 }
1348 } // xcb
1349
1350 d->widget.filename->setText(cur);
1351 }
1352 else
1353 d->widget.filename->setText(printer->outputFileName());
1354 const QString printerName = printer->printerName();
1355 if (!printerName.isEmpty()) {
1356 const int i = d->widget.printers->findText(printerName);
1357 if (i >= 0)
1358 d->widget.printers->setCurrentIndex(i);
1359 }
1360 // PDF printer not added to the dialog yet, we'll handle those cases in QUnixPrintWidgetPrivate::updateWidget
1361}
1362
1363/*! \internal
1364*/
1365QUnixPrintWidget::~QUnixPrintWidget()
1366{
1367 delete d;
1368}
1369
1370/*! \internal
1371
1372 Updates the printer with the states held in the QUnixPrintWidget.
1373*/
1374void QUnixPrintWidget::updatePrinter()
1375{
1376 d->setupPrinter();
1377}
1378
1379#if QT_CONFIG(cups)
1380
1381////////////////////////////////////////////////////////////////////////////////
1382////////////////////////////////////////////////////////////////////////////////
1383
1384#endif // QT_CONFIG(cups)
1385#endif // defined (Q_OS_UNIX)
1386
1387QT_END_NAMESPACE
1388
1389#include "moc_qprintdialog.cpp"
1390#include "qprintdialog_unix.moc"
QUnixPrintWidget * top
void selectPrinter(const QPrinter::OutputFormat outputFormat)
virtual void setTabs(const QList< QWidget * > &tabs) override
QDialogButtonBox * buttons
Ui::QPrintSettingsOutput options
QPrinter::OutputFormat printerOutputFormat
void showEvent(QShowEvent *event) override
\reimp
QUnixPrintWidgetPrivate(QUnixPrintWidget *q, QPrinter *prn)
void _q_printerChanged(int index)
QPrintPropertiesDialog * propertiesDialog
QUnixPrintWidget *const parent
void setOptionsPane(QPrintDialogPrivate *pane)
static void _q_pdu_initResources()