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 groupLayout->addRow(optionLabel, choicesCbWithLabel);
477 anyWidgetCreated = true;
478 choicesCb->setProperty(ppdOptionProperty, QVariant::fromValue(option));
479 choicesCb->setProperty(warningLabelProperty, QVariant::fromValue(warningLabel));
480 m_advancedOptionsCombos << choicesCb;
481 } else {
482 delete choicesCb;
483 }
484 }
485 }
486
487 if (groupLayout->rowCount() > 0) {
488 QGroupBox *groupBox = new QGroupBox(toUnicode(group->text));
489 groupBox->setLayout(groupLayout);
490 layout->addWidget(groupBox);
491 } else {
492 delete groupLayout;
493 }
494 }
495 }
496
497 layout->addStretch();
498 widget.scrollArea->setWidget(holdingWidget);
499 }
500
501 return anyWidgetCreated;
502}
503
504void QPrintPropertiesDialog::setPrinterAdvancedCupsOptions() const
505{
506 for (const QComboBox *choicesCb : m_advancedOptionsCombos) {
507 const ppd_option_t *option = qvariant_cast<const ppd_option_t *>(choicesCb->property(ppdOptionProperty));
508
509 // We can't use choicesCb->currentIndex() to know the index of the option in the choices[] array
510 // because some of them may not be present in the list because they conflict with the
511 // installable options so use the index passed on addItem
512 const int selectedChoiceIndex = choicesCb->currentData().toInt();
513 const char *selectedChoice = option->choices[selectedChoiceIndex].choice;
514
515 if (qstrcmp(option->keyword, "ColorModel") == 0)
516 m_printer->setColorMode(qstrcmp(selectedChoice, "Gray") == 0 ? QPrinter::GrayScale : QPrinter::Color);
517
518 if (qstrcmp(option->defchoice, selectedChoice) != 0)
519 QCUPSSupport::setCupsOption(m_printer, QString::fromLatin1(option->keyword), QString::fromLatin1(selectedChoice));
520 }
521}
522
523void QPrintPropertiesDialog::revertAdvancedOptionsToSavedValues() const
524{
525 for (QComboBox *choicesCb : m_advancedOptionsCombos) {
526 const int originallySelectedChoice = qvariant_cast<int>(choicesCb->property(ppdOriginallySelectedChoiceProperty));
527 const int newComboIndexToSelect = choicesCb->findData(originallySelectedChoice);
528 choicesCb->setCurrentIndex(newComboIndexToSelect);
529 // The currentIndexChanged lambda takes care of resetting the ppd option
530 }
531 widget.conflictsLabel->setVisible(anyPpdOptionConflict());
532}
533
534void QPrintPropertiesDialog::advancedOptionsUpdateSavedValues() const
535{
536 for (QComboBox *choicesCb : m_advancedOptionsCombos)
537 choicesCb->setProperty(ppdOriginallySelectedChoiceProperty, choicesCb->currentData());
538}
539
540bool QPrintPropertiesDialog::anyPpdOptionConflict() const
541{
542 // we need to execute both since besides returning true/false they update the warning icons
543 const bool pageSetupConflicts = widget.pageSetup->hasPpdConflict();
544 const bool advancedOptionConflicts = anyAdvancedOptionConflict();
545 return pageSetupConflicts || advancedOptionConflicts;
546}
547
548bool QPrintPropertiesDialog::anyAdvancedOptionConflict() const
549{
550 const QIcon warning = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, nullptr);
551
552 bool anyConflicted = false;
553
554 for (const QComboBox *choicesCb : m_advancedOptionsCombos) {
555 const ppd_option_t *option = qvariant_cast<const ppd_option_t *>(choicesCb->property(ppdOptionProperty));
556 QLabel *warningLabel = qvariant_cast<QLabel *>(choicesCb->property(warningLabelProperty));
557 if (option->conflicted) {
558 anyConflicted = true;
559 const int pixmap_size = choicesCb->sizeHint().height() * .75;
560 warningLabel->setPixmap(warning.pixmap(pixmap_size, pixmap_size));
561 } else {
562 warningLabel->setPixmap(QPixmap());
563 }
564 }
565
566 return anyConflicted;
567}
568
569#endif
570
571
572////////////////////////////////////////////////////////////////////////////////
573////////////////////////////////////////////////////////////////////////////////
574
575/*
576
577 QPrintDialogPrivate
578
579 The lower half of the Print Dialog containing the Copies and Options
580 tabs that expands when the Options button is selected.
581
582*/
583QPrintDialogPrivate::QPrintDialogPrivate()
584 : top(nullptr), bottom(nullptr), buttons(nullptr), collapseButton(nullptr),
585 explicitDuplexMode(QPrint::DuplexAuto)
586{
588}
589
593
595{
596 Q_Q(QPrintDialog);
597
598 top = new QUnixPrintWidget(q->printer(), q);
599 bottom = new QWidget(q);
600 options.setupUi(bottom);
601 options.color->setIconSize(QSize(32, 32));
602 options.color->setIcon(QIcon(":/qt-project.org/dialogs/qprintdialog/images/status-color.png"_L1));
603 options.grayscale->setIconSize(QSize(32, 32));
604 options.grayscale->setIcon(QIcon(":/qt-project.org/dialogs/qprintdialog/images/status-gray-scale.png"_L1));
605
606#if QT_CONFIG(cups)
607 // Add Page Set widget if CUPS is available
608 options.pageSetCombo->addItem(tr("All Pages"), QVariant::fromValue(QCUPSSupport::AllPages));
609 options.pageSetCombo->addItem(tr("Odd Pages"), QVariant::fromValue(QCUPSSupport::OddPages));
610 options.pageSetCombo->addItem(tr("Even Pages"), QVariant::fromValue(QCUPSSupport::EvenPages));
611#else
612 delete options.pagesRadioButton;
613 delete options.pagesLineEdit;
614 options.pagesRadioButton = nullptr;
615 options.pagesLineEdit = nullptr;
616#endif
617
619
620 buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, q);
621 collapseButton = new QPushButton(QPrintDialog::tr("&Options >>"), buttons);
622 buttons->addButton(collapseButton, QDialogButtonBox::ResetRole);
623 bottom->setVisible(false);
624
625 QPushButton *printButton = buttons->button(QDialogButtonBox::Ok);
626 printButton->setText(QPrintDialog::tr("&Print"));
627 printButton->setDefault(true);
628
629 QVBoxLayout *lay = new QVBoxLayout(q);
630 lay->addWidget(top);
631 lay->addWidget(bottom);
632 lay->addWidget(buttons);
633
634#if !QT_CONFIG(messagebox)
635 QObject::connect(buttons, SIGNAL(accepted()), q, SLOT(accept()));
636#else
637 QObject::connect(buttons, SIGNAL(accepted()), q, SLOT(_q_checkFields()));
638#endif
639 QObject::connect(buttons, SIGNAL(rejected()), q, SLOT(reject()));
640
641 QObject::connect(options.printSelection, SIGNAL(toggled(bool)),
642 q, SLOT(_q_togglePageSetCombo(bool)));
643
644 QObject::connect(options.printCurrentPage, SIGNAL(toggled(bool)),
645 q, SLOT(_q_togglePageSetCombo(bool)));
646
647 QObject::connect(collapseButton, SIGNAL(released()), q, SLOT(_q_collapseOrExpandDialog()));
648
649 QObject::connect(options.noDuplex, &QAbstractButton::clicked, q, [this] { setExplicitDuplexMode(QPrint::DuplexNone); });
650 QObject::connect(options.duplexLong, &QAbstractButton::clicked, q, [this] { setExplicitDuplexMode(QPrint::DuplexLongSide); });
651 QObject::connect(options.duplexShort, &QAbstractButton::clicked, q, [this] { setExplicitDuplexMode(QPrint::DuplexShortSide); });
652
653#if QT_CONFIG(cups)
654 QObject::connect(options.noDuplex, &QAbstractButton::toggled, q, [this] { updatePpdDuplexOption(options.noDuplex); });
655 QObject::connect(options.duplexLong, &QAbstractButton::toggled, q, [this] { updatePpdDuplexOption(options.duplexLong); });
656 QObject::connect(options.duplexShort, &QAbstractButton::toggled, q, [this] { updatePpdDuplexOption(options.duplexShort); });
657#endif
658}
659
660// initialize printer options
661void QPrintDialogPrivate::selectPrinter(const QPrinter::OutputFormat outputFormat)
662{
663 Q_Q(QPrintDialog);
664 QPrinter *p = q->printer();
665 printerOutputFormat = outputFormat;
666
667 // printer supports duplex mode?
668 const auto supportedDuplexMode = top->d->m_currentPrintDevice.supportedDuplexModes();
669 options.duplexLong->setEnabled(supportedDuplexMode.contains(QPrint::DuplexLongSide));
670 options.duplexShort->setEnabled(supportedDuplexMode.contains(QPrint::DuplexShortSide));
671
672 if (p->colorMode() == QPrinter::Color)
673 options.color->setChecked(true);
674 else
675 options.grayscale->setChecked(true);
676
677 // duplex priorities to be as follows:
678 // 1) a user-selected duplex value in the dialog has highest priority
679 // 2) duplex value set in the QPrinter
680 QPrint::DuplexMode duplex;
681 if (explicitDuplexMode != QPrint::DuplexAuto && supportedDuplexMode.contains(explicitDuplexMode))
682 duplex = explicitDuplexMode;
683 else
684 duplex = static_cast<QPrint::DuplexMode>(p->duplex());
685 switch (duplex) {
686 case QPrint::DuplexNone:
687 options.noDuplex->setChecked(true); break;
688 case QPrint::DuplexLongSide:
689 case QPrint::DuplexAuto:
690 options.duplexLong->setChecked(true); break;
691 case QPrint::DuplexShortSide:
692 options.duplexShort->setChecked(true); break;
693 }
694 options.copies->setValue(p->copyCount());
695 options.collate->setChecked(p->collateCopies());
696 options.reverse->setChecked(p->pageOrder() == QPrinter::LastPageFirst);
697
698 if (outputFormat == QPrinter::PdfFormat || options.printSelection->isChecked()
699 || options.printCurrentPage->isChecked())
700
701 options.pageSetCombo->setEnabled(false);
702 else
703 options.pageSetCombo->setEnabled(true);
704
705#if QT_CONFIG(cups)
706 // Disable complex page ranges widget when printing to pdf
707 // It doesn't work since it relies on cups to do the heavy lifting and cups
708 // is not used when printing to PDF
709 options.pagesRadioButton->setEnabled(outputFormat != QPrinter::PdfFormat);
710
711 // Disable color options on main dialog if not printing to file, it will be handled by CUPS advanced dialog
712 options.colorMode->setVisible(outputFormat == QPrinter::PdfFormat);
713#endif
714}
715
716#if QT_CONFIG(cups)
717
718void QPrintDialogPrivate::updatePpdDuplexOption(QRadioButton *radio)
719{
720 const bool checked = radio->isChecked();
721 if (checked) {
722 if (radio == options.noDuplex) top->d->setPpdDuplex(QPrinter::DuplexNone);
723 else if (radio == options.duplexLong) top->d->setPpdDuplex(QPrinter::DuplexLongSide);
724 else if (radio == options.duplexShort) top->d->setPpdDuplex(QPrinter::DuplexShortSide);
725 }
726 const bool conflict = checked && top->d->m_duplexPpdOption && top->d->m_duplexPpdOption->conflicted;
727 radio->setIcon(conflict ? QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, nullptr) : QIcon());
728}
729
730#endif
731
732void QPrintDialogPrivate::setExplicitDuplexMode(const QPrint::DuplexMode duplexMode)
733{
734 explicitDuplexMode = duplexMode;
735}
736
738{
739 // First setup the requested OutputFormat, Printer and Page Size first
741
742 // Then setup Print Job options
743 Q_Q(QPrintDialog);
744 QPrinter* p = q->printer();
745
746 if (options.duplex->isEnabled()) {
747 if (options.noDuplex->isChecked())
748 p->setDuplex(QPrinter::DuplexNone);
749 else if (options.duplexLong->isChecked())
750 p->setDuplex(QPrinter::DuplexLongSide);
751 else
752 p->setDuplex(QPrinter::DuplexShortSide);
753 }
754
755#if QT_CONFIG(cups)
756 // When printing to a device the colorMode will be set by the advanced panel
757 if (p->outputFormat() == QPrinter::PdfFormat)
758#endif
759 p->setColorMode(options.color->isChecked() ? QPrinter::Color : QPrinter::GrayScale);
760
761 p->setPageOrder(options.reverse->isChecked() ? QPrinter::LastPageFirst : QPrinter::FirstPageFirst);
762
763 // print range
764 if (options.printAll->isChecked()) {
765 p->setPrintRange(QPrinter::AllPages);
766 p->setPageRanges(QPageRanges());
767 } else if (options.printSelection->isChecked()) {
768 p->setPrintRange(QPrinter::Selection);
769 p->setPageRanges(QPageRanges());
770 } else if (options.printCurrentPage->isChecked()) {
771 p->setPrintRange(QPrinter::CurrentPage);
772 p->setPageRanges(QPageRanges());
773 } else if (options.printRange->isChecked()) {
774 if (q->testOption(QPrintDialog::PrintPageRange)) {
775 p->setPrintRange(QPrinter::PageRange);
776 p->setFromTo(options.from->value(), qMax(options.from->value(), options.to->value()));
777 } else {
778 // This case happens when CUPS server-side page range is enabled
779 // Setting the range to the printer occurs below
780 p->setPrintRange(QPrinter::AllPages);
781 p->setPageRanges(QPageRanges());
782 }
783 }
784
785#if QT_CONFIG(cups)
786 if (options.pagesRadioButton->isChecked()) {
787 const QPageRanges ranges = QPageRanges::fromString(options.pagesLineEdit->text());
788 p->setPrintRange(QPrinter::AllPages);
789 p->setPageRanges(QPageRanges());
790
791 // server-side page filtering
792 QCUPSSupport::setPageRange(p, ranges.toString());
793 }
794
795 // page set
796 if (p->printRange() == QPrinter::AllPages || p->printRange() == QPrinter::PageRange) {
797 //If the application is selecting pages and the first page number is even then need to adjust the odd-even accordingly
798 QCUPSSupport::PageSet pageSet = qvariant_cast<QCUPSSupport::PageSet>(options.pageSetCombo->itemData(options.pageSetCombo->currentIndex()));
799 if (q->testOption(QPrintDialog::PrintPageRange)
800 && p->printRange() == QPrinter::PageRange
801 && (q->fromPage() % 2 == 0)) {
802
803 switch (pageSet) {
804 case QCUPSSupport::AllPages:
805 break;
806 case QCUPSSupport::OddPages:
807 QCUPSSupport::setPageSet(p, QCUPSSupport::EvenPages);
808 break;
809 case QCUPSSupport::EvenPages:
810 QCUPSSupport::setPageSet(p, QCUPSSupport::OddPages);
811 break;
812 }
813 } else if (pageSet != QCUPSSupport::AllPages) {
814 QCUPSSupport::setPageSet(p, pageSet);
815 }
816
817 // server-side page range, since we set the page range on the printer to 0-0/AllPages above,
818 // we need to take the values directly from the widget as q->fromPage() will return 0
819 if (!q->testOption(QPrintDialog::PrintPageRange) && options.printRange->isChecked())
820 QCUPSSupport::setPageRange(p, options.from->value(), qMax(options.from->value(), options.to->value()));
821 }
822#endif
823
824 // copies
825 p->setCopyCount(options.copies->value());
826 p->setCollateCopies(options.collate->isChecked());
827}
828
830{
831 if (printerOutputFormat == QPrinter::PdfFormat)
832 return;
833
834 options.pageSetCombo->setDisabled(checked);
835}
836
838{
839 int collapseHeight = 0;
840 Q_Q(QPrintDialog);
841 QWidget *widgetToHide = bottom;
842 if (widgetToHide->isVisible()) {
843 collapseButton->setText(QPrintDialog::tr("&Options >>"));
844 collapseHeight = widgetToHide->y() + widgetToHide->height() - (top->y() + top->height());
845 }
846 else
847 collapseButton->setText(QPrintDialog::tr("&Options <<"));
848 widgetToHide->setVisible(! widgetToHide->isVisible());
849 if (! widgetToHide->isVisible()) { // make it shrink
850 q->layout()->activate();
851 q->resize( QSize(q->width(), q->height() - collapseHeight) );
852 }
853}
854
855#if QT_CONFIG(messagebox)
856void QPrintDialogPrivate::_q_checkFields()
857{
858 Q_Q(QPrintDialog);
859 if (top->d->checkFields())
860 q->accept();
861}
862#endif // QT_CONFIG(messagebox)
863
864
866{
867 Q_Q(QPrintDialog);
868 options.gbPrintRange->setVisible(q->testOption(QPrintDialog::PrintPageRange) ||
869 q->testOption(QPrintDialog::PrintSelection) ||
870 q->testOption(QPrintDialog::PrintCurrentPage));
871
872 options.printRange->setEnabled(q->testOption(QPrintDialog::PrintPageRange));
873 options.printSelection->setVisible(q->testOption(QPrintDialog::PrintSelection));
874 options.printCurrentPage->setVisible(q->testOption(QPrintDialog::PrintCurrentPage));
875 options.collate->setVisible(q->testOption(QPrintDialog::PrintCollateCopies));
876
877#if QT_CONFIG(cups)
878 // Don't display Page Set if only Selection or Current Page are enabled
879 if (!q->testOption(QPrintDialog::PrintPageRange)
880 && (q->testOption(QPrintDialog::PrintSelection) || q->testOption(QPrintDialog::PrintCurrentPage))) {
881 options.pageSetCombo->setVisible(false);
882 options.pageSetLabel->setVisible(false);
883 } else {
884 options.pageSetCombo->setVisible(true);
885 options.pageSetLabel->setVisible(true);
886 }
887
888 if (!q->testOption(QPrintDialog::PrintPageRange)) {
889 // If we can do CUPS server side pages selection,
890 // display the page range widgets
891 options.gbPrintRange->setVisible(true);
892 options.printRange->setEnabled(true);
893 }
894#endif
895
896 switch (q->printRange()) {
897 case QPrintDialog::AllPages:
898 options.printAll->setChecked(true);
899 options.pageSetCombo->setEnabled(true);
900 break;
901 case QPrintDialog::Selection:
902 options.printSelection->setChecked(true);
903 options.pageSetCombo->setEnabled(false);
904 break;
905 case QPrintDialog::PageRange:
906 options.printRange->setChecked(true);
907 options.pageSetCombo->setEnabled(true);
908 break;
909 case QPrintDialog::CurrentPage:
910 if (q->testOption(QPrintDialog::PrintCurrentPage)) {
911 options.printCurrentPage->setChecked(true);
912 options.pageSetCombo->setEnabled(false);
913 }
914 break;
915 default:
916 break;
917 }
918 const int minPage = qMax(1, qMin(q->minPage() , q->maxPage()));
919 const int maxPage = qMax(1, q->maxPage() == INT_MAX ? 9999 : q->maxPage());
920
921 options.from->setMinimum(minPage);
922 options.to->setMinimum(minPage);
923 options.from->setMaximum(maxPage);
924 options.to->setMaximum(maxPage);
925
926 options.from->setValue(q->fromPage());
927 options.to->setValue(q->toPage());
929}
930
931void QPrintDialogPrivate::setTabs(const QList<QWidget*> &tabWidgets)
932{
933 QList<QWidget*>::ConstIterator iter = tabWidgets.begin();
934 while(iter != tabWidgets.constEnd()) {
935 QWidget *tab = *iter;
936 options.tabs->addTab(tab, tab->windowTitle());
937 ++iter;
938 }
939}
940
941////////////////////////////////////////////////////////////////////////////////
942////////////////////////////////////////////////////////////////////////////////
943
944/*
945
946 QPrintDialog
947
948 The main Print Dialog.
949
950*/
951
952QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent)
953 : QAbstractPrintDialog(*(new QPrintDialogPrivate), printer, parent)
954{
955 Q_D(QPrintDialog);
956 d->init();
957}
958
959/*!
960 Constructs a print dialog with the given \a parent.
961*/
962QPrintDialog::QPrintDialog(QWidget *parent)
963 : QAbstractPrintDialog(*(new QPrintDialogPrivate), nullptr, parent)
964{
965 Q_D(QPrintDialog);
966 d->init();
967}
968
969QPrintDialog::~QPrintDialog()
970{
971}
972
973void QPrintDialog::setVisible(bool visible)
974{
975 Q_D(QPrintDialog);
976
977 if (visible)
978 d->updateWidgets();
979
980 QAbstractPrintDialog::setVisible(visible);
981}
982
983int QPrintDialog::exec()
984{
985 return QAbstractPrintDialog::exec();
986}
987
988void QPrintDialog::accept()
989{
990 Q_D(QPrintDialog);
991#if QT_CONFIG(cups) && QT_CONFIG(messagebox)
992 if (d->options.pagesRadioButton->isChecked()) {
993 const QString rangesText = d->options.pagesLineEdit->text();
994 if (rangesText.isEmpty() || QPageRanges::fromString(rangesText).isEmpty()) {
995 QMessageBox::critical(this, tr("Invalid Pages Definition"),
996 tr("%1 does not follow the correct syntax. Please use ',' to separate "
997 "ranges and pages, '-' to define ranges and make sure ranges do "
998 "not intersect with each other.").arg(rangesText),
999 QMessageBox::Ok, QMessageBox::Ok);
1000 return;
1001 }
1002 }
1003 if (d->top->d->m_duplexPpdOption && d->top->d->m_duplexPpdOption->conflicted) {
1004 const QMessageBox::StandardButton answer = QMessageBox::warning(this, tr("Duplex Settings Conflicts"),
1005 tr("There are conflicts in duplex settings. Do you want to fix them?"),
1006 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
1007 if (answer != QMessageBox::No)
1008 return;
1009 }
1010#endif
1011 d->setupPrinter();
1012 QDialog::accept();
1013}
1014
1015////////////////////////////////////////////////////////////////////////////////
1016////////////////////////////////////////////////////////////////////////////////
1017
1018/*
1019
1020 QUnixPrintWidget && QUnixPrintWidgetPrivate
1021
1022 The upper half of the Print Dialog containing the Printer Selection widgets
1023
1024*/
1025
1026#if defined (Q_OS_UNIX)
1027
1028/*! \internal
1029*/
1030QUnixPrintWidgetPrivate::QUnixPrintWidgetPrivate(QUnixPrintWidget *p, QPrinter *prn)
1031 : parent(p), propertiesDialog(nullptr), printer(prn),
1032#if QT_CONFIG(cups)
1033 m_duplexPpdOption(nullptr),
1034#endif
1035 optionsPane(nullptr), filePrintersAdded(false)
1036{
1037 q = nullptr;
1038 if (parent)
1039 q = qobject_cast<QPrintDialog*> (parent->parent());
1040
1041 widget.setupUi(parent);
1042
1043 int currentPrinterIndex = 0;
1044 QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
1045 if (ps) {
1046 const QStringList printers = ps->availablePrintDeviceIds();
1047 const QString defaultPrinter = ps->defaultPrintDeviceId();
1048
1049 widget.printers->addItems(printers);
1050
1051 const QString selectedPrinter = prn && !prn->printerName().isEmpty() ? prn->printerName() : defaultPrinter;
1052 const int idx = printers.indexOf(selectedPrinter);
1053
1054 if (idx >= 0)
1055 currentPrinterIndex = idx;
1056 }
1057 widget.properties->setEnabled(true);
1058
1059#if QT_CONFIG(filesystemmodel) && QT_CONFIG(completer)
1060 QFileSystemModel *fsm = new QFileSystemModel(widget.filename);
1061 fsm->setRootPath(QDir::homePath());
1062 widget.filename->setCompleter(new QCompleter(fsm, widget.filename));
1063#endif
1064 _q_printerChanged(currentPrinterIndex);
1065
1066 QObject::connect(widget.printers, SIGNAL(currentIndexChanged(int)),
1067 parent, SLOT(_q_printerChanged(int)));
1068 QObject::connect(widget.fileBrowser, SIGNAL(clicked()), parent, SLOT(_q_btnBrowseClicked()));
1069 QObject::connect(widget.properties, SIGNAL(clicked()), parent, SLOT(_q_btnPropertiesClicked()));
1070
1071 // disable features that QPrinter does not yet support.
1072 widget.preview->setVisible(false);
1073}
1074
1075void QUnixPrintWidgetPrivate::updateWidget()
1076{
1077 const bool printToFile = q == nullptr || q->testOption(QPrintDialog::PrintToFile);
1078 if (printToFile && !filePrintersAdded) {
1079 if (widget.printers->count())
1080 widget.printers->insertSeparator(widget.printers->count());
1081 widget.printers->addItem(QPrintDialog::tr("Print to File (PDF)"));
1082 filePrintersAdded = true;
1083 if (widget.printers->count() == 1)
1084 _q_printerChanged(0);
1085 }
1086 if (!printToFile && filePrintersAdded) {
1087 widget.printers->removeItem(widget.printers->count()-1);
1088 widget.printers->removeItem(widget.printers->count()-1);
1089 if (widget.printers->count())
1090 widget.printers->removeItem(widget.printers->count()-1); // remove separator
1091 filePrintersAdded = false;
1092 }
1093 if (printer && filePrintersAdded && (printer->outputFormat() != QPrinter::NativeFormat
1094 || printer->printerName().isEmpty()))
1095 {
1096 if (printer->outputFormat() == QPrinter::PdfFormat)
1097 widget.printers->setCurrentIndex(widget.printers->count() - 1);
1098 widget.filename->setEnabled(true);
1099 widget.lOutput->setEnabled(true);
1100 }
1101
1102 widget.filename->setVisible(printToFile);
1103 widget.lOutput->setVisible(printToFile);
1104 widget.fileBrowser->setVisible(printToFile);
1105
1106 if (q)
1107 widget.properties->setVisible(q->testOption(QAbstractPrintDialog::PrintShowPageSize));
1108}
1109
1110QUnixPrintWidgetPrivate::~QUnixPrintWidgetPrivate()
1111{
1112}
1113
1114void QUnixPrintWidgetPrivate::_q_printerChanged(int index)
1115{
1116 if (index < 0)
1117 return;
1118 const int printerCount = widget.printers->count();
1119 widget.filename->setEnabled(false);
1120 widget.lOutput->setEnabled(false);
1121
1122 // Reset properties dialog when printer is changed
1123 if (propertiesDialog){
1124 delete propertiesDialog;
1125 propertiesDialog = nullptr;
1126 }
1127
1128#if QT_CONFIG(cups)
1129 m_duplexPpdOption = nullptr;
1130#endif
1131
1132 if (filePrintersAdded) {
1133 Q_ASSERT(index != printerCount - 2); // separator
1134 if (index == printerCount - 1) { // PDF
1135 widget.location->setText(QPrintDialog::tr("Local file"));
1136 widget.type->setText(QPrintDialog::tr("Write PDF file"));
1137 widget.properties->setEnabled(true);
1138 widget.filename->setEnabled(true);
1139 QString filename = widget.filename->text();
1140 widget.filename->setText(filename);
1141 widget.lOutput->setEnabled(true);
1142 printer->setOutputFormat(QPrinter::PdfFormat);
1143 m_currentPrintDevice = QPrintDevice();
1144 if (optionsPane)
1145 optionsPane->selectPrinter(QPrinter::PdfFormat);
1146 return;
1147 }
1148 }
1149
1150 if (printer) {
1151 printer->setOutputFormat(QPrinter::NativeFormat);
1152
1153 QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
1154 if (ps)
1155 m_currentPrintDevice = ps->createPrintDevice(widget.printers->itemText(index));
1156 else
1157 m_currentPrintDevice = QPrintDevice();
1158
1159 printer->setPrinterName(m_currentPrintDevice.id());
1160
1161 widget.location->setText(m_currentPrintDevice.location());
1162 widget.type->setText(m_currentPrintDevice.makeAndModel());
1163 if (optionsPane)
1164 optionsPane->selectPrinter(QPrinter::NativeFormat);
1165 }
1166
1167#if QT_CONFIG(cups)
1168 m_duplexPpdOption = QCUPSSupport::findPpdOption("Duplex", &m_currentPrintDevice);
1169#endif
1170}
1171
1172void QUnixPrintWidgetPrivate::setOptionsPane(QPrintDialogPrivate *pane)
1173{
1174 optionsPane = pane;
1175 if (optionsPane)
1176 optionsPane->selectPrinter(QPrinter::NativeFormat);
1177}
1178
1179void QUnixPrintWidgetPrivate::_q_btnBrowseClicked()
1180{
1181 QString filename = widget.filename->text();
1182#if QT_CONFIG(filedialog)
1183 filename = QFileDialog::getSaveFileName(parent, QPrintDialog::tr("Print To File ..."), filename,
1184 QString(), nullptr, QFileDialog::DontConfirmOverwrite);
1185#else
1186 filename.clear();
1187#endif
1188 if (!filename.isEmpty()) {
1189 widget.filename->setText(filename);
1190 widget.printers->setCurrentIndex(widget.printers->count() - 1); // the pdf one
1191 }
1192}
1193
1194#if QT_CONFIG(messagebox)
1195bool QUnixPrintWidgetPrivate::checkFields()
1196{
1197 if (widget.filename->isEnabled()) {
1198 QString file = widget.filename->text();
1199 QFile f(file);
1200 QFileInfo fi(f);
1201 bool exists = fi.exists();
1202 bool opened = false;
1203 if (exists && fi.isDir()) {
1204 QMessageBox::warning(q, q->windowTitle(),
1205 QPrintDialog::tr("%1 is a directory.\nPlease choose a different file name.").arg(file));
1206 return false;
1207 } else if ((exists && !fi.isWritable()) || !(opened = f.open(QFile::Append))) {
1208 QMessageBox::warning(q, q->windowTitle(),
1209 QPrintDialog::tr("File %1 is not writable.\nPlease choose a different file name.").arg(file));
1210 return false;
1211 } else if (exists) {
1212 int ret = QMessageBox::question(q, q->windowTitle(),
1213 QPrintDialog::tr("%1 already exists.\nDo you want to overwrite it?").arg(file),
1214 QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
1215 if (ret == QMessageBox::No)
1216 return false;
1217 }
1218 if (opened) {
1219 f.close();
1220 if (!exists)
1221 f.remove();
1222 }
1223 }
1224
1225#if QT_CONFIG(cups)
1226 if (propertiesDialog) {
1227 QCUPSSupport::PagesPerSheet pagesPerSheet = qvariant_cast<QCUPSSupport::PagesPerSheet>(propertiesDialog->widget.pageSetup->m_ui.pagesPerSheetCombo
1228 ->currentData());
1229
1230 QCUPSSupport::PageSet pageSet = qvariant_cast<QCUPSSupport::PageSet>(optionsPane->options.pageSetCombo->currentData());
1231
1232
1233 if (pagesPerSheet != QCUPSSupport::OnePagePerSheet
1234 && pageSet != QCUPSSupport::AllPages) {
1235 QMessageBox::warning(q, q->windowTitle(),
1236 QPrintDialog::tr("Options 'Pages Per Sheet' and 'Page Set' cannot be used together.\nPlease turn one of those options off."));
1237 return false;
1238 }
1239 }
1240#endif
1241
1242 // Every test passed. Accept the dialog.
1243 return true;
1244}
1245#endif // QT_CONFIG(messagebox)
1246
1247void QUnixPrintWidgetPrivate::setupPrinterProperties()
1248{
1249 delete propertiesDialog;
1250
1251 QPrinter::OutputFormat outputFormat;
1252 QString printerName;
1253
1254 if (q->testOption(QPrintDialog::PrintToFile)
1255 && (widget.printers->currentIndex() == widget.printers->count() - 1)) {// PDF
1256 outputFormat = QPrinter::PdfFormat;
1257 } else {
1258 outputFormat = QPrinter::NativeFormat;
1259 printerName = widget.printers->currentText();
1260 }
1261
1262 propertiesDialog = new QPrintPropertiesDialog(q->printer(), &m_currentPrintDevice, outputFormat, printerName, q);
1263}
1264
1265#if QT_CONFIG(cups)
1266void QUnixPrintWidgetPrivate::setPpdDuplex(QPrinter::DuplexMode mode)
1267{
1268 auto values = QStringList{} << QStringLiteral("Duplex");
1269 if (mode == QPrinter::DuplexNone) values << QStringLiteral("None");
1270 else if (mode == QPrinter::DuplexLongSide) values << QStringLiteral("DuplexNoTumble");
1271 else if (mode == QPrinter::DuplexShortSide) values << QStringLiteral("DuplexTumble");
1272
1273 m_currentPrintDevice.setProperty(PDPK_PpdOption, values);
1274}
1275#endif
1276
1277void QUnixPrintWidgetPrivate::_q_btnPropertiesClicked()
1278{
1279 if (!propertiesDialog)
1280 setupPrinterProperties();
1281 propertiesDialog->exec();
1282
1283#if QT_CONFIG(cups)
1284 // update the warning icon on the duplex options if needed
1285 optionsPane->updatePpdDuplexOption(optionsPane->options.noDuplex);
1286 optionsPane->updatePpdDuplexOption(optionsPane->options.duplexLong);
1287 optionsPane->updatePpdDuplexOption(optionsPane->options.duplexShort);
1288#endif
1289}
1290
1291void QUnixPrintWidgetPrivate::setupPrinter()
1292{
1293 const int printerCount = widget.printers->count();
1294 const int index = widget.printers->currentIndex();
1295
1296 if (filePrintersAdded && index == printerCount - 1) { // PDF
1297 printer->setPrinterName(QString());
1298 Q_ASSERT(index != printerCount - 2); // separator
1299 printer->setOutputFormat(QPrinter::PdfFormat);
1300 QString path = widget.filename->text();
1301 if (QDir::isRelativePath(path))
1302 path = QDir::homePath() + QDir::separator() + path;
1303 printer->setOutputFileName(path);
1304 }
1305 else {
1306 printer->setPrinterName(widget.printers->currentText());
1307 printer->setOutputFileName(QString());
1308 }
1309
1310 if (!propertiesDialog)
1311 setupPrinterProperties();
1312
1313 propertiesDialog->setupPrinter();
1314}
1315
1316/*! \internal
1317*/
1318QUnixPrintWidget::QUnixPrintWidget(QPrinter *printer, QWidget *parent)
1319 : QWidget(parent), d(new QUnixPrintWidgetPrivate(this, printer))
1320{
1321 if (printer == nullptr)
1322 return;
1323 if (printer->outputFileName().isEmpty()) {
1324 QString home = QDir::homePath();
1325 QString cur = QDir::currentPath();
1326 if (!home.endsWith(u'/'))
1327 home += u'/';
1328 if (!cur.startsWith(home))
1329 cur = home;
1330 else if (!cur.endsWith(u'/'))
1331 cur += u'/';
1332 if (QGuiApplication::platformName() == "xcb"_L1) {
1333 if (printer->docName().isEmpty()) {
1334 cur += "print.pdf"_L1;
1335 } else {
1336#if QT_CONFIG(regularexpression)
1337 const QRegularExpression re(QStringLiteral("(.*)\\.\\S+"));
1338 auto match = re.match(printer->docName());
1339 if (match.hasMatch())
1340 cur += match.captured(1);
1341 else
1342#endif
1343 cur += printer->docName();
1344 cur += ".pdf"_L1;
1345 }
1346 } // xcb
1347
1348 d->widget.filename->setText(cur);
1349 }
1350 else
1351 d->widget.filename->setText(printer->outputFileName());
1352 const QString printerName = printer->printerName();
1353 if (!printerName.isEmpty()) {
1354 const int i = d->widget.printers->findText(printerName);
1355 if (i >= 0)
1356 d->widget.printers->setCurrentIndex(i);
1357 }
1358 // PDF printer not added to the dialog yet, we'll handle those cases in QUnixPrintWidgetPrivate::updateWidget
1359}
1360
1361/*! \internal
1362*/
1363QUnixPrintWidget::~QUnixPrintWidget()
1364{
1365 delete d;
1366}
1367
1368/*! \internal
1369
1370 Updates the printer with the states held in the QUnixPrintWidget.
1371*/
1372void QUnixPrintWidget::updatePrinter()
1373{
1374 d->setupPrinter();
1375}
1376
1377#if QT_CONFIG(cups)
1378
1379////////////////////////////////////////////////////////////////////////////////
1380////////////////////////////////////////////////////////////////////////////////
1381
1382#endif // QT_CONFIG(cups)
1383#endif // defined (Q_OS_UNIX)
1384
1385QT_END_NAMESPACE
1386
1387#include "moc_qprintdialog.cpp"
1388#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()