4#include "qplatformdefs.h"
5#include <QtPrintSupport/private/qtprintsupportglobal_p.h>
7#include "private/qabstractprintdialog_p.h"
8#if QT_CONFIG(messagebox)
9#include <QtWidgets/qmessagebox.h>
12#if QT_CONFIG(filedialog)
13#include "qfiledialog.h"
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>
23#include <QtWidgets/qstyleditemdelegate.h>
24#include <QtWidgets/qformlayout.h>
25#include <QtPrintSupport/qprinter.h>
27#include <qpa/qplatformprintplugin.h>
28#include <qpa/qplatformprintersupport.h>
30#include <private/qprintdevice_p.h>
32#include <QtWidgets/qdialogbuttonbox.h>
34#if QT_CONFIG(regularexpression)
35#include <qregularexpression.h>
38#if QT_CONFIG(completer)
39#include <private/qcompleter_p.h>
41#include "ui_qprintpropertieswidget.h"
42#include "ui_qprintsettingsoutput.h"
43#include "ui_qprintwidget.h"
47#include <private/qcups_p.h>
48#if QT_CONFIG(cupsjobwidget)
49#include "qcupsjobwidget_p.h"
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
88 Q_INIT_RESOURCE(qprintdialog);
93using namespace Qt::StringLiterals;
117 Ui::QPrintPropertiesWidget widget;
118 QDialogButtonBox *m_buttons;
119#if QT_CONFIG(cupsjobwidget)
150 friend class QPrintDialog;
154 Q_PRIVATE_SLOT(d,
void _q_printerChanged(
int))
190 bool filePrintersAdded;
195 Q_DECLARE_PUBLIC(QPrintDialog)
206#if QT_CONFIG(messagebox)
217 virtual void setTabs(
const QList<QWidget*> &tabs)
override;
226 void setExplicitDuplexMode(QPrint::DuplexMode duplexMode);
228 QPrint::DuplexMode explicitDuplexMode;
235
236
237
238
239
240
241
244 QPrinter::OutputFormat outputFormat,
const QString &printerName,
245 QAbstractPrintDialog *parent)
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);
259 connect(m_buttons->button(QDialogButtonBox::Ok), &QPushButton::clicked,
this, &QPrintPropertiesDialog::accept);
260 connect(m_buttons->button(QDialogButtonBox::Cancel), &QPushButton::clicked,
this, &QPrintPropertiesDialog::reject);
262 widget.pageSetup->setPrinter(printer, currentPrintDevice, outputFormat, printerName);
264#if QT_CONFIG(cupsjobwidget)
265 m_jobOptions =
new QCupsJobWidget(printer, currentPrintDevice);
266 widget.tabs->insertTab(1, m_jobOptions, tr(
"Job Options"));
269 const int advancedTabIndex = widget.tabs->indexOf(widget.cupsPropertiesPage);
271 m_currentPrintDevice = currentPrintDevice;
272 const bool anyWidgetCreated = createAdvancedOptionsWidget();
274 widget.tabs->setTabEnabled(advancedTabIndex, anyWidgetCreated);
276 connect(widget.pageSetup, &QPageSetupWidget::ppdOptionChanged,
this, [
this] {
277 widget.conflictsLabel->setVisible(anyPpdOptionConflict());
281 Q_UNUSED(currentPrintDevice);
282 widget.tabs->setTabEnabled(advancedTabIndex,
false);
293 QCUPSSupport::clearCupsOptions(m_printer);
296 widget.pageSetup->setupPrinter();
297#if QT_CONFIG(cupsjobwidget)
298 m_jobOptions->setupPrinter();
303 m_printer->setColorMode(QPrinter::Color);
305 setPrinterAdvancedCupsOptions();
311 widget.pageSetup->revertToSavedValues();
313#if QT_CONFIG(cupsjobwidget)
314 m_jobOptions->revertToSavedValues();
318 revertAdvancedOptionsToSavedValues();
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)
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)
341 advancedOptionsUpdateSavedValues();
344#if QT_CONFIG(cupsjobwidget)
345 m_jobOptions->updateSavedValues();
348 widget.pageSetup->updateSavedValues();
356 widget.conflictsLabel->setVisible(anyPpdOptionConflict());
358 QDialog::showEvent(event);
364static const char *ppdOptionProperty =
"_q_ppd_option";
367static const char *ppdOriginallySelectedChoiceProperty =
"_q_ppd_originally_selected_choice";
370static const char *warningLabelProperty =
"_q_warning_label";
372static bool isBlacklistedGroup(
const ppd_group_t *group)
noexcept
374 return qstrcmp(group->name,
"InstallableOptions") == 0;
377static bool isBlacklistedOption(
const char *keyword)
noexcept
380 const char *cupsOptionBlacklist[] = {
388 auto equals = [](
const char *keyword) {
389 return [keyword](
const char *candidate) {
390 return qstrcmp(keyword, candidate) == 0;
393 return std::any_of(std::begin(cupsOptionBlacklist), std::end(cupsOptionBlacklist), equals(keyword));
396bool QPrintPropertiesDialog::createAdvancedOptionsWidget()
398 bool anyWidgetCreated =
false;
400 ppd_file_t *ppd = qvariant_cast<ppd_file_t*>(m_currentPrintDevice->property(PDPK_PpdFile));
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);
409 QWidget *holdingWidget =
new QWidget();
410 QVBoxLayout *layout =
new QVBoxLayout(holdingWidget);
412 for (
int i = 0; i < ppd->num_groups; ++i) {
413 const ppd_group_t *group = &ppd->groups[i];
415 if (!isBlacklistedGroup(group)) {
416 QFormLayout *groupLayout =
new QFormLayout();
418 for (
int i = 0; i < group->num_options; ++i) {
419 const ppd_option_t *option = &group->options[i];
421 if (!isBlacklistedOption(option->keyword)) {
422 QComboBox *choicesCb =
new QComboBox();
424 const auto setPpdOptionFromCombo = [
this, choicesCb, option] {
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());
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));
456 if (markedChoiceNotAvailable) {
460 setPpdOptionFromCombo();
463 if (choicesCb->count() > 1) {
465 connect(choicesCb, &QComboBox::currentIndexChanged,
this, setPpdOptionFromCombo);
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);
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;
487 if (groupLayout->rowCount() > 0) {
488 QGroupBox *groupBox =
new QGroupBox(toUnicode(group->text));
489 groupBox->setLayout(groupLayout);
490 layout->addWidget(groupBox);
497 layout->addStretch();
498 widget.scrollArea->setWidget(holdingWidget);
501 return anyWidgetCreated;
504void QPrintPropertiesDialog::setPrinterAdvancedCupsOptions()
const
506 for (
const QComboBox *choicesCb : m_advancedOptionsCombos) {
507 const ppd_option_t *option = qvariant_cast<
const ppd_option_t *>(choicesCb->property(ppdOptionProperty));
512 const int selectedChoiceIndex = choicesCb->currentData().toInt();
513 const char *selectedChoice = option->choices[selectedChoiceIndex].choice;
515 if (qstrcmp(option->keyword,
"ColorModel") == 0)
516 m_printer->setColorMode(qstrcmp(selectedChoice,
"Gray") == 0 ? QPrinter::GrayScale : QPrinter::Color);
518 if (qstrcmp(option->defchoice, selectedChoice) != 0)
519 QCUPSSupport::setCupsOption(m_printer, QString::fromLatin1(option->keyword), QString::fromLatin1(selectedChoice));
523void QPrintPropertiesDialog::revertAdvancedOptionsToSavedValues()
const
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);
531 widget.conflictsLabel->setVisible(anyPpdOptionConflict());
534void QPrintPropertiesDialog::advancedOptionsUpdateSavedValues()
const
536 for (QComboBox *choicesCb : m_advancedOptionsCombos)
537 choicesCb->setProperty(ppdOriginallySelectedChoiceProperty, choicesCb->currentData());
540bool QPrintPropertiesDialog::anyPpdOptionConflict()
const
543 const bool pageSetupConflicts = widget.pageSetup->hasPpdConflict();
544 const bool advancedOptionConflicts = anyAdvancedOptionConflict();
545 return pageSetupConflicts || advancedOptionConflicts;
548bool QPrintPropertiesDialog::anyAdvancedOptionConflict()
const
550 const QIcon warning = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning,
nullptr,
nullptr);
552 bool anyConflicted =
false;
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));
562 warningLabel->setPixmap(QPixmap());
566 return anyConflicted;
576
577
578
579
580
581
582
585 explicitDuplexMode(QPrint::DuplexAuto)
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));
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));
612 delete options.pagesRadioButton;
613 delete options.pagesLineEdit;
614 options.pagesRadioButton =
nullptr;
615 options.pagesLineEdit =
nullptr;
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);
625 QPushButton *printButton = buttons->button(QDialogButtonBox::Ok);
626 printButton->setText(QPrintDialog::tr(
"&Print"));
627 printButton->setDefault(
true);
629 QVBoxLayout *lay =
new QVBoxLayout(q);
631 lay->addWidget(bottom);
632 lay->addWidget(buttons);
634#if !QT_CONFIG(messagebox)
635 QObject::connect(buttons, SIGNAL(accepted()), q, SLOT(accept()));
637 QObject::connect(buttons, SIGNAL(accepted()), q, SLOT(_q_checkFields()));
639 QObject::connect(buttons, SIGNAL(rejected()), q, SLOT(reject()));
641 QObject::connect(options.printSelection, SIGNAL(toggled(
bool)),
642 q, SLOT(_q_togglePageSetCombo(
bool)));
644 QObject::connect(options.printCurrentPage, SIGNAL(toggled(
bool)),
645 q, SLOT(_q_togglePageSetCombo(
bool)));
647 QObject::connect(collapseButton, SIGNAL(released()), q, SLOT(_q_collapseOrExpandDialog()));
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); });
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); });
664 QPrinter *p = q->printer();
665 printerOutputFormat = outputFormat;
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));
672 if (p->colorMode() == QPrinter::Color)
673 options.color->setChecked(
true);
675 options.grayscale->setChecked(
true);
680 QPrint::DuplexMode duplex;
681 if (explicitDuplexMode != QPrint::DuplexAuto && supportedDuplexMode.contains(explicitDuplexMode))
682 duplex = explicitDuplexMode;
684 duplex =
static_cast<QPrint::DuplexMode>(p->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;
694 options.copies->setValue(p->copyCount());
695 options.collate->setChecked(p->collateCopies());
696 options.reverse->setChecked(p->pageOrder() == QPrinter::LastPageFirst);
698 if (outputFormat == QPrinter::PdfFormat || options.printSelection->isChecked()
699 || options.printCurrentPage->isChecked())
701 options.pageSetCombo->setEnabled(
false);
703 options.pageSetCombo->setEnabled(
true);
709 options.pagesRadioButton->setEnabled(outputFormat != QPrinter::PdfFormat);
712 options.colorMode->setVisible(outputFormat == QPrinter::PdfFormat);
718void QPrintDialogPrivate::updatePpdDuplexOption(QRadioButton *radio)
720 const bool checked = radio->isChecked();
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);
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());
734 explicitDuplexMode = duplexMode;
744 QPrinter* p = q->printer();
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);
752 p->setDuplex(QPrinter::DuplexShortSide);
757 if (p->outputFormat() == QPrinter::PdfFormat)
759 p->setColorMode(options.color->isChecked() ? QPrinter::Color : QPrinter::GrayScale);
761 p->setPageOrder(options.reverse->isChecked() ? QPrinter::LastPageFirst : QPrinter::FirstPageFirst);
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()));
780 p->setPrintRange(QPrinter::AllPages);
781 p->setPageRanges(QPageRanges());
786 if (options.pagesRadioButton->isChecked()) {
787 const QPageRanges ranges = QPageRanges::fromString(options.pagesLineEdit->text());
788 p->setPrintRange(QPrinter::AllPages);
789 p->setPageRanges(QPageRanges());
792 QCUPSSupport::setPageRange(p, ranges.toString());
796 if (p->printRange() == QPrinter::AllPages || p->printRange() == QPrinter::PageRange) {
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)) {
804 case QCUPSSupport::AllPages:
806 case QCUPSSupport::OddPages:
807 QCUPSSupport::setPageSet(p, QCUPSSupport::EvenPages);
809 case QCUPSSupport::EvenPages:
810 QCUPSSupport::setPageSet(p, QCUPSSupport::OddPages);
813 }
else if (pageSet != QCUPSSupport::AllPages) {
814 QCUPSSupport::setPageSet(p, pageSet);
819 if (!q->testOption(QPrintDialog::PrintPageRange) && options.printRange->isChecked())
820 QCUPSSupport::setPageRange(p, options.from->value(), qMax(options.from->value(), options.to->value()));
825 p->setCopyCount(options.copies->value());
826 p->setCollateCopies(options.collate->isChecked());
831 if (printerOutputFormat == QPrinter::PdfFormat)
834 options.pageSetCombo->setDisabled(checked);
839 int collapseHeight = 0;
841 QWidget *widgetToHide = bottom;
842 if (widgetToHide->isVisible()) {
843 collapseButton->setText(QPrintDialog::tr(
"&Options >>"));
844 collapseHeight = widgetToHide->y() + widgetToHide->height() - (
top->y() +
top->height());
847 collapseButton->setText(QPrintDialog::tr(
"&Options <<"));
848 widgetToHide->setVisible(! widgetToHide->isVisible());
849 if (! widgetToHide->isVisible()) {
850 q->layout()->activate();
851 q->resize( QSize(q->width(), q->height() - collapseHeight) );
855#if QT_CONFIG(messagebox)
856void QPrintDialogPrivate::_q_checkFields()
859 if (top->d->checkFields())
868 options.gbPrintRange->setVisible(q->testOption(QPrintDialog::PrintPageRange) ||
869 q->testOption(QPrintDialog::PrintSelection) ||
870 q->testOption(QPrintDialog::PrintCurrentPage));
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));
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);
884 options.pageSetCombo->setVisible(
true);
885 options.pageSetLabel->setVisible(
true);
888 if (!q->testOption(QPrintDialog::PrintPageRange)) {
891 options.gbPrintRange->setVisible(
true);
892 options.printRange->setEnabled(
true);
896 switch (q->printRange()) {
897 case QPrintDialog::AllPages:
898 options.printAll->setChecked(
true);
899 options.pageSetCombo->setEnabled(
true);
901 case QPrintDialog::Selection:
902 options.printSelection->setChecked(
true);
903 options.pageSetCombo->setEnabled(
false);
905 case QPrintDialog::PageRange:
906 options.printRange->setChecked(
true);
907 options.pageSetCombo->setEnabled(
true);
909 case QPrintDialog::CurrentPage:
910 if (q->testOption(QPrintDialog::PrintCurrentPage)) {
911 options.printCurrentPage->setChecked(
true);
912 options.pageSetCombo->setEnabled(
false);
918 const int minPage = qMax(1, qMin(q->minPage() , q->maxPage()));
919 const int maxPage = qMax(1, q->maxPage() == INT_MAX ? 9999 : q->maxPage());
921 options.from->setMinimum(minPage);
922 options.to->setMinimum(minPage);
923 options.from->setMaximum(maxPage);
924 options.to->setMaximum(maxPage);
926 options.from->setValue(q->fromPage());
927 options.to->setValue(q->toPage());
933 QList<QWidget*>::ConstIterator iter = tabWidgets.begin();
934 while(iter != tabWidgets.constEnd()) {
935 QWidget *tab = *iter;
936 options.tabs->addTab(tab, tab->windowTitle());
945
946
947
948
949
950
952QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent)
953 : QAbstractPrintDialog(*(
new QPrintDialogPrivate), printer, parent)
960
961
962QPrintDialog::QPrintDialog(QWidget *parent)
963 : QAbstractPrintDialog(*(
new QPrintDialogPrivate),
nullptr, parent)
969QPrintDialog::~QPrintDialog()
973void QPrintDialog::setVisible(
bool visible)
980 QAbstractPrintDialog::setVisible(visible);
983int QPrintDialog::exec()
985 return QAbstractPrintDialog::exec();
988void QPrintDialog::accept()
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);
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)
1019
1020
1021
1022
1023
1024
1026#if defined (Q_OS_UNIX)
1029
1030QUnixPrintWidgetPrivate::QUnixPrintWidgetPrivate(QUnixPrintWidget *p, QPrinter *prn)
1031 : parent(p), propertiesDialog(
nullptr), printer(prn),
1033 m_duplexPpdOption(
nullptr),
1035 optionsPane(
nullptr), filePrintersAdded(
false)
1039 q = qobject_cast<QPrintDialog*> (parent->parent());
1041 widget.setupUi(parent);
1043 int currentPrinterIndex = 0;
1044 QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
1046 const QStringList printers = ps->availablePrintDeviceIds();
1047 const QString defaultPrinter = ps->defaultPrintDeviceId();
1049 widget.printers->addItems(printers);
1051 const QString selectedPrinter = prn && !prn->printerName().isEmpty() ? prn->printerName() : defaultPrinter;
1052 const int idx = printers.indexOf(selectedPrinter);
1055 currentPrinterIndex = idx;
1057 widget.properties->setEnabled(
true);
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));
1064 _q_printerChanged(currentPrinterIndex);
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()));
1072 widget.preview->setVisible(
false);
1075void QUnixPrintWidgetPrivate::updateWidget()
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);
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);
1091 filePrintersAdded =
false;
1093 if (printer && filePrintersAdded && (printer->outputFormat() != QPrinter::NativeFormat
1094 || printer->printerName().isEmpty()))
1096 if (printer->outputFormat() == QPrinter::PdfFormat)
1097 widget.printers->setCurrentIndex(widget.printers->count() - 1);
1098 widget.filename->setEnabled(
true);
1099 widget.lOutput->setEnabled(
true);
1102 widget.filename->setVisible(printToFile);
1103 widget.lOutput->setVisible(printToFile);
1104 widget.fileBrowser->setVisible(printToFile);
1107 widget.properties->setVisible(q->testOption(QAbstractPrintDialog::PrintShowPageSize));
1110QUnixPrintWidgetPrivate::~QUnixPrintWidgetPrivate()
1114void QUnixPrintWidgetPrivate::_q_printerChanged(
int index)
1118 const int printerCount = widget.printers->count();
1119 widget.filename->setEnabled(
false);
1120 widget.lOutput->setEnabled(
false);
1123 if (propertiesDialog){
1124 delete propertiesDialog;
1125 propertiesDialog =
nullptr;
1129 m_duplexPpdOption =
nullptr;
1132 if (filePrintersAdded) {
1133 Q_ASSERT(index != printerCount - 2);
1134 if (index == printerCount - 1) {
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();
1145 optionsPane->selectPrinter(QPrinter::PdfFormat);
1151 printer->setOutputFormat(QPrinter::NativeFormat);
1153 QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
1155 m_currentPrintDevice = ps->createPrintDevice(widget.printers->itemText(index));
1157 m_currentPrintDevice = QPrintDevice();
1159 printer->setPrinterName(m_currentPrintDevice.id());
1161 widget.location->setText(m_currentPrintDevice.location());
1162 widget.type->setText(m_currentPrintDevice.makeAndModel());
1164 optionsPane->selectPrinter(QPrinter::NativeFormat);
1168 m_duplexPpdOption = QCUPSSupport::findPpdOption(
"Duplex", &m_currentPrintDevice);
1172void QUnixPrintWidgetPrivate::setOptionsPane(QPrintDialogPrivate *pane)
1176 optionsPane->selectPrinter(QPrinter::NativeFormat);
1179void QUnixPrintWidgetPrivate::_q_btnBrowseClicked()
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);
1188 if (!filename.isEmpty()) {
1189 widget.filename->setText(filename);
1190 widget.printers->setCurrentIndex(widget.printers->count() - 1);
1194#if QT_CONFIG(messagebox)
1195bool QUnixPrintWidgetPrivate::checkFields()
1197 if (widget.filename->isEnabled()) {
1198 QString file = widget.filename->text();
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));
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));
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)
1226 if (propertiesDialog) {
1227 QCUPSSupport::PagesPerSheet pagesPerSheet = qvariant_cast<QCUPSSupport::PagesPerSheet>(propertiesDialog->widget.pageSetup->m_ui.pagesPerSheetCombo
1230 QCUPSSupport::PageSet pageSet = qvariant_cast<QCUPSSupport::PageSet>(optionsPane->options.pageSetCombo->currentData());
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."));
1247void QUnixPrintWidgetPrivate::setupPrinterProperties()
1249 delete propertiesDialog;
1251 QPrinter::OutputFormat outputFormat;
1252 QString printerName;
1254 if (q->testOption(QPrintDialog::PrintToFile)
1255 && (widget.printers->currentIndex() == widget.printers->count() - 1)) {
1256 outputFormat = QPrinter::PdfFormat;
1258 outputFormat = QPrinter::NativeFormat;
1259 printerName = widget.printers->currentText();
1262 propertiesDialog =
new QPrintPropertiesDialog(q->printer(), &m_currentPrintDevice, outputFormat, printerName, q);
1266void QUnixPrintWidgetPrivate::setPpdDuplex(QPrinter::DuplexMode mode)
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");
1273 m_currentPrintDevice.setProperty(PDPK_PpdOption, values);
1277void QUnixPrintWidgetPrivate::_q_btnPropertiesClicked()
1279 if (!propertiesDialog)
1280 setupPrinterProperties();
1281 propertiesDialog->exec();
1285 optionsPane->updatePpdDuplexOption(optionsPane->options.noDuplex);
1286 optionsPane->updatePpdDuplexOption(optionsPane->options.duplexLong);
1287 optionsPane->updatePpdDuplexOption(optionsPane->options.duplexShort);
1291void QUnixPrintWidgetPrivate::setupPrinter()
1293 const int printerCount = widget.printers->count();
1294 const int index = widget.printers->currentIndex();
1296 if (filePrintersAdded && index == printerCount - 1) {
1297 printer->setPrinterName(QString());
1298 Q_ASSERT(index != printerCount - 2);
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);
1306 printer->setPrinterName(widget.printers->currentText());
1307 printer->setOutputFileName(QString());
1310 if (!propertiesDialog)
1311 setupPrinterProperties();
1313 propertiesDialog->setupPrinter();
1317
1318QUnixPrintWidget::QUnixPrintWidget(QPrinter *printer, QWidget *parent)
1319 : QWidget(parent), d(
new QUnixPrintWidgetPrivate(
this, printer))
1321 if (printer ==
nullptr)
1323 if (printer->outputFileName().isEmpty()) {
1324 QString home = QDir::homePath();
1325 QString cur = QDir::currentPath();
1326 if (!home.endsWith(u'/'))
1328 if (!cur.startsWith(home))
1330 else if (!cur.endsWith(u'/'))
1332 if (QGuiApplication::platformName() ==
"xcb"_L1) {
1333 if (printer->docName().isEmpty()) {
1334 cur +=
"print.pdf"_L1;
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);
1343 cur += printer->docName();
1348 d->widget.filename->setText(cur);
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);
1356 d->widget.printers->setCurrentIndex(i);
1362
1363QUnixPrintWidget::~QUnixPrintWidget()
1369
1370
1371
1372void QUnixPrintWidget::updatePrinter()
1387#include "moc_qprintdialog.cpp"
1388#include "qprintdialog_unix.moc"
void selectPrinter(const QPrinter::OutputFormat outputFormat)
void _q_togglePageSetCombo(bool)
QPushButton * collapseButton
virtual void setTabs(const QList< QWidget * > &tabs) override
QDialogButtonBox * buttons
Ui::QPrintSettingsOutput options
void _q_collapseOrExpandDialog()
QPrinter::OutputFormat printerOutputFormat
~QPrintPropertiesDialog()
void setupPrinter() const
void showEvent(QShowEvent *event) override
\reimp
static void _q_pdu_initResources()