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 customValueEdit->setAccessibleName(
501 tr(
"Custom value for %1").arg(optionText));
502 choicesCbWithLabelLayout->addWidget(customValueEdit);
503 choicesCb->setProperty(customValueLineEditProperty,
504 QVariant::fromValue(customValueEdit));
506 setPpdOptionFromCombo();
508 choicesCbWithLabelLayout->addWidget(warningLabel);
510 QLabel *optionLabel =
new QLabel(optionText);
511 optionLabel->setBuddy(choicesCb);
512 groupLayout->addRow(optionLabel, choicesCbWithLabel);
513 anyWidgetCreated =
true;
514 choicesCb->setProperty(ppdOptionProperty, QVariant::fromValue(option));
515 choicesCb->setProperty(warningLabelProperty, QVariant::fromValue(warningLabel));
516 m_advancedOptionsCombos << choicesCb;
523 if (groupLayout->rowCount() > 0) {
524 QGroupBox *groupBox =
new QGroupBox(toUnicode(group->text));
525 groupBox->setLayout(groupLayout);
526 layout->addWidget(groupBox);
533 layout->addStretch();
534 widget.scrollArea->setWidget(holdingWidget);
537 return anyWidgetCreated;
540void QPrintPropertiesDialog::setPrinterAdvancedCupsOptions()
const
542 for (
const QComboBox *choicesCb : m_advancedOptionsCombos) {
543 const ppd_option_t *option = qvariant_cast<
const ppd_option_t *>(choicesCb->property(ppdOptionProperty));
548 const int selectedChoiceIndex = choicesCb->currentData().toInt();
549 QString selectedChoice = QString::fromLatin1(option->choices[selectedChoiceIndex].choice);
551 if (selectedChoice == u"Custom") {
552 if (
auto *customValueEdit = qvariant_cast<QLineEdit *>(
553 choicesCb->property(customValueLineEditProperty))) {
554 const QString &customValue = customValueEdit->text();
555 if (!customValue.isEmpty())
556 selectedChoice = u"Custom." + customValue;
560 if (qstrcmp(option->keyword,
"ColorModel") == 0)
561 m_printer->setColorMode(selectedChoice == u"Gray" ? QPrinter::GrayScale
564 if (qstrcmp(option->defchoice, selectedChoice.toLatin1().constData()) != 0)
565 QCUPSSupport::setCupsOption(m_printer, QString::fromLatin1(option->keyword),
570void QPrintPropertiesDialog::revertAdvancedOptionsToSavedValues()
const
572 for (QComboBox *choicesCb : m_advancedOptionsCombos) {
573 const int originallySelectedChoice = qvariant_cast<
int>(choicesCb->property(ppdOriginallySelectedChoiceProperty));
574 const int newComboIndexToSelect = choicesCb->findData(originallySelectedChoice);
575 choicesCb->setCurrentIndex(newComboIndexToSelect);
578 widget.conflictsLabel->setVisible(anyPpdOptionConflict());
581void QPrintPropertiesDialog::advancedOptionsUpdateSavedValues()
const
583 for (QComboBox *choicesCb : m_advancedOptionsCombos)
584 choicesCb->setProperty(ppdOriginallySelectedChoiceProperty, choicesCb->currentData());
587bool QPrintPropertiesDialog::anyPpdOptionConflict()
const
590 const bool pageSetupConflicts = widget.pageSetup->hasPpdConflict();
591 const bool advancedOptionConflicts = anyAdvancedOptionConflict();
592 return pageSetupConflicts || advancedOptionConflicts;
595bool QPrintPropertiesDialog::anyAdvancedOptionConflict()
const
597 const QIcon warning = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning,
nullptr,
nullptr);
599 bool anyConflicted =
false;
601 for (
const QComboBox *choicesCb : m_advancedOptionsCombos) {
602 const ppd_option_t *option = qvariant_cast<
const ppd_option_t *>(choicesCb->property(ppdOptionProperty));
603 QLabel *warningLabel = qvariant_cast<QLabel *>(choicesCb->property(warningLabelProperty));
604 if (option->conflicted) {
605 anyConflicted =
true;
606 const int pixmap_size = choicesCb->sizeHint().height() * .75;
607 warningLabel->setPixmap(warning.pixmap(pixmap_size, pixmap_size));
609 warningLabel->setPixmap(QPixmap());
613 return anyConflicted;
623
624
625
626
627
628
629
632 explicitDuplexMode(QPrint::DuplexAuto)
645 top =
new QUnixPrintWidget(q->printer(), q);
646 bottom =
new QWidget(q);
647 options.setupUi(bottom);
648 options.color->setIconSize(QSize(32, 32));
649 options.color->setIcon(QIcon(
":/qt-project.org/dialogs/qprintdialog/images/status-color.png"_L1));
650 options.grayscale->setIconSize(QSize(32, 32));
651 options.grayscale->setIcon(QIcon(
":/qt-project.org/dialogs/qprintdialog/images/status-gray-scale.png"_L1));
655 options.pageSetCombo->addItem(tr(
"All Pages"), QVariant::fromValue(QCUPSSupport::AllPages));
656 options.pageSetCombo->addItem(tr(
"Odd Pages"), QVariant::fromValue(QCUPSSupport::OddPages));
657 options.pageSetCombo->addItem(tr(
"Even Pages"), QVariant::fromValue(QCUPSSupport::EvenPages));
659 delete options.pagesRadioButton;
660 delete options.pagesLineEdit;
661 options.pagesRadioButton =
nullptr;
662 options.pagesLineEdit =
nullptr;
667 buttons =
new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, q);
668 collapseButton =
new QPushButton(QPrintDialog::tr(
"&Options >>"), buttons);
669 buttons->addButton(collapseButton, QDialogButtonBox::ResetRole);
670 bottom->setVisible(
false);
672 QPushButton *printButton = buttons->button(QDialogButtonBox::Ok);
673 printButton->setText(QPrintDialog::tr(
"&Print"));
674 printButton->setDefault(
true);
676 QVBoxLayout *lay =
new QVBoxLayout(q);
678 lay->addWidget(bottom);
679 lay->addWidget(buttons);
681#if !QT_CONFIG(messagebox)
682 QObject::connect(buttons, SIGNAL(accepted()), q, SLOT(accept()));
684 QObject::connect(buttons, SIGNAL(accepted()), q, SLOT(_q_checkFields()));
686 QObject::connect(buttons, SIGNAL(rejected()), q, SLOT(reject()));
688 QObject::connect(options.printSelection, SIGNAL(toggled(
bool)),
689 q, SLOT(_q_togglePageSetCombo(
bool)));
691 QObject::connect(options.printCurrentPage, SIGNAL(toggled(
bool)),
692 q, SLOT(_q_togglePageSetCombo(
bool)));
694 QObject::connect(collapseButton, SIGNAL(released()), q, SLOT(_q_collapseOrExpandDialog()));
696 QObject::connect(options.noDuplex, &QAbstractButton::clicked, q, [
this] { setExplicitDuplexMode(QPrint::DuplexNone); });
697 QObject::connect(options.duplexLong, &QAbstractButton::clicked, q, [
this] { setExplicitDuplexMode(QPrint::DuplexLongSide); });
698 QObject::connect(options.duplexShort, &QAbstractButton::clicked, q, [
this] { setExplicitDuplexMode(QPrint::DuplexShortSide); });
701 QObject::connect(options.noDuplex, &QAbstractButton::toggled, q, [
this] { updatePpdDuplexOption(options.noDuplex); });
702 QObject::connect(options.duplexLong, &QAbstractButton::toggled, q, [
this] { updatePpdDuplexOption(options.duplexLong); });
703 QObject::connect(options.duplexShort, &QAbstractButton::toggled, q, [
this] { updatePpdDuplexOption(options.duplexShort); });
711 QPrinter *p = q->printer();
712 printerOutputFormat = outputFormat;
715 const auto supportedDuplexMode =
top->d->m_currentPrintDevice.supportedDuplexModes();
716 options.duplexLong->setEnabled(supportedDuplexMode.contains(QPrint::DuplexLongSide));
717 options.duplexShort->setEnabled(supportedDuplexMode.contains(QPrint::DuplexShortSide));
719 if (p->colorMode() == QPrinter::Color)
720 options.color->setChecked(
true);
722 options.grayscale->setChecked(
true);
727 QPrint::DuplexMode duplex;
728 if (explicitDuplexMode != QPrint::DuplexAuto && supportedDuplexMode.contains(explicitDuplexMode))
729 duplex = explicitDuplexMode;
731 duplex =
static_cast<QPrint::DuplexMode>(p->duplex());
733 case QPrint::DuplexNone:
734 options.noDuplex->setChecked(
true);
break;
735 case QPrint::DuplexLongSide:
736 case QPrint::DuplexAuto:
737 options.duplexLong->setChecked(
true);
break;
738 case QPrint::DuplexShortSide:
739 options.duplexShort->setChecked(
true);
break;
741 options.copies->setValue(p->copyCount());
742 options.collate->setChecked(p->collateCopies());
743 options.reverse->setChecked(p->pageOrder() == QPrinter::LastPageFirst);
745 if (outputFormat == QPrinter::PdfFormat || options.printSelection->isChecked()
746 || options.printCurrentPage->isChecked())
748 options.pageSetCombo->setEnabled(
false);
750 options.pageSetCombo->setEnabled(
true);
756 options.pagesRadioButton->setEnabled(outputFormat != QPrinter::PdfFormat);
759 options.colorMode->setVisible(outputFormat == QPrinter::PdfFormat);
765void QPrintDialogPrivate::updatePpdDuplexOption(QRadioButton *radio)
767 const bool checked = radio->isChecked();
769 if (radio == options.noDuplex) top->d->setPpdDuplex(QPrinter::DuplexNone);
770 else if (radio == options.duplexLong) top->d->setPpdDuplex(QPrinter::DuplexLongSide);
771 else if (radio == options.duplexShort) top->d->setPpdDuplex(QPrinter::DuplexShortSide);
773 const bool conflict = checked && top->d->m_duplexPpdOption && top->d->m_duplexPpdOption->conflicted;
774 radio->setIcon(conflict ? QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning,
nullptr,
nullptr) : QIcon());
781 explicitDuplexMode = duplexMode;
791 QPrinter* p = q->printer();
793 if (options.duplex->isEnabled()) {
794 if (options.noDuplex->isChecked())
795 p->setDuplex(QPrinter::DuplexNone);
796 else if (options.duplexLong->isChecked())
797 p->setDuplex(QPrinter::DuplexLongSide);
799 p->setDuplex(QPrinter::DuplexShortSide);
804 if (p->outputFormat() == QPrinter::PdfFormat)
806 p->setColorMode(options.color->isChecked() ? QPrinter::Color : QPrinter::GrayScale);
808 p->setPageOrder(options.reverse->isChecked() ? QPrinter::LastPageFirst : QPrinter::FirstPageFirst);
811 if (options.printAll->isChecked()) {
812 p->setPrintRange(QPrinter::AllPages);
813 p->setPageRanges(QPageRanges());
814 }
else if (options.printSelection->isChecked()) {
815 p->setPrintRange(QPrinter::Selection);
816 p->setPageRanges(QPageRanges());
817 }
else if (options.printCurrentPage->isChecked()) {
818 p->setPrintRange(QPrinter::CurrentPage);
819 p->setPageRanges(QPageRanges());
820 }
else if (options.printRange->isChecked()) {
821 if (q->testOption(QPrintDialog::PrintPageRange)) {
822 p->setPrintRange(QPrinter::PageRange);
823 p->setFromTo(options.from->value(), qMax(options.from->value(), options.to->value()));
827 p->setPrintRange(QPrinter::AllPages);
828 p->setPageRanges(QPageRanges());
833 if (options.pagesRadioButton->isChecked()) {
834 const QPageRanges ranges = QPageRanges::fromString(options.pagesLineEdit->text());
835 p->setPrintRange(QPrinter::AllPages);
836 p->setPageRanges(QPageRanges());
839 QCUPSSupport::setPageRange(p, ranges.toString());
843 if (p->printRange() == QPrinter::AllPages || p->printRange() == QPrinter::PageRange) {
845 QCUPSSupport::PageSet pageSet = qvariant_cast<QCUPSSupport::PageSet>(options.pageSetCombo->itemData(options.pageSetCombo->currentIndex()));
846 if (q->testOption(QPrintDialog::PrintPageRange)
847 && p->printRange() == QPrinter::PageRange
848 && (q->fromPage() % 2 == 0)) {
851 case QCUPSSupport::AllPages:
853 case QCUPSSupport::OddPages:
854 QCUPSSupport::setPageSet(p, QCUPSSupport::EvenPages);
856 case QCUPSSupport::EvenPages:
857 QCUPSSupport::setPageSet(p, QCUPSSupport::OddPages);
860 }
else if (pageSet != QCUPSSupport::AllPages) {
861 QCUPSSupport::setPageSet(p, pageSet);
866 if (!q->testOption(QPrintDialog::PrintPageRange) && options.printRange->isChecked())
867 QCUPSSupport::setPageRange(p, options.from->value(), qMax(options.from->value(), options.to->value()));
872 p->setCopyCount(options.copies->value());
873 p->setCollateCopies(options.collate->isChecked());
878 if (printerOutputFormat == QPrinter::PdfFormat)
881 options.pageSetCombo->setDisabled(checked);
886 int collapseHeight = 0;
888 QWidget *widgetToHide = bottom;
889 if (widgetToHide->isVisible()) {
891 collapseHeight = widgetToHide->y() + widgetToHide->height() - (
top->y() +
top->height());
895 widgetToHide->setVisible(! widgetToHide->isVisible());
896 if (! widgetToHide->isVisible()) {
897 q->layout()->activate();
898 q->resize( QSize(q->width(), q->height() - collapseHeight) );
902#if QT_CONFIG(messagebox)
903void QPrintDialogPrivate::_q_checkFields()
906 if (top->d->checkFields())
915 options.gbPrintRange->setVisible(q->testOption(QPrintDialog::PrintPageRange) ||
916 q->testOption(QPrintDialog::PrintSelection) ||
917 q->testOption(QPrintDialog::PrintCurrentPage));
919 options.printRange->setEnabled(q->testOption(QPrintDialog::PrintPageRange));
920 options.printSelection->setVisible(q->testOption(QPrintDialog::PrintSelection));
921 options.printCurrentPage->setVisible(q->testOption(QPrintDialog::PrintCurrentPage));
922 options.collate->setVisible(q->testOption(QPrintDialog::PrintCollateCopies));
926 if (!q->testOption(QPrintDialog::PrintPageRange)
927 && (q->testOption(QPrintDialog::PrintSelection) || q->testOption(QPrintDialog::PrintCurrentPage))) {
928 options.pageSetCombo->setVisible(
false);
929 options.pageSetLabel->setVisible(
false);
931 options.pageSetCombo->setVisible(
true);
932 options.pageSetLabel->setVisible(
true);
935 if (!q->testOption(QPrintDialog::PrintPageRange)) {
938 options.gbPrintRange->setVisible(
true);
939 options.printRange->setEnabled(
true);
943 switch (q->printRange()) {
944 case QPrintDialog::AllPages:
945 options.printAll->setChecked(
true);
946 options.pageSetCombo->setEnabled(
true);
948 case QPrintDialog::Selection:
949 options.printSelection->setChecked(
true);
950 options.pageSetCombo->setEnabled(
false);
952 case QPrintDialog::PageRange:
953 options.printRange->setChecked(
true);
954 options.pageSetCombo->setEnabled(
true);
956 case QPrintDialog::CurrentPage:
957 if (q->testOption(QPrintDialog::PrintCurrentPage)) {
958 options.printCurrentPage->setChecked(
true);
959 options.pageSetCombo->setEnabled(
false);
965 const int minPage = qMax(1, qMin(q->minPage() , q->maxPage()));
966 const int maxPage = qMax(1, q->maxPage() == INT_MAX ? 9999 : q->maxPage());
968 options.from->setMinimum(minPage);
969 options.to->setMinimum(minPage);
970 options.from->setMaximum(maxPage);
971 options.to->setMaximum(maxPage);
973 options.from->setValue(q->fromPage());
974 options.to->setValue(q->toPage());
980 QList<QWidget*>::ConstIterator iter = tabWidgets.begin();
981 while(iter != tabWidgets.constEnd()) {
982 QWidget *tab = *iter;
983 options.tabs->addTab(tab, tab->windowTitle());
992
993
994
995
996
997
999QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent)
1000 : QAbstractPrintDialog(*(
new QPrintDialogPrivate), printer, parent)
1007
1008
1009QPrintDialog::QPrintDialog(QWidget *parent)
1010 : QAbstractPrintDialog(*(
new QPrintDialogPrivate),
nullptr, parent)
1016QPrintDialog::~QPrintDialog()
1020void QPrintDialog::setVisible(
bool visible)
1027 QAbstractPrintDialog::setVisible(visible);
1030int QPrintDialog::exec()
1032 return QAbstractPrintDialog::exec();
1035void QPrintDialog::accept()
1038#if QT_CONFIG(cups) && QT_CONFIG(messagebox)
1039 if (d->options.pagesRadioButton->isChecked()) {
1040 const QString rangesText = d->options.pagesLineEdit->text();
1041 if (rangesText.isEmpty() || QPageRanges::fromString(rangesText).isEmpty()) {
1042 QMessageBox::critical(
this, tr(
"Invalid Pages Definition"),
1043 tr(
"%1 does not follow the correct syntax. Please use ',' to separate "
1044 "ranges and pages, '-' to define ranges and make sure ranges do "
1045 "not intersect with each other.").arg(rangesText),
1046 QMessageBox::Ok, QMessageBox::Ok);
1050 if (d->top->d->m_duplexPpdOption && d->top->d->m_duplexPpdOption->conflicted) {
1051 const QMessageBox::StandardButton answer = QMessageBox::warning(
this, tr(
"Duplex Settings Conflicts"),
1052 tr(
"There are conflicts in duplex settings. Do you want to fix them?"),
1053 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
1054 if (answer != QMessageBox::No)
1066
1067
1068
1069
1070
1071
1073#if defined (Q_OS_UNIX)
1076
1077QUnixPrintWidgetPrivate::QUnixPrintWidgetPrivate(QUnixPrintWidget *p, QPrinter *prn)
1078 : parent(p), propertiesDialog(
nullptr), printer(prn),
1080 m_duplexPpdOption(
nullptr),
1082 optionsPane(
nullptr), filePrintersAdded(
false)
1086 q = qobject_cast<QPrintDialog*> (parent->parent());
1088 widget.setupUi(parent);
1090 int currentPrinterIndex = 0;
1091 QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
1093 const QStringList printers = ps->availablePrintDeviceIds();
1094 const QString defaultPrinter = ps->defaultPrintDeviceId();
1096 widget.printers->addItems(printers);
1098 const QString selectedPrinter = prn && !prn->printerName().isEmpty() ? prn->printerName() : defaultPrinter;
1099 const int idx = printers.indexOf(selectedPrinter);
1102 currentPrinterIndex = idx;
1104 widget.properties->setEnabled(
true);
1106#if QT_CONFIG(filesystemmodel) && QT_CONFIG(completer)
1107 QFileSystemModel *fsm =
new QFileSystemModel(widget.filename);
1108 fsm->setRootPath(QDir::homePath());
1109 widget.filename->setCompleter(
new QCompleter(fsm, widget.filename));
1111 _q_printerChanged(currentPrinterIndex);
1113 QObject::connect(widget.printers, SIGNAL(currentIndexChanged(
int)),
1114 parent, SLOT(_q_printerChanged(
int)));
1115 QObject::connect(widget.fileBrowser, SIGNAL(clicked()), parent, SLOT(_q_btnBrowseClicked()));
1116 QObject::connect(widget.properties, SIGNAL(clicked()), parent, SLOT(_q_btnPropertiesClicked()));
1119 widget.preview->setVisible(
false);
1122void QUnixPrintWidgetPrivate::updateWidget()
1124 const bool printToFile = q ==
nullptr || q->testOption(QPrintDialog::PrintToFile);
1125 if (printToFile && !filePrintersAdded) {
1126 if (widget.printers->count())
1127 widget.printers->insertSeparator(widget.printers->count());
1128 widget.printers->addItem(QPrintDialog::tr(
"Print to File (PDF)"));
1129 filePrintersAdded =
true;
1130 if (widget.printers->count() == 1)
1131 _q_printerChanged(0);
1133 if (!printToFile && filePrintersAdded) {
1134 widget.printers->removeItem(widget.printers->count()-1);
1135 widget.printers->removeItem(widget.printers->count()-1);
1136 if (widget.printers->count())
1137 widget.printers->removeItem(widget.printers->count()-1);
1138 filePrintersAdded =
false;
1140 if (printer && filePrintersAdded && (printer->outputFormat() != QPrinter::NativeFormat
1141 || printer->printerName().isEmpty()))
1143 if (printer->outputFormat() == QPrinter::PdfFormat)
1144 widget.printers->setCurrentIndex(widget.printers->count() - 1);
1145 widget.filename->setEnabled(
true);
1146 widget.lOutput->setEnabled(
true);
1149 widget.filename->setVisible(printToFile);
1150 widget.lOutput->setVisible(printToFile);
1151 widget.fileBrowser->setVisible(printToFile);
1154 widget.properties->setVisible(q->testOption(QAbstractPrintDialog::PrintShowPageSize));
1157QUnixPrintWidgetPrivate::~QUnixPrintWidgetPrivate()
1161void QUnixPrintWidgetPrivate::_q_printerChanged(
int index)
1165 const int printerCount = widget.printers->count();
1166 widget.filename->setEnabled(
false);
1167 widget.lOutput->setEnabled(
false);
1170 if (propertiesDialog){
1171 delete propertiesDialog;
1172 propertiesDialog =
nullptr;
1176 m_duplexPpdOption =
nullptr;
1179 if (filePrintersAdded) {
1180 Q_ASSERT(index != printerCount - 2);
1181 if (index == printerCount - 1) {
1182 widget.location->setText(QPrintDialog::tr(
"Local file"));
1183 widget.type->setText(QPrintDialog::tr(
"Write PDF file"));
1184 widget.properties->setEnabled(
true);
1185 widget.filename->setEnabled(
true);
1186 QString filename = widget.filename->text();
1187 widget.filename->setText(filename);
1188 widget.lOutput->setEnabled(
true);
1189 printer->setOutputFormat(QPrinter::PdfFormat);
1190 m_currentPrintDevice = QPrintDevice();
1192 optionsPane->selectPrinter(QPrinter::PdfFormat);
1198 printer->setOutputFormat(QPrinter::NativeFormat);
1200 QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
1202 m_currentPrintDevice = ps->createPrintDevice(widget.printers->itemText(index));
1204 m_currentPrintDevice = QPrintDevice();
1206 printer->setPrinterName(m_currentPrintDevice.id());
1208 widget.location->setText(m_currentPrintDevice.location());
1209 widget.type->setText(m_currentPrintDevice.makeAndModel());
1211 optionsPane->selectPrinter(QPrinter::NativeFormat);
1215 m_duplexPpdOption = QCUPSSupport::findPpdOption(
"Duplex", &m_currentPrintDevice);
1219void QUnixPrintWidgetPrivate::setOptionsPane(QPrintDialogPrivate *pane)
1223 optionsPane->selectPrinter(QPrinter::NativeFormat);
1226void QUnixPrintWidgetPrivate::_q_btnBrowseClicked()
1228 QString filename = widget.filename->text();
1229#if QT_CONFIG(filedialog)
1230 filename = QFileDialog::getSaveFileName(parent, QPrintDialog::tr(
"Print To File ..."), filename,
1231 QString(),
nullptr, QFileDialog::DontConfirmOverwrite);
1235 if (!filename.isEmpty()) {
1236 widget.filename->setText(filename);
1237 widget.printers->setCurrentIndex(widget.printers->count() - 1);
1241#if QT_CONFIG(messagebox)
1242bool QUnixPrintWidgetPrivate::checkFields()
1244 if (widget.filename->isEnabled()) {
1245 QString file = widget.filename->text();
1248 bool exists = fi.exists();
1249 bool opened =
false;
1250 if (exists && fi.isDir()) {
1251 QMessageBox::warning(q, q->windowTitle(),
1252 QPrintDialog::tr(
"%1 is a directory.\nPlease choose a different file name.").arg(file));
1254 }
else if ((exists && !fi.isWritable()) || !(opened = f.open(QFile::Append))) {
1255 QMessageBox::warning(q, q->windowTitle(),
1256 QPrintDialog::tr(
"File %1 is not writable.\nPlease choose a different file name.").arg(file));
1258 }
else if (exists) {
1259 int ret = QMessageBox::question(q, q->windowTitle(),
1260 QPrintDialog::tr(
"%1 already exists.\nDo you want to overwrite it?").arg(file),
1261 QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
1262 if (ret == QMessageBox::No)
1273 if (propertiesDialog) {
1274 QCUPSSupport::PagesPerSheet pagesPerSheet = qvariant_cast<QCUPSSupport::PagesPerSheet>(propertiesDialog->widget.pageSetup->m_ui.pagesPerSheetCombo
1277 QCUPSSupport::PageSet pageSet = qvariant_cast<QCUPSSupport::PageSet>(optionsPane->options.pageSetCombo->currentData());
1280 if (pagesPerSheet != QCUPSSupport::OnePagePerSheet
1281 && pageSet != QCUPSSupport::AllPages) {
1282 QMessageBox::warning(q, q->windowTitle(),
1283 QPrintDialog::tr(
"Options 'Pages Per Sheet' and 'Page Set' cannot be used together.\nPlease turn one of those options off."));
1294void QUnixPrintWidgetPrivate::setupPrinterProperties()
1296 delete propertiesDialog;
1298 QPrinter::OutputFormat outputFormat;
1299 QString printerName;
1301 if (q->testOption(QPrintDialog::PrintToFile)
1302 && (widget.printers->currentIndex() == widget.printers->count() - 1)) {
1303 outputFormat = QPrinter::PdfFormat;
1305 outputFormat = QPrinter::NativeFormat;
1306 printerName = widget.printers->currentText();
1309 propertiesDialog =
new QPrintPropertiesDialog(q->printer(), &m_currentPrintDevice, outputFormat, printerName, q);
1313void QUnixPrintWidgetPrivate::setPpdDuplex(QPrinter::DuplexMode mode)
1315 auto values = QStringList{} << QStringLiteral(
"Duplex");
1316 if (mode == QPrinter::DuplexNone) values << QStringLiteral(
"None");
1317 else if (mode == QPrinter::DuplexLongSide) values << QStringLiteral(
"DuplexNoTumble");
1318 else if (mode == QPrinter::DuplexShortSide) values << QStringLiteral(
"DuplexTumble");
1320 m_currentPrintDevice.setProperty(PDPK_PpdOption, values);
1324void QUnixPrintWidgetPrivate::_q_btnPropertiesClicked()
1326 if (!propertiesDialog)
1327 setupPrinterProperties();
1328 propertiesDialog->exec();
1332 optionsPane->updatePpdDuplexOption(optionsPane->options.noDuplex);
1333 optionsPane->updatePpdDuplexOption(optionsPane->options.duplexLong);
1334 optionsPane->updatePpdDuplexOption(optionsPane->options.duplexShort);
1338void QUnixPrintWidgetPrivate::setupPrinter()
1340 const int printerCount = widget.printers->count();
1341 const int index = widget.printers->currentIndex();
1343 if (filePrintersAdded && index == printerCount - 1) {
1344 printer->setPrinterName(QString());
1345 Q_ASSERT(index != printerCount - 2);
1346 printer->setOutputFormat(QPrinter::PdfFormat);
1347 QString path = widget.filename->text();
1348 if (QDir::isRelativePath(path))
1349 path = QDir::homePath() + QDir::separator() + path;
1350 printer->setOutputFileName(path);
1353 printer->setPrinterName(widget.printers->currentText());
1354 printer->setOutputFileName(QString());
1357 if (!propertiesDialog)
1358 setupPrinterProperties();
1360 propertiesDialog->setupPrinter();
1364
1365QUnixPrintWidget::QUnixPrintWidget(QPrinter *printer, QWidget *parent)
1366 : QWidget(parent), d(
new QUnixPrintWidgetPrivate(
this, printer))
1368 if (printer ==
nullptr)
1370 if (printer->outputFileName().isEmpty()) {
1371 QString home = QDir::homePath();
1372 QString cur = QDir::currentPath();
1373 if (!home.endsWith(u'/'))
1375 if (!cur.startsWith(home))
1377 else if (!cur.endsWith(u'/'))
1379 if (QGuiApplication::platformName() ==
"xcb"_L1) {
1380 if (printer->docName().isEmpty()) {
1381 cur +=
"print.pdf"_L1;
1383#if QT_CONFIG(regularexpression)
1384 const QRegularExpression re(QStringLiteral(
"(.*)\\.\\S+"));
1385 auto match = re.match(printer->docName());
1386 if (match.hasMatch())
1387 cur += match.captured(1);
1390 cur += printer->docName();
1395 d->widget.filename->setText(cur);
1398 d->widget.filename->setText(printer->outputFileName());
1399 const QString printerName = printer->printerName();
1400 if (!printerName.isEmpty()) {
1401 const int i = d->widget.printers->findText(printerName);
1403 d->widget.printers->setCurrentIndex(i);
1409
1410QUnixPrintWidget::~QUnixPrintWidget()
1416
1417
1418
1419void QUnixPrintWidget::updatePrinter()
1434#include "moc_qprintdialog.cpp"
1435#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()