5#include "qplatformdefs.h"
6#include <QtPrintSupport/private/qtprintsupportglobal_p.h>
8#include "private/qabstractprintdialog_p.h"
9#if QT_CONFIG(messagebox)
10#include <QtWidgets/qmessagebox.h>
13#if QT_CONFIG(filedialog)
14#include "qfiledialog.h"
16#include <QtCore/qdebug.h>
17#include <QtCore/qdir.h>
18#include <QtCore/qglobal.h>
19#include <QtCore/qstringconverter.h>
20#include <QtGui/qevent.h>
21#if QT_CONFIG(filesystemmodel)
22#include <QtGui/qfilesystemmodel.h>
24#include <QtWidgets/qstyleditemdelegate.h>
25#include <QtWidgets/qformlayout.h>
26#include <QtPrintSupport/qprinter.h>
28#include <qpa/qplatformprintplugin.h>
29#include <qpa/qplatformprintersupport.h>
31#include <private/qprintdevice_p.h>
33#include <QtWidgets/qdialogbuttonbox.h>
35#if QT_CONFIG(regularexpression)
36#include <qregularexpression.h>
39#if QT_CONFIG(completer)
40#include <private/qcompleter_p.h>
42#include "ui_qprintpropertieswidget.h"
43#include "ui_qprintsettingsoutput.h"
44#include "ui_qprintwidget.h"
48#include <private/qcups_p.h>
49#if QT_CONFIG(cupsjobwidget)
50#include "qcupsjobwidget_p.h"
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
85
89 Q_INIT_RESOURCE(qprintdialog);
94using namespace Qt::StringLiterals;
118 Ui::QPrintPropertiesWidget widget;
119 QDialogButtonBox *m_buttons;
120#if QT_CONFIG(cupsjobwidget)
151 friend class QPrintDialog;
155 Q_PRIVATE_SLOT(d,
void _q_printerChanged(
int))
191 bool filePrintersAdded;
196 Q_DECLARE_PUBLIC(QPrintDialog)
207#if QT_CONFIG(messagebox)
218 virtual void setTabs(
const QList<QWidget*> &tabs)
override;
227 void setExplicitDuplexMode(QPrint::DuplexMode duplexMode);
229 QPrint::DuplexMode explicitDuplexMode;
236
237
238
239
240
241
242
245 QPrinter::OutputFormat outputFormat,
const QString &printerName,
246 QAbstractPrintDialog *parent)
252 setWindowTitle(tr(
"Printer Properties"));
253 QVBoxLayout *lay =
new QVBoxLayout(
this);
254 QWidget *content =
new QWidget(
this);
255 widget.setupUi(content);
256 m_buttons =
new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal,
this);
257 lay->addWidget(content);
258 lay->addWidget(m_buttons);
261 connect(m_buttons->button(QDialogButtonBox::Cancel), &QPushButton::clicked,
this, &QPrintPropertiesDialog::reject);
263 widget.pageSetup->setPrinter(printer, currentPrintDevice, outputFormat, printerName);
265#if QT_CONFIG(cupsjobwidget)
266 m_jobOptions =
new QCupsJobWidget(printer, currentPrintDevice);
267 widget.tabs->insertTab(1, m_jobOptions, tr(
"Job Options"));
270 const int advancedTabIndex = widget.tabs->indexOf(widget.cupsPropertiesPage);
272 m_currentPrintDevice = currentPrintDevice;
273 const bool anyWidgetCreated = createAdvancedOptionsWidget();
275 widget.tabs->setTabEnabled(advancedTabIndex, anyWidgetCreated);
277 connect(widget.pageSetup, &QPageSetupWidget::ppdOptionChanged,
this, [
this] {
278 widget.conflictsLabel->setVisible(anyPpdOptionConflict());
282 Q_UNUSED(currentPrintDevice);
283 widget.tabs->setTabEnabled(advancedTabIndex,
false);
294 QCUPSSupport::clearCupsOptions(m_printer);
297 widget.pageSetup->setupPrinter();
298#if QT_CONFIG(cupsjobwidget)
299 m_jobOptions->setupPrinter();
304 m_printer->setColorMode(QPrinter::Color);
306 setPrinterAdvancedCupsOptions();
312 widget.pageSetup->revertToSavedValues();
314#if QT_CONFIG(cupsjobwidget)
315 m_jobOptions->revertToSavedValues();
319 revertAdvancedOptionsToSavedValues();
326#if QT_CONFIG(cups) && QT_CONFIG(messagebox)
327 if (widget.pageSetup->hasPpdConflict()) {
328 widget.tabs->setCurrentWidget(widget.tabPage);
329 const QMessageBox::StandardButton answer = QMessageBox::warning(
this, tr(
"Page Setup Conflicts"),
330 tr(
"There are conflicts in page setup options. Do you want to fix them?"),
331 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
332 if (answer != QMessageBox::No)
334 }
else if (anyAdvancedOptionConflict()) {
335 widget.tabs->setCurrentWidget(widget.cupsPropertiesPage);
336 const QMessageBox::StandardButton answer = QMessageBox::warning(
this, tr(
"Advanced Option Conflicts"),
337 tr(
"There are conflicts in some advanced options. Do you want to fix them?"),
338 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
339 if (answer != QMessageBox::No)
342 advancedOptionsUpdateSavedValues();
345#if QT_CONFIG(cupsjobwidget)
346 m_jobOptions->updateSavedValues();
349 widget.pageSetup->updateSavedValues();
357 widget.conflictsLabel->setVisible(anyPpdOptionConflict());
359 QDialog::showEvent(event);
365static const char *ppdOptionProperty =
"_q_ppd_option";
368static const char *ppdOriginallySelectedChoiceProperty =
"_q_ppd_originally_selected_choice";
371static const char *customValueLineEditProperty =
"_q_custom_value_lineedit";
374static const char *warningLabelProperty =
"_q_warning_label";
376static bool isBlacklistedGroup(
const ppd_group_t *group)
noexcept
378 return qstrcmp(group->name,
"InstallableOptions") == 0;
381static bool isBlacklistedOption(
const char *keyword)
noexcept
384 const char *cupsOptionBlacklist[] = {
392 auto equals = [](
const char *keyword) {
393 return [keyword](
const char *candidate) {
394 return qstrcmp(keyword, candidate) == 0;
397 return std::any_of(std::begin(cupsOptionBlacklist), std::end(cupsOptionBlacklist), equals(keyword));
400bool QPrintPropertiesDialog::createAdvancedOptionsWidget()
402 bool anyWidgetCreated =
false;
404 ppd_file_t *ppd = qvariant_cast<ppd_file_t*>(m_currentPrintDevice->property(PDPK_PpdFile));
407 toUnicode = QStringDecoder(ppd->lang_encoding, QStringDecoder::Flag::Stateless);
408 if (!toUnicode.isValid()) {
409 qWarning() <<
"QPrinSupport: Cups uses unsupported encoding" << ppd->lang_encoding;
410 toUnicode = QStringDecoder(QStringDecoder::Utf8, QStringDecoder::Flag::Stateless);
413 QWidget *holdingWidget =
new QWidget();
414 QVBoxLayout *layout =
new QVBoxLayout(holdingWidget);
416 for (
int i = 0; i < ppd->num_groups; ++i) {
417 const ppd_group_t *group = &ppd->groups[i];
419 if (!isBlacklistedGroup(group)) {
420 QFormLayout *groupLayout =
new QFormLayout();
422 for (
int i = 0; i < group->num_options; ++i) {
423 const ppd_option_t *option = &group->options[i];
425 if (!isBlacklistedOption(option->keyword)) {
426 QComboBox *choicesCb =
new QComboBox();
428 const auto setPpdOptionFromCombo = [
this, choicesCb, option] {
432 const int selectedChoiceIndex = choicesCb->currentData().toInt();
433 const QString &choice = QString::fromLatin1(
434 option->choices[selectedChoiceIndex].choice);
435 const QStringList &values { QString::fromLatin1(option->keyword), choice };
436 m_currentPrintDevice->setProperty(PDPK_PpdOption, values);
437 widget.conflictsLabel->setVisible(anyPpdOptionConflict());
439 if (
auto *customValueEdit = qvariant_cast<QLineEdit *>(
440 choicesCb->property(customValueLineEditProperty))) {
441 const bool customSelected = choice == u"Custom";
442 customValueEdit->setVisible(customSelected);
443 if (customSelected) {
444 const QStringList params{ QString::fromLatin1(
447 m_currentPrintDevice->property(PDPK_OptionValue, params)
449 if (value.startsWith(u"Custom."))
450 customValueEdit->setText(value.mid(7));
455 bool foundMarkedChoice =
false;
456 bool markedChoiceNotAvailable =
false;
457 for (
int i = 0; i < option->num_choices; ++i) {
458 const ppd_choice_t *choice = &option->choices[i];
459 const auto values = QStringList{} << QString::fromLatin1(option->keyword) << QString::fromLatin1(choice->choice);
460 const bool choiceIsInstallableConflict = m_currentPrintDevice->isFeatureAvailable(PDPK_PpdChoiceIsInstallableConflict, values);
461 if (choiceIsInstallableConflict &&
static_cast<
int>(choice->marked) == 1) {
462 markedChoiceNotAvailable =
true;
463 }
else if (!choiceIsInstallableConflict) {
464 choicesCb->addItem(toUnicode(choice->text), i);
465 if (
static_cast<
int>(choice->marked) == 1) {
466 choicesCb->setCurrentIndex(choicesCb->count() - 1);
467 choicesCb->setProperty(ppdOriginallySelectedChoiceProperty, QVariant(i));
468 foundMarkedChoice =
true;
469 }
else if (!foundMarkedChoice && qstrcmp(choice->choice, option->defchoice) == 0) {
470 choicesCb->setCurrentIndex(choicesCb->count() - 1);
471 choicesCb->setProperty(ppdOriginallySelectedChoiceProperty, QVariant(i));
476 if (markedChoiceNotAvailable) {
480 setPpdOptionFromCombo();
483 if (choicesCb->count() > 1) {
485 connect(choicesCb, &QComboBox::currentIndexChanged,
this, setPpdOptionFromCombo);
488 QWidget *choicesCbWithLabel =
new QWidget();
489 QHBoxLayout *choicesCbWithLabelLayout =
new QHBoxLayout(choicesCbWithLabel);
490 choicesCbWithLabelLayout->setContentsMargins(0, 0, 0, 0);
491 QLabel *warningLabel =
new QLabel();
492 choicesCbWithLabelLayout->addWidget(choicesCb);
494 const QString &optionText = toUnicode(option->text);
495 const QStringList ¶ms{ QString::fromLatin1(option->keyword) };
496 const bool hasCustomOption = m_currentPrintDevice->isFeatureAvailable(
497 PDPK_PpdCustomOption, params);
498 if (hasCustomOption) {
499 auto *customValueEdit =
new QLineEdit;
500#if QT_CONFIG(accessibility)
501 customValueEdit->setAccessibleName(
502 tr(
"Custom value for %1").arg(optionText));
504 choicesCbWithLabelLayout->addWidget(customValueEdit);
505 choicesCb->setProperty(customValueLineEditProperty,
506 QVariant::fromValue(customValueEdit));
508 setPpdOptionFromCombo();
510 choicesCbWithLabelLayout->addWidget(warningLabel);
512 QLabel *optionLabel =
new QLabel(optionText);
513 optionLabel->setBuddy(choicesCb);
514 groupLayout->addRow(optionLabel, choicesCbWithLabel);
515 anyWidgetCreated =
true;
516 choicesCb->setProperty(ppdOptionProperty, QVariant::fromValue(option));
517 choicesCb->setProperty(warningLabelProperty, QVariant::fromValue(warningLabel));
518 m_advancedOptionsCombos << choicesCb;
525 if (groupLayout->rowCount() > 0) {
526 QGroupBox *groupBox =
new QGroupBox(toUnicode(group->text));
527 groupBox->setLayout(groupLayout);
528 layout->addWidget(groupBox);
535 layout->addStretch();
536 widget.scrollArea->setWidget(holdingWidget);
539 return anyWidgetCreated;
542void QPrintPropertiesDialog::setPrinterAdvancedCupsOptions()
const
544 for (
const QComboBox *choicesCb : m_advancedOptionsCombos) {
545 const ppd_option_t *option = qvariant_cast<
const ppd_option_t *>(choicesCb->property(ppdOptionProperty));
550 const int selectedChoiceIndex = choicesCb->currentData().toInt();
551 QString selectedChoice = QString::fromLatin1(option->choices[selectedChoiceIndex].choice);
553 if (selectedChoice == u"Custom") {
554 if (
auto *customValueEdit = qvariant_cast<QLineEdit *>(
555 choicesCb->property(customValueLineEditProperty))) {
556 const QString &customValue = customValueEdit->text();
557 if (!customValue.isEmpty())
558 selectedChoice = u"Custom." + customValue;
562 if (qstrcmp(option->keyword,
"ColorModel") == 0)
563 m_printer->setColorMode(selectedChoice == u"Gray" ? QPrinter::GrayScale
566 if (qstrcmp(option->defchoice, selectedChoice.toLatin1().constData()) != 0)
567 QCUPSSupport::setCupsOption(m_printer, QString::fromLatin1(option->keyword),
572void QPrintPropertiesDialog::revertAdvancedOptionsToSavedValues()
const
574 for (QComboBox *choicesCb : m_advancedOptionsCombos) {
575 const int originallySelectedChoice = qvariant_cast<
int>(choicesCb->property(ppdOriginallySelectedChoiceProperty));
576 const int newComboIndexToSelect = choicesCb->findData(originallySelectedChoice);
577 choicesCb->setCurrentIndex(newComboIndexToSelect);
580 widget.conflictsLabel->setVisible(anyPpdOptionConflict());
583void QPrintPropertiesDialog::advancedOptionsUpdateSavedValues()
const
585 for (QComboBox *choicesCb : m_advancedOptionsCombos)
586 choicesCb->setProperty(ppdOriginallySelectedChoiceProperty, choicesCb->currentData());
589bool QPrintPropertiesDialog::anyPpdOptionConflict()
const
592 const bool pageSetupConflicts = widget.pageSetup->hasPpdConflict();
593 const bool advancedOptionConflicts = anyAdvancedOptionConflict();
594 return pageSetupConflicts || advancedOptionConflicts;
597bool QPrintPropertiesDialog::anyAdvancedOptionConflict()
const
599 const QIcon warning = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning,
nullptr,
nullptr);
601 bool anyConflicted =
false;
603 for (
const QComboBox *choicesCb : m_advancedOptionsCombos) {
604 const ppd_option_t *option = qvariant_cast<
const ppd_option_t *>(choicesCb->property(ppdOptionProperty));
605 QLabel *warningLabel = qvariant_cast<QLabel *>(choicesCb->property(warningLabelProperty));
606 if (option->conflicted) {
607 anyConflicted =
true;
608 const int pixmap_size = choicesCb->sizeHint().height() * .75;
609 warningLabel->setPixmap(warning.pixmap(pixmap_size, pixmap_size));
611 warningLabel->setPixmap(QPixmap());
615 return anyConflicted;
625
626
627
628
629
630
631
634 explicitDuplexMode(QPrint::DuplexAuto)
647 top =
new QUnixPrintWidget(q->printer(), q);
648 bottom =
new QWidget(q);
649 options.setupUi(bottom);
650 options.color->setIconSize(QSize(32, 32));
651 options.color->setIcon(QIcon(
":/qt-project.org/dialogs/qprintdialog/images/status-color.png"_L1));
652 options.grayscale->setIconSize(QSize(32, 32));
653 options.grayscale->setIcon(QIcon(
":/qt-project.org/dialogs/qprintdialog/images/status-gray-scale.png"_L1));
657 options.pageSetCombo->addItem(tr(
"All Pages"), QVariant::fromValue(QCUPSSupport::AllPages));
658 options.pageSetCombo->addItem(tr(
"Odd Pages"), QVariant::fromValue(QCUPSSupport::OddPages));
659 options.pageSetCombo->addItem(tr(
"Even Pages"), QVariant::fromValue(QCUPSSupport::EvenPages));
661 delete options.pagesRadioButton;
662 delete options.pagesLineEdit;
663 options.pagesRadioButton =
nullptr;
664 options.pagesLineEdit =
nullptr;
669 buttons =
new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, q);
670 collapseButton =
new QPushButton(QPrintDialog::tr(
"&Options >>"), buttons);
671 buttons->addButton(collapseButton, QDialogButtonBox::ResetRole);
672 bottom->setVisible(
false);
674 QPushButton *printButton = buttons->button(QDialogButtonBox::Ok);
675 printButton->setText(QPrintDialog::tr(
"&Print"));
676 printButton->setDefault(
true);
678 QVBoxLayout *lay =
new QVBoxLayout(q);
680 lay->addWidget(bottom);
681 lay->addWidget(buttons);
683#if !QT_CONFIG(messagebox)
684 QObject::connect(buttons, SIGNAL(accepted()), q, SLOT(accept()));
686 QObject::connect(buttons, SIGNAL(accepted()), q, SLOT(_q_checkFields()));
688 QObject::connect(buttons, SIGNAL(rejected()), q, SLOT(reject()));
690 QObject::connect(options.printSelection, SIGNAL(toggled(
bool)),
691 q, SLOT(_q_togglePageSetCombo(
bool)));
693 QObject::connect(options.printCurrentPage, SIGNAL(toggled(
bool)),
694 q, SLOT(_q_togglePageSetCombo(
bool)));
696 QObject::connect(collapseButton, SIGNAL(released()), q, SLOT(_q_collapseOrExpandDialog()));
698 QObject::connect(options.noDuplex, &QAbstractButton::clicked, q, [
this] { setExplicitDuplexMode(QPrint::DuplexNone); });
699 QObject::connect(options.duplexLong, &QAbstractButton::clicked, q, [
this] { setExplicitDuplexMode(QPrint::DuplexLongSide); });
700 QObject::connect(options.duplexShort, &QAbstractButton::clicked, q, [
this] { setExplicitDuplexMode(QPrint::DuplexShortSide); });
703 QObject::connect(options.noDuplex, &QAbstractButton::toggled, q, [
this] { updatePpdDuplexOption(options.noDuplex); });
704 QObject::connect(options.duplexLong, &QAbstractButton::toggled, q, [
this] { updatePpdDuplexOption(options.duplexLong); });
705 QObject::connect(options.duplexShort, &QAbstractButton::toggled, q, [
this] { updatePpdDuplexOption(options.duplexShort); });
713 QPrinter *p = q->printer();
714 printerOutputFormat = outputFormat;
717 const auto supportedDuplexMode =
top->d->m_currentPrintDevice.supportedDuplexModes();
718 options.duplexLong->setEnabled(supportedDuplexMode.contains(QPrint::DuplexLongSide));
719 options.duplexShort->setEnabled(supportedDuplexMode.contains(QPrint::DuplexShortSide));
721 if (p->colorMode() == QPrinter::Color)
722 options.color->setChecked(
true);
724 options.grayscale->setChecked(
true);
729 QPrint::DuplexMode duplex;
730 if (explicitDuplexMode != QPrint::DuplexAuto && supportedDuplexMode.contains(explicitDuplexMode))
731 duplex = explicitDuplexMode;
733 duplex =
static_cast<QPrint::DuplexMode>(p->duplex());
735 case QPrint::DuplexNone:
736 options.noDuplex->setChecked(
true);
break;
737 case QPrint::DuplexLongSide:
738 case QPrint::DuplexAuto:
739 options.duplexLong->setChecked(
true);
break;
740 case QPrint::DuplexShortSide:
741 options.duplexShort->setChecked(
true);
break;
743 options.copies->setValue(p->copyCount());
744 options.collate->setChecked(p->collateCopies());
745 options.reverse->setChecked(p->pageOrder() == QPrinter::LastPageFirst);
747 if (outputFormat == QPrinter::PdfFormat || options.printSelection->isChecked()
748 || options.printCurrentPage->isChecked())
750 options.pageSetCombo->setEnabled(
false);
752 options.pageSetCombo->setEnabled(
true);
758 options.pagesRadioButton->setEnabled(outputFormat != QPrinter::PdfFormat);
761 options.colorMode->setVisible(outputFormat == QPrinter::PdfFormat);
767void QPrintDialogPrivate::updatePpdDuplexOption(QRadioButton *radio)
769 const bool checked = radio->isChecked();
771 if (radio == options.noDuplex) top->d->setPpdDuplex(QPrinter::DuplexNone);
772 else if (radio == options.duplexLong) top->d->setPpdDuplex(QPrinter::DuplexLongSide);
773 else if (radio == options.duplexShort) top->d->setPpdDuplex(QPrinter::DuplexShortSide);
775 const bool conflict = checked && top->d->m_duplexPpdOption && top->d->m_duplexPpdOption->conflicted;
776 radio->setIcon(conflict ? QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning,
nullptr,
nullptr) : QIcon());
783 explicitDuplexMode = duplexMode;
793 QPrinter* p = q->printer();
795 if (options.duplex->isEnabled()) {
796 if (options.noDuplex->isChecked())
797 p->setDuplex(QPrinter::DuplexNone);
798 else if (options.duplexLong->isChecked())
799 p->setDuplex(QPrinter::DuplexLongSide);
801 p->setDuplex(QPrinter::DuplexShortSide);
806 if (p->outputFormat() == QPrinter::PdfFormat)
808 p->setColorMode(options.color->isChecked() ? QPrinter::Color : QPrinter::GrayScale);
810 p->setPageOrder(options.reverse->isChecked() ? QPrinter::LastPageFirst : QPrinter::FirstPageFirst);
813 if (options.printAll->isChecked()) {
814 p->setPrintRange(QPrinter::AllPages);
815 p->setPageRanges(QPageRanges());
816 }
else if (options.printSelection->isChecked()) {
817 p->setPrintRange(QPrinter::Selection);
818 p->setPageRanges(QPageRanges());
819 }
else if (options.printCurrentPage->isChecked()) {
820 p->setPrintRange(QPrinter::CurrentPage);
821 p->setPageRanges(QPageRanges());
822 }
else if (options.printRange->isChecked()) {
823 if (q->testOption(QPrintDialog::PrintPageRange)) {
824 p->setPrintRange(QPrinter::PageRange);
825 p->setFromTo(options.from->value(), qMax(options.from->value(), options.to->value()));
829 p->setPrintRange(QPrinter::AllPages);
830 p->setPageRanges(QPageRanges());
835 if (options.pagesRadioButton->isChecked()) {
836 const QPageRanges ranges = QPageRanges::fromString(options.pagesLineEdit->text());
837 p->setPrintRange(QPrinter::AllPages);
838 p->setPageRanges(QPageRanges());
841 QCUPSSupport::setPageRange(p, ranges.toString());
845 if (p->printRange() == QPrinter::AllPages || p->printRange() == QPrinter::PageRange) {
847 QCUPSSupport::PageSet pageSet = qvariant_cast<QCUPSSupport::PageSet>(options.pageSetCombo->itemData(options.pageSetCombo->currentIndex()));
848 if (q->testOption(QPrintDialog::PrintPageRange)
849 && p->printRange() == QPrinter::PageRange
850 && (q->fromPage() % 2 == 0)) {
853 case QCUPSSupport::AllPages:
855 case QCUPSSupport::OddPages:
856 QCUPSSupport::setPageSet(p, QCUPSSupport::EvenPages);
858 case QCUPSSupport::EvenPages:
859 QCUPSSupport::setPageSet(p, QCUPSSupport::OddPages);
862 }
else if (pageSet != QCUPSSupport::AllPages) {
863 QCUPSSupport::setPageSet(p, pageSet);
868 if (!q->testOption(QPrintDialog::PrintPageRange) && options.printRange->isChecked())
869 QCUPSSupport::setPageRange(p, options.from->value(), qMax(options.from->value(), options.to->value()));
874 p->setCopyCount(options.copies->value());
875 p->setCollateCopies(options.collate->isChecked());
880 if (printerOutputFormat == QPrinter::PdfFormat)
883 options.pageSetCombo->setDisabled(checked);
888 int collapseHeight = 0;
890 QWidget *widgetToHide = bottom;
891 if (widgetToHide->isVisible()) {
893 collapseHeight = widgetToHide->y() + widgetToHide->height() - (
top->y() +
top->height());
897 widgetToHide->setVisible(! widgetToHide->isVisible());
898 if (! widgetToHide->isVisible()) {
899 q->layout()->activate();
900 q->resize( QSize(q->width(), q->height() - collapseHeight) );
904#if QT_CONFIG(messagebox)
905void QPrintDialogPrivate::_q_checkFields()
908 if (top->d->checkFields())
917 options.gbPrintRange->setVisible(q->testOption(QPrintDialog::PrintPageRange) ||
918 q->testOption(QPrintDialog::PrintSelection) ||
919 q->testOption(QPrintDialog::PrintCurrentPage));
921 options.printRange->setEnabled(q->testOption(QPrintDialog::PrintPageRange));
922 options.printSelection->setVisible(q->testOption(QPrintDialog::PrintSelection));
923 options.printCurrentPage->setVisible(q->testOption(QPrintDialog::PrintCurrentPage));
924 options.collate->setVisible(q->testOption(QPrintDialog::PrintCollateCopies));
928 if (!q->testOption(QPrintDialog::PrintPageRange)
929 && (q->testOption(QPrintDialog::PrintSelection) || q->testOption(QPrintDialog::PrintCurrentPage))) {
930 options.pageSetCombo->setVisible(
false);
931 options.pageSetLabel->setVisible(
false);
933 options.pageSetCombo->setVisible(
true);
934 options.pageSetLabel->setVisible(
true);
937 if (!q->testOption(QPrintDialog::PrintPageRange)) {
940 options.gbPrintRange->setVisible(
true);
941 options.printRange->setEnabled(
true);
945 switch (q->printRange()) {
946 case QPrintDialog::AllPages:
947 options.printAll->setChecked(
true);
948 options.pageSetCombo->setEnabled(
true);
950 case QPrintDialog::Selection:
951 options.printSelection->setChecked(
true);
952 options.pageSetCombo->setEnabled(
false);
954 case QPrintDialog::PageRange:
955 options.printRange->setChecked(
true);
956 options.pageSetCombo->setEnabled(
true);
958 case QPrintDialog::CurrentPage:
959 if (q->testOption(QPrintDialog::PrintCurrentPage)) {
960 options.printCurrentPage->setChecked(
true);
961 options.pageSetCombo->setEnabled(
false);
967 const int minPage = qMax(1, qMin(q->minPage() , q->maxPage()));
968 const int maxPage = qMax(1, q->maxPage() == INT_MAX ? 9999 : q->maxPage());
970 options.from->setMinimum(minPage);
971 options.to->setMinimum(minPage);
972 options.from->setMaximum(maxPage);
973 options.to->setMaximum(maxPage);
975 options.from->setValue(q->fromPage());
976 options.to->setValue(q->toPage());
982 QList<QWidget*>::ConstIterator iter = tabWidgets.begin();
983 while(iter != tabWidgets.constEnd()) {
984 QWidget *tab = *iter;
985 options.tabs->addTab(tab, tab->windowTitle());
994
995
996
997
998
999
1001QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent)
1002 : QAbstractPrintDialog(*(
new QPrintDialogPrivate), printer, parent)
1009
1010
1011QPrintDialog::QPrintDialog(QWidget *parent)
1012 : QAbstractPrintDialog(*(
new QPrintDialogPrivate),
nullptr, parent)
1018QPrintDialog::~QPrintDialog()
1022void QPrintDialog::setVisible(
bool visible)
1029 QAbstractPrintDialog::setVisible(visible);
1032int QPrintDialog::exec()
1034 return QAbstractPrintDialog::exec();
1037void QPrintDialog::accept()
1040#if QT_CONFIG(cups) && QT_CONFIG(messagebox)
1041 if (d->options.pagesRadioButton->isChecked()) {
1042 const QString rangesText = d->options.pagesLineEdit->text();
1043 if (rangesText.isEmpty() || QPageRanges::fromString(rangesText).isEmpty()) {
1044 QMessageBox::critical(
this, tr(
"Invalid Pages Definition"),
1045 tr(
"%1 does not follow the correct syntax. Please use ',' to separate "
1046 "ranges and pages, '-' to define ranges and make sure ranges do "
1047 "not intersect with each other.").arg(rangesText),
1048 QMessageBox::Ok, QMessageBox::Ok);
1052 if (d->top->d->m_duplexPpdOption && d->top->d->m_duplexPpdOption->conflicted) {
1053 const QMessageBox::StandardButton answer = QMessageBox::warning(
this, tr(
"Duplex Settings Conflicts"),
1054 tr(
"There are conflicts in duplex settings. Do you want to fix them?"),
1055 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
1056 if (answer != QMessageBox::No)
1068
1069
1070
1071
1072
1073
1075#if defined (Q_OS_UNIX)
1078
1079QUnixPrintWidgetPrivate::QUnixPrintWidgetPrivate(QUnixPrintWidget *p, QPrinter *prn)
1080 : parent(p), propertiesDialog(
nullptr), printer(prn),
1082 m_duplexPpdOption(
nullptr),
1084 optionsPane(
nullptr), filePrintersAdded(
false)
1088 q = qobject_cast<QPrintDialog*> (parent->parent());
1090 widget.setupUi(parent);
1092 int currentPrinterIndex = 0;
1093 QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
1095 const QStringList printers = ps->availablePrintDeviceIds();
1096 const QString defaultPrinter = ps->defaultPrintDeviceId();
1098 widget.printers->addItems(printers);
1100 const QString selectedPrinter = prn && !prn->printerName().isEmpty() ? prn->printerName() : defaultPrinter;
1101 const int idx = printers.indexOf(selectedPrinter);
1104 currentPrinterIndex = idx;
1106 widget.properties->setEnabled(
true);
1108#if QT_CONFIG(filesystemmodel) && QT_CONFIG(completer)
1109 QFileSystemModel *fsm =
new QFileSystemModel(widget.filename);
1110 fsm->setRootPath(QDir::homePath());
1111 widget.filename->setCompleter(
new QCompleter(fsm, widget.filename));
1113 _q_printerChanged(currentPrinterIndex);
1115 QObject::connect(widget.printers, SIGNAL(currentIndexChanged(
int)),
1116 parent, SLOT(_q_printerChanged(
int)));
1117 QObject::connect(widget.fileBrowser, SIGNAL(clicked()), parent, SLOT(_q_btnBrowseClicked()));
1118 QObject::connect(widget.properties, SIGNAL(clicked()), parent, SLOT(_q_btnPropertiesClicked()));
1121 widget.preview->setVisible(
false);
1124void QUnixPrintWidgetPrivate::updateWidget()
1126 const bool printToFile = q ==
nullptr || q->testOption(QPrintDialog::PrintToFile);
1127 if (printToFile && !filePrintersAdded) {
1128 if (widget.printers->count())
1129 widget.printers->insertSeparator(widget.printers->count());
1130 widget.printers->addItem(QPrintDialog::tr(
"Print to File (PDF)"));
1131 filePrintersAdded =
true;
1132 if (widget.printers->count() == 1)
1133 _q_printerChanged(0);
1135 if (!printToFile && filePrintersAdded) {
1136 widget.printers->removeItem(widget.printers->count()-1);
1137 widget.printers->removeItem(widget.printers->count()-1);
1138 if (widget.printers->count())
1139 widget.printers->removeItem(widget.printers->count()-1);
1140 filePrintersAdded =
false;
1142 if (printer && filePrintersAdded && (printer->outputFormat() != QPrinter::NativeFormat
1143 || printer->printerName().isEmpty()))
1145 if (printer->outputFormat() == QPrinter::PdfFormat)
1146 widget.printers->setCurrentIndex(widget.printers->count() - 1);
1147 widget.filename->setEnabled(
true);
1148 widget.lOutput->setEnabled(
true);
1151 widget.filename->setVisible(printToFile);
1152 widget.lOutput->setVisible(printToFile);
1153 widget.fileBrowser->setVisible(printToFile);
1156 widget.properties->setVisible(q->testOption(QAbstractPrintDialog::PrintShowPageSize));
1159QUnixPrintWidgetPrivate::~QUnixPrintWidgetPrivate()
1163void QUnixPrintWidgetPrivate::_q_printerChanged(
int index)
1167 const int printerCount = widget.printers->count();
1168 widget.filename->setEnabled(
false);
1169 widget.lOutput->setEnabled(
false);
1172 if (propertiesDialog){
1173 delete propertiesDialog;
1174 propertiesDialog =
nullptr;
1178 m_duplexPpdOption =
nullptr;
1181 if (filePrintersAdded) {
1182 Q_ASSERT(index != printerCount - 2);
1183 if (index == printerCount - 1) {
1184 widget.location->setText(QPrintDialog::tr(
"Local file"));
1185 widget.type->setText(QPrintDialog::tr(
"Write PDF file"));
1186 widget.properties->setEnabled(
true);
1187 widget.filename->setEnabled(
true);
1188 QString filename = widget.filename->text();
1189 widget.filename->setText(filename);
1190 widget.lOutput->setEnabled(
true);
1191 printer->setOutputFormat(QPrinter::PdfFormat);
1192 m_currentPrintDevice = QPrintDevice();
1194 optionsPane->selectPrinter(QPrinter::PdfFormat);
1200 printer->setOutputFormat(QPrinter::NativeFormat);
1202 QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
1204 m_currentPrintDevice = ps->createPrintDevice(widget.printers->itemText(index));
1206 m_currentPrintDevice = QPrintDevice();
1208 printer->setPrinterName(m_currentPrintDevice.id());
1210 widget.location->setText(m_currentPrintDevice.location());
1211 widget.type->setText(m_currentPrintDevice.makeAndModel());
1213 optionsPane->selectPrinter(QPrinter::NativeFormat);
1217 m_duplexPpdOption = QCUPSSupport::findPpdOption(
"Duplex", &m_currentPrintDevice);
1221void QUnixPrintWidgetPrivate::setOptionsPane(QPrintDialogPrivate *pane)
1225 optionsPane->selectPrinter(QPrinter::NativeFormat);
1228void QUnixPrintWidgetPrivate::_q_btnBrowseClicked()
1230 QString filename = widget.filename->text();
1231#if QT_CONFIG(filedialog)
1232 filename = QFileDialog::getSaveFileName(parent, QPrintDialog::tr(
"Print To File ..."), filename,
1233 QString(),
nullptr, QFileDialog::DontConfirmOverwrite);
1237 if (!filename.isEmpty()) {
1238 widget.filename->setText(filename);
1239 widget.printers->setCurrentIndex(widget.printers->count() - 1);
1243#if QT_CONFIG(messagebox)
1244bool QUnixPrintWidgetPrivate::checkFields()
1246 if (widget.filename->isEnabled()) {
1247 QString file = widget.filename->text();
1250 bool exists = fi.exists();
1251 bool opened =
false;
1252 if (exists && fi.isDir()) {
1253 QMessageBox::warning(q, q->windowTitle(),
1254 QPrintDialog::tr(
"%1 is a directory.\nPlease choose a different file name.").arg(file));
1256 }
else if ((exists && !fi.isWritable()) || !(opened = f.open(QFile::Append))) {
1257 QMessageBox::warning(q, q->windowTitle(),
1258 QPrintDialog::tr(
"File %1 is not writable.\nPlease choose a different file name.").arg(file));
1260 }
else if (exists) {
1261 int ret = QMessageBox::question(q, q->windowTitle(),
1262 QPrintDialog::tr(
"%1 already exists.\nDo you want to overwrite it?").arg(file),
1263 QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
1264 if (ret == QMessageBox::No)
1275 if (propertiesDialog) {
1276 QCUPSSupport::PagesPerSheet pagesPerSheet = qvariant_cast<QCUPSSupport::PagesPerSheet>(propertiesDialog->widget.pageSetup->m_ui.pagesPerSheetCombo
1279 QCUPSSupport::PageSet pageSet = qvariant_cast<QCUPSSupport::PageSet>(optionsPane->options.pageSetCombo->currentData());
1282 if (pagesPerSheet != QCUPSSupport::OnePagePerSheet
1283 && pageSet != QCUPSSupport::AllPages) {
1284 QMessageBox::warning(q, q->windowTitle(),
1285 QPrintDialog::tr(
"Options 'Pages Per Sheet' and 'Page Set' cannot be used together.\nPlease turn one of those options off."));
1296void QUnixPrintWidgetPrivate::setupPrinterProperties()
1298 delete propertiesDialog;
1300 QPrinter::OutputFormat outputFormat;
1301 QString printerName;
1303 if (q->testOption(QPrintDialog::PrintToFile)
1304 && (widget.printers->currentIndex() == widget.printers->count() - 1)) {
1305 outputFormat = QPrinter::PdfFormat;
1307 outputFormat = QPrinter::NativeFormat;
1308 printerName = widget.printers->currentText();
1311 propertiesDialog =
new QPrintPropertiesDialog(q->printer(), &m_currentPrintDevice, outputFormat, printerName, q);
1315void QUnixPrintWidgetPrivate::setPpdDuplex(QPrinter::DuplexMode mode)
1317 auto values = QStringList{} << QStringLiteral(
"Duplex");
1318 if (mode == QPrinter::DuplexNone) values << QStringLiteral(
"None");
1319 else if (mode == QPrinter::DuplexLongSide) values << QStringLiteral(
"DuplexNoTumble");
1320 else if (mode == QPrinter::DuplexShortSide) values << QStringLiteral(
"DuplexTumble");
1322 m_currentPrintDevice.setProperty(PDPK_PpdOption, values);
1326void QUnixPrintWidgetPrivate::_q_btnPropertiesClicked()
1328 if (!propertiesDialog)
1329 setupPrinterProperties();
1330 propertiesDialog->exec();
1334 optionsPane->updatePpdDuplexOption(optionsPane->options.noDuplex);
1335 optionsPane->updatePpdDuplexOption(optionsPane->options.duplexLong);
1336 optionsPane->updatePpdDuplexOption(optionsPane->options.duplexShort);
1340void QUnixPrintWidgetPrivate::setupPrinter()
1342 const int printerCount = widget.printers->count();
1343 const int index = widget.printers->currentIndex();
1345 if (filePrintersAdded && index == printerCount - 1) {
1346 printer->setPrinterName(QString());
1347 Q_ASSERT(index != printerCount - 2);
1348 printer->setOutputFormat(QPrinter::PdfFormat);
1349 QString path = widget.filename->text();
1350 if (QDir::isRelativePath(path))
1351 path = QDir::homePath() + QDir::separator() + path;
1352 printer->setOutputFileName(path);
1355 printer->setPrinterName(widget.printers->currentText());
1356 printer->setOutputFileName(QString());
1359 if (!propertiesDialog)
1360 setupPrinterProperties();
1362 propertiesDialog->setupPrinter();
1366
1367QUnixPrintWidget::QUnixPrintWidget(QPrinter *printer, QWidget *parent)
1368 : QWidget(parent), d(
new QUnixPrintWidgetPrivate(
this, printer))
1370 if (printer ==
nullptr)
1372 if (printer->outputFileName().isEmpty()) {
1373 QString home = QDir::homePath();
1374 QString cur = QDir::currentPath();
1375 if (!home.endsWith(u'/'))
1377 if (!cur.startsWith(home))
1379 else if (!cur.endsWith(u'/'))
1381 if (QGuiApplication::platformName() ==
"xcb"_L1) {
1382 if (printer->docName().isEmpty()) {
1383 cur +=
"print.pdf"_L1;
1385#if QT_CONFIG(regularexpression)
1386 const QRegularExpression re(QStringLiteral(
"(.*)\\.\\S+"));
1387 auto match = re.match(printer->docName());
1388 if (match.hasMatch())
1389 cur += match.captured(1);
1392 cur += printer->docName();
1397 d->widget.filename->setText(cur);
1400 d->widget.filename->setText(printer->outputFileName());
1401 const QString printerName = printer->printerName();
1402 if (!printerName.isEmpty()) {
1403 const int i = d->widget.printers->findText(printerName);
1405 d->widget.printers->setCurrentIndex(i);
1411
1412QUnixPrintWidget::~QUnixPrintWidget()
1418
1419
1420
1421void QUnixPrintWidget::updatePrinter()
1436#include "moc_qprintdialog.cpp"
1437#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()