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