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 *warningLabelProperty =
"_q_warning_label";
373static bool isBlacklistedGroup(
const ppd_group_t *group)
noexcept
375 return qstrcmp(group->name,
"InstallableOptions") == 0;
378static bool isBlacklistedOption(
const char *keyword)
noexcept
381 const char *cupsOptionBlacklist[] = {
389 auto equals = [](
const char *keyword) {
390 return [keyword](
const char *candidate) {
391 return qstrcmp(keyword, candidate) == 0;
394 return std::any_of(std::begin(cupsOptionBlacklist), std::end(cupsOptionBlacklist), equals(keyword));
397bool QPrintPropertiesDialog::createAdvancedOptionsWidget()
399 bool anyWidgetCreated =
false;
401 ppd_file_t *ppd = qvariant_cast<ppd_file_t*>(m_currentPrintDevice->property(PDPK_PpdFile));
404 toUnicode = QStringDecoder(ppd->lang_encoding, QStringDecoder::Flag::Stateless);
405 if (!toUnicode.isValid()) {
406 qWarning() <<
"QPrinSupport: Cups uses unsupported encoding" << ppd->lang_encoding;
407 toUnicode = QStringDecoder(QStringDecoder::Utf8, QStringDecoder::Flag::Stateless);
410 QWidget *holdingWidget =
new QWidget();
411 QVBoxLayout *layout =
new QVBoxLayout(holdingWidget);
413 for (
int i = 0; i < ppd->num_groups; ++i) {
414 const ppd_group_t *group = &ppd->groups[i];
416 if (!isBlacklistedGroup(group)) {
417 QFormLayout *groupLayout =
new QFormLayout();
419 for (
int i = 0; i < group->num_options; ++i) {
420 const ppd_option_t *option = &group->options[i];
422 if (!isBlacklistedOption(option->keyword)) {
423 QComboBox *choicesCb =
new QComboBox();
425 const auto setPpdOptionFromCombo = [
this, choicesCb, option] {
429 const int selectedChoiceIndex = choicesCb->currentData().toInt();
430 const auto values = QStringList{} << QString::fromLatin1(option->keyword)
431 << QString::fromLatin1(option->choices[selectedChoiceIndex].choice);
432 m_currentPrintDevice->setProperty(PDPK_PpdOption, values);
433 widget.conflictsLabel->setVisible(anyPpdOptionConflict());
436 bool foundMarkedChoice =
false;
437 bool markedChoiceNotAvailable =
false;
438 for (
int i = 0; i < option->num_choices; ++i) {
439 const ppd_choice_t *choice = &option->choices[i];
440 const auto values = QStringList{} << QString::fromLatin1(option->keyword) << QString::fromLatin1(choice->choice);
441 const bool choiceIsInstallableConflict = m_currentPrintDevice->isFeatureAvailable(PDPK_PpdChoiceIsInstallableConflict, values);
442 if (choiceIsInstallableConflict &&
static_cast<
int>(choice->marked) == 1) {
443 markedChoiceNotAvailable =
true;
444 }
else if (!choiceIsInstallableConflict) {
445 choicesCb->addItem(toUnicode(choice->text), i);
446 if (
static_cast<
int>(choice->marked) == 1) {
447 choicesCb->setCurrentIndex(choicesCb->count() - 1);
448 choicesCb->setProperty(ppdOriginallySelectedChoiceProperty, QVariant(i));
449 foundMarkedChoice =
true;
450 }
else if (!foundMarkedChoice && qstrcmp(choice->choice, option->defchoice) == 0) {
451 choicesCb->setCurrentIndex(choicesCb->count() - 1);
452 choicesCb->setProperty(ppdOriginallySelectedChoiceProperty, QVariant(i));
457 if (markedChoiceNotAvailable) {
461 setPpdOptionFromCombo();
464 if (choicesCb->count() > 1) {
466 connect(choicesCb, &QComboBox::currentIndexChanged,
this, setPpdOptionFromCombo);
469 QWidget *choicesCbWithLabel =
new QWidget();
470 QHBoxLayout *choicesCbWithLabelLayout =
new QHBoxLayout(choicesCbWithLabel);
471 choicesCbWithLabelLayout->setContentsMargins(0, 0, 0, 0);
472 QLabel *warningLabel =
new QLabel();
473 choicesCbWithLabelLayout->addWidget(choicesCb);
474 choicesCbWithLabelLayout->addWidget(warningLabel);
476 QLabel *optionLabel =
new QLabel(toUnicode(option->text));
477 optionLabel->setBuddy(choicesCb);
478 groupLayout->addRow(optionLabel, choicesCbWithLabel);
479 anyWidgetCreated =
true;
480 choicesCb->setProperty(ppdOptionProperty, QVariant::fromValue(option));
481 choicesCb->setProperty(warningLabelProperty, QVariant::fromValue(warningLabel));
482 m_advancedOptionsCombos << choicesCb;
489 if (groupLayout->rowCount() > 0) {
490 QGroupBox *groupBox =
new QGroupBox(toUnicode(group->text));
491 groupBox->setLayout(groupLayout);
492 layout->addWidget(groupBox);
499 layout->addStretch();
500 widget.scrollArea->setWidget(holdingWidget);
503 return anyWidgetCreated;
506void QPrintPropertiesDialog::setPrinterAdvancedCupsOptions()
const
508 for (
const QComboBox *choicesCb : m_advancedOptionsCombos) {
509 const ppd_option_t *option = qvariant_cast<
const ppd_option_t *>(choicesCb->property(ppdOptionProperty));
514 const int selectedChoiceIndex = choicesCb->currentData().toInt();
515 const char *selectedChoice = option->choices[selectedChoiceIndex].choice;
517 if (qstrcmp(option->keyword,
"ColorModel") == 0)
518 m_printer->setColorMode(qstrcmp(selectedChoice,
"Gray") == 0 ? QPrinter::GrayScale : QPrinter::Color);
520 if (qstrcmp(option->defchoice, selectedChoice) != 0)
521 QCUPSSupport::setCupsOption(m_printer, QString::fromLatin1(option->keyword), QString::fromLatin1(selectedChoice));
525void QPrintPropertiesDialog::revertAdvancedOptionsToSavedValues()
const
527 for (QComboBox *choicesCb : m_advancedOptionsCombos) {
528 const int originallySelectedChoice = qvariant_cast<
int>(choicesCb->property(ppdOriginallySelectedChoiceProperty));
529 const int newComboIndexToSelect = choicesCb->findData(originallySelectedChoice);
530 choicesCb->setCurrentIndex(newComboIndexToSelect);
533 widget.conflictsLabel->setVisible(anyPpdOptionConflict());
536void QPrintPropertiesDialog::advancedOptionsUpdateSavedValues()
const
538 for (QComboBox *choicesCb : m_advancedOptionsCombos)
539 choicesCb->setProperty(ppdOriginallySelectedChoiceProperty, choicesCb->currentData());
542bool QPrintPropertiesDialog::anyPpdOptionConflict()
const
545 const bool pageSetupConflicts = widget.pageSetup->hasPpdConflict();
546 const bool advancedOptionConflicts = anyAdvancedOptionConflict();
547 return pageSetupConflicts || advancedOptionConflicts;
550bool QPrintPropertiesDialog::anyAdvancedOptionConflict()
const
552 const QIcon warning = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning,
nullptr,
nullptr);
554 bool anyConflicted =
false;
556 for (
const QComboBox *choicesCb : m_advancedOptionsCombos) {
557 const ppd_option_t *option = qvariant_cast<
const ppd_option_t *>(choicesCb->property(ppdOptionProperty));
558 QLabel *warningLabel = qvariant_cast<QLabel *>(choicesCb->property(warningLabelProperty));
559 if (option->conflicted) {
560 anyConflicted =
true;
561 const int pixmap_size = choicesCb->sizeHint().height() * .75;
562 warningLabel->setPixmap(warning.pixmap(pixmap_size, pixmap_size));
564 warningLabel->setPixmap(QPixmap());
568 return anyConflicted;
578
579
580
581
582
583
584
587 explicitDuplexMode(QPrint::DuplexAuto)
600 top =
new QUnixPrintWidget(q->printer(), q);
601 bottom =
new QWidget(q);
602 options.setupUi(bottom);
603 options.color->setIconSize(QSize(32, 32));
604 options.color->setIcon(QIcon(
":/qt-project.org/dialogs/qprintdialog/images/status-color.png"_L1));
605 options.grayscale->setIconSize(QSize(32, 32));
606 options.grayscale->setIcon(QIcon(
":/qt-project.org/dialogs/qprintdialog/images/status-gray-scale.png"_L1));
610 options.pageSetCombo->addItem(tr(
"All Pages"), QVariant::fromValue(QCUPSSupport::AllPages));
611 options.pageSetCombo->addItem(tr(
"Odd Pages"), QVariant::fromValue(QCUPSSupport::OddPages));
612 options.pageSetCombo->addItem(tr(
"Even Pages"), QVariant::fromValue(QCUPSSupport::EvenPages));
614 delete options.pagesRadioButton;
615 delete options.pagesLineEdit;
616 options.pagesRadioButton =
nullptr;
617 options.pagesLineEdit =
nullptr;
622 buttons =
new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, q);
623 collapseButton =
new QPushButton(QPrintDialog::tr(
"&Options >>"), buttons);
624 buttons->addButton(collapseButton, QDialogButtonBox::ResetRole);
625 bottom->setVisible(
false);
627 QPushButton *printButton = buttons->button(QDialogButtonBox::Ok);
628 printButton->setText(QPrintDialog::tr(
"&Print"));
629 printButton->setDefault(
true);
631 QVBoxLayout *lay =
new QVBoxLayout(q);
633 lay->addWidget(bottom);
634 lay->addWidget(buttons);
636#if !QT_CONFIG(messagebox)
637 QObject::connect(buttons, SIGNAL(accepted()), q, SLOT(accept()));
639 QObject::connect(buttons, SIGNAL(accepted()), q, SLOT(_q_checkFields()));
641 QObject::connect(buttons, SIGNAL(rejected()), q, SLOT(reject()));
643 QObject::connect(options.printSelection, SIGNAL(toggled(
bool)),
644 q, SLOT(_q_togglePageSetCombo(
bool)));
646 QObject::connect(options.printCurrentPage, SIGNAL(toggled(
bool)),
647 q, SLOT(_q_togglePageSetCombo(
bool)));
649 QObject::connect(collapseButton, SIGNAL(released()), q, SLOT(_q_collapseOrExpandDialog()));
651 QObject::connect(options.noDuplex, &QAbstractButton::clicked, q, [
this] { setExplicitDuplexMode(QPrint::DuplexNone); });
652 QObject::connect(options.duplexLong, &QAbstractButton::clicked, q, [
this] { setExplicitDuplexMode(QPrint::DuplexLongSide); });
653 QObject::connect(options.duplexShort, &QAbstractButton::clicked, q, [
this] { setExplicitDuplexMode(QPrint::DuplexShortSide); });
656 QObject::connect(options.noDuplex, &QAbstractButton::toggled, q, [
this] { updatePpdDuplexOption(options.noDuplex); });
657 QObject::connect(options.duplexLong, &QAbstractButton::toggled, q, [
this] { updatePpdDuplexOption(options.duplexLong); });
658 QObject::connect(options.duplexShort, &QAbstractButton::toggled, q, [
this] { updatePpdDuplexOption(options.duplexShort); });
666 QPrinter *p = q->printer();
667 printerOutputFormat = outputFormat;
670 const auto supportedDuplexMode =
top->d->m_currentPrintDevice.supportedDuplexModes();
671 options.duplexLong->setEnabled(supportedDuplexMode.contains(QPrint::DuplexLongSide));
672 options.duplexShort->setEnabled(supportedDuplexMode.contains(QPrint::DuplexShortSide));
674 if (p->colorMode() == QPrinter::Color)
675 options.color->setChecked(
true);
677 options.grayscale->setChecked(
true);
682 QPrint::DuplexMode duplex;
683 if (explicitDuplexMode != QPrint::DuplexAuto && supportedDuplexMode.contains(explicitDuplexMode))
684 duplex = explicitDuplexMode;
686 duplex =
static_cast<QPrint::DuplexMode>(p->duplex());
688 case QPrint::DuplexNone:
689 options.noDuplex->setChecked(
true);
break;
690 case QPrint::DuplexLongSide:
691 case QPrint::DuplexAuto:
692 options.duplexLong->setChecked(
true);
break;
693 case QPrint::DuplexShortSide:
694 options.duplexShort->setChecked(
true);
break;
696 options.copies->setValue(p->copyCount());
697 options.collate->setChecked(p->collateCopies());
698 options.reverse->setChecked(p->pageOrder() == QPrinter::LastPageFirst);
700 if (outputFormat == QPrinter::PdfFormat || options.printSelection->isChecked()
701 || options.printCurrentPage->isChecked())
703 options.pageSetCombo->setEnabled(
false);
705 options.pageSetCombo->setEnabled(
true);
711 options.pagesRadioButton->setEnabled(outputFormat != QPrinter::PdfFormat);
714 options.colorMode->setVisible(outputFormat == QPrinter::PdfFormat);
720void QPrintDialogPrivate::updatePpdDuplexOption(QRadioButton *radio)
722 const bool checked = radio->isChecked();
724 if (radio == options.noDuplex) top->d->setPpdDuplex(QPrinter::DuplexNone);
725 else if (radio == options.duplexLong) top->d->setPpdDuplex(QPrinter::DuplexLongSide);
726 else if (radio == options.duplexShort) top->d->setPpdDuplex(QPrinter::DuplexShortSide);
728 const bool conflict = checked && top->d->m_duplexPpdOption && top->d->m_duplexPpdOption->conflicted;
729 radio->setIcon(conflict ? QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning,
nullptr,
nullptr) : QIcon());
736 explicitDuplexMode = duplexMode;
746 QPrinter* p = q->printer();
748 if (options.duplex->isEnabled()) {
749 if (options.noDuplex->isChecked())
750 p->setDuplex(QPrinter::DuplexNone);
751 else if (options.duplexLong->isChecked())
752 p->setDuplex(QPrinter::DuplexLongSide);
754 p->setDuplex(QPrinter::DuplexShortSide);
759 if (p->outputFormat() == QPrinter::PdfFormat)
761 p->setColorMode(options.color->isChecked() ? QPrinter::Color : QPrinter::GrayScale);
763 p->setPageOrder(options.reverse->isChecked() ? QPrinter::LastPageFirst : QPrinter::FirstPageFirst);
766 if (options.printAll->isChecked()) {
767 p->setPrintRange(QPrinter::AllPages);
768 p->setPageRanges(QPageRanges());
769 }
else if (options.printSelection->isChecked()) {
770 p->setPrintRange(QPrinter::Selection);
771 p->setPageRanges(QPageRanges());
772 }
else if (options.printCurrentPage->isChecked()) {
773 p->setPrintRange(QPrinter::CurrentPage);
774 p->setPageRanges(QPageRanges());
775 }
else if (options.printRange->isChecked()) {
776 if (q->testOption(QPrintDialog::PrintPageRange)) {
777 p->setPrintRange(QPrinter::PageRange);
778 p->setFromTo(options.from->value(), qMax(options.from->value(), options.to->value()));
782 p->setPrintRange(QPrinter::AllPages);
783 p->setPageRanges(QPageRanges());
788 if (options.pagesRadioButton->isChecked()) {
789 const QPageRanges ranges = QPageRanges::fromString(options.pagesLineEdit->text());
790 p->setPrintRange(QPrinter::AllPages);
791 p->setPageRanges(QPageRanges());
794 QCUPSSupport::setPageRange(p, ranges.toString());
798 if (p->printRange() == QPrinter::AllPages || p->printRange() == QPrinter::PageRange) {
800 QCUPSSupport::PageSet pageSet = qvariant_cast<QCUPSSupport::PageSet>(options.pageSetCombo->itemData(options.pageSetCombo->currentIndex()));
801 if (q->testOption(QPrintDialog::PrintPageRange)
802 && p->printRange() == QPrinter::PageRange
803 && (q->fromPage() % 2 == 0)) {
806 case QCUPSSupport::AllPages:
808 case QCUPSSupport::OddPages:
809 QCUPSSupport::setPageSet(p, QCUPSSupport::EvenPages);
811 case QCUPSSupport::EvenPages:
812 QCUPSSupport::setPageSet(p, QCUPSSupport::OddPages);
815 }
else if (pageSet != QCUPSSupport::AllPages) {
816 QCUPSSupport::setPageSet(p, pageSet);
821 if (!q->testOption(QPrintDialog::PrintPageRange) && options.printRange->isChecked())
822 QCUPSSupport::setPageRange(p, options.from->value(), qMax(options.from->value(), options.to->value()));
827 p->setCopyCount(options.copies->value());
828 p->setCollateCopies(options.collate->isChecked());
833 if (printerOutputFormat == QPrinter::PdfFormat)
836 options.pageSetCombo->setDisabled(checked);
841 int collapseHeight = 0;
843 QWidget *widgetToHide = bottom;
844 if (widgetToHide->isVisible()) {
846 collapseHeight = widgetToHide->y() + widgetToHide->height() - (
top->y() +
top->height());
850 widgetToHide->setVisible(! widgetToHide->isVisible());
851 if (! widgetToHide->isVisible()) {
852 q->layout()->activate();
853 q->resize( QSize(q->width(), q->height() - collapseHeight) );
857#if QT_CONFIG(messagebox)
858void QPrintDialogPrivate::_q_checkFields()
861 if (top->d->checkFields())
870 options.gbPrintRange->setVisible(q->testOption(QPrintDialog::PrintPageRange) ||
871 q->testOption(QPrintDialog::PrintSelection) ||
872 q->testOption(QPrintDialog::PrintCurrentPage));
874 options.printRange->setEnabled(q->testOption(QPrintDialog::PrintPageRange));
875 options.printSelection->setVisible(q->testOption(QPrintDialog::PrintSelection));
876 options.printCurrentPage->setVisible(q->testOption(QPrintDialog::PrintCurrentPage));
877 options.collate->setVisible(q->testOption(QPrintDialog::PrintCollateCopies));
881 if (!q->testOption(QPrintDialog::PrintPageRange)
882 && (q->testOption(QPrintDialog::PrintSelection) || q->testOption(QPrintDialog::PrintCurrentPage))) {
883 options.pageSetCombo->setVisible(
false);
884 options.pageSetLabel->setVisible(
false);
886 options.pageSetCombo->setVisible(
true);
887 options.pageSetLabel->setVisible(
true);
890 if (!q->testOption(QPrintDialog::PrintPageRange)) {
893 options.gbPrintRange->setVisible(
true);
894 options.printRange->setEnabled(
true);
898 switch (q->printRange()) {
899 case QPrintDialog::AllPages:
900 options.printAll->setChecked(
true);
901 options.pageSetCombo->setEnabled(
true);
903 case QPrintDialog::Selection:
904 options.printSelection->setChecked(
true);
905 options.pageSetCombo->setEnabled(
false);
907 case QPrintDialog::PageRange:
908 options.printRange->setChecked(
true);
909 options.pageSetCombo->setEnabled(
true);
911 case QPrintDialog::CurrentPage:
912 if (q->testOption(QPrintDialog::PrintCurrentPage)) {
913 options.printCurrentPage->setChecked(
true);
914 options.pageSetCombo->setEnabled(
false);
920 const int minPage = qMax(1, qMin(q->minPage() , q->maxPage()));
921 const int maxPage = qMax(1, q->maxPage() == INT_MAX ? 9999 : q->maxPage());
923 options.from->setMinimum(minPage);
924 options.to->setMinimum(minPage);
925 options.from->setMaximum(maxPage);
926 options.to->setMaximum(maxPage);
928 options.from->setValue(q->fromPage());
929 options.to->setValue(q->toPage());
935 QList<QWidget*>::ConstIterator iter = tabWidgets.begin();
936 while(iter != tabWidgets.constEnd()) {
937 QWidget *tab = *iter;
938 options.tabs->addTab(tab, tab->windowTitle());
947
948
949
950
951
952
954QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent)
955 : QAbstractPrintDialog(*(
new QPrintDialogPrivate), printer, parent)
962
963
964QPrintDialog::QPrintDialog(QWidget *parent)
965 : QAbstractPrintDialog(*(
new QPrintDialogPrivate),
nullptr, parent)
971QPrintDialog::~QPrintDialog()
975void QPrintDialog::setVisible(
bool visible)
982 QAbstractPrintDialog::setVisible(visible);
985int QPrintDialog::exec()
987 return QAbstractPrintDialog::exec();
990void QPrintDialog::accept()
993#if QT_CONFIG(cups) && QT_CONFIG(messagebox)
994 if (d->options.pagesRadioButton->isChecked()) {
995 const QString rangesText = d->options.pagesLineEdit->text();
996 if (rangesText.isEmpty() || QPageRanges::fromString(rangesText).isEmpty()) {
997 QMessageBox::critical(
this, tr(
"Invalid Pages Definition"),
998 tr(
"%1 does not follow the correct syntax. Please use ',' to separate "
999 "ranges and pages, '-' to define ranges and make sure ranges do "
1000 "not intersect with each other.").arg(rangesText),
1001 QMessageBox::Ok, QMessageBox::Ok);
1005 if (d->top->d->m_duplexPpdOption && d->top->d->m_duplexPpdOption->conflicted) {
1006 const QMessageBox::StandardButton answer = QMessageBox::warning(
this, tr(
"Duplex Settings Conflicts"),
1007 tr(
"There are conflicts in duplex settings. Do you want to fix them?"),
1008 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
1009 if (answer != QMessageBox::No)
1021
1022
1023
1024
1025
1026
1028#if defined (Q_OS_UNIX)
1031
1032QUnixPrintWidgetPrivate::QUnixPrintWidgetPrivate(QUnixPrintWidget *p, QPrinter *prn)
1033 : parent(p), propertiesDialog(
nullptr), printer(prn),
1035 m_duplexPpdOption(
nullptr),
1037 optionsPane(
nullptr), filePrintersAdded(
false)
1041 q = qobject_cast<QPrintDialog*> (parent->parent());
1043 widget.setupUi(parent);
1045 int currentPrinterIndex = 0;
1046 QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
1048 const QStringList printers = ps->availablePrintDeviceIds();
1049 const QString defaultPrinter = ps->defaultPrintDeviceId();
1051 widget.printers->addItems(printers);
1053 const QString selectedPrinter = prn && !prn->printerName().isEmpty() ? prn->printerName() : defaultPrinter;
1054 const int idx = printers.indexOf(selectedPrinter);
1057 currentPrinterIndex = idx;
1059 widget.properties->setEnabled(
true);
1061#if QT_CONFIG(filesystemmodel) && QT_CONFIG(completer)
1062 QFileSystemModel *fsm =
new QFileSystemModel(widget.filename);
1063 fsm->setRootPath(QDir::homePath());
1064 widget.filename->setCompleter(
new QCompleter(fsm, widget.filename));
1066 _q_printerChanged(currentPrinterIndex);
1068 QObject::connect(widget.printers, SIGNAL(currentIndexChanged(
int)),
1069 parent, SLOT(_q_printerChanged(
int)));
1070 QObject::connect(widget.fileBrowser, SIGNAL(clicked()), parent, SLOT(_q_btnBrowseClicked()));
1071 QObject::connect(widget.properties, SIGNAL(clicked()), parent, SLOT(_q_btnPropertiesClicked()));
1074 widget.preview->setVisible(
false);
1077void QUnixPrintWidgetPrivate::updateWidget()
1079 const bool printToFile = q ==
nullptr || q->testOption(QPrintDialog::PrintToFile);
1080 if (printToFile && !filePrintersAdded) {
1081 if (widget.printers->count())
1082 widget.printers->insertSeparator(widget.printers->count());
1083 widget.printers->addItem(QPrintDialog::tr(
"Print to File (PDF)"));
1084 filePrintersAdded =
true;
1085 if (widget.printers->count() == 1)
1086 _q_printerChanged(0);
1088 if (!printToFile && filePrintersAdded) {
1089 widget.printers->removeItem(widget.printers->count()-1);
1090 widget.printers->removeItem(widget.printers->count()-1);
1091 if (widget.printers->count())
1092 widget.printers->removeItem(widget.printers->count()-1);
1093 filePrintersAdded =
false;
1095 if (printer && filePrintersAdded && (printer->outputFormat() != QPrinter::NativeFormat
1096 || printer->printerName().isEmpty()))
1098 if (printer->outputFormat() == QPrinter::PdfFormat)
1099 widget.printers->setCurrentIndex(widget.printers->count() - 1);
1100 widget.filename->setEnabled(
true);
1101 widget.lOutput->setEnabled(
true);
1104 widget.filename->setVisible(printToFile);
1105 widget.lOutput->setVisible(printToFile);
1106 widget.fileBrowser->setVisible(printToFile);
1109 widget.properties->setVisible(q->testOption(QAbstractPrintDialog::PrintShowPageSize));
1112QUnixPrintWidgetPrivate::~QUnixPrintWidgetPrivate()
1116void QUnixPrintWidgetPrivate::_q_printerChanged(
int index)
1120 const int printerCount = widget.printers->count();
1121 widget.filename->setEnabled(
false);
1122 widget.lOutput->setEnabled(
false);
1125 if (propertiesDialog){
1126 delete propertiesDialog;
1127 propertiesDialog =
nullptr;
1131 m_duplexPpdOption =
nullptr;
1134 if (filePrintersAdded) {
1135 Q_ASSERT(index != printerCount - 2);
1136 if (index == printerCount - 1) {
1137 widget.location->setText(QPrintDialog::tr(
"Local file"));
1138 widget.type->setText(QPrintDialog::tr(
"Write PDF file"));
1139 widget.properties->setEnabled(
true);
1140 widget.filename->setEnabled(
true);
1141 QString filename = widget.filename->text();
1142 widget.filename->setText(filename);
1143 widget.lOutput->setEnabled(
true);
1144 printer->setOutputFormat(QPrinter::PdfFormat);
1145 m_currentPrintDevice = QPrintDevice();
1147 optionsPane->selectPrinter(QPrinter::PdfFormat);
1153 printer->setOutputFormat(QPrinter::NativeFormat);
1155 QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
1157 m_currentPrintDevice = ps->createPrintDevice(widget.printers->itemText(index));
1159 m_currentPrintDevice = QPrintDevice();
1161 printer->setPrinterName(m_currentPrintDevice.id());
1163 widget.location->setText(m_currentPrintDevice.location());
1164 widget.type->setText(m_currentPrintDevice.makeAndModel());
1166 optionsPane->selectPrinter(QPrinter::NativeFormat);
1170 m_duplexPpdOption = QCUPSSupport::findPpdOption(
"Duplex", &m_currentPrintDevice);
1174void QUnixPrintWidgetPrivate::setOptionsPane(QPrintDialogPrivate *pane)
1178 optionsPane->selectPrinter(QPrinter::NativeFormat);
1181void QUnixPrintWidgetPrivate::_q_btnBrowseClicked()
1183 QString filename = widget.filename->text();
1184#if QT_CONFIG(filedialog)
1185 filename = QFileDialog::getSaveFileName(parent, QPrintDialog::tr(
"Print To File ..."), filename,
1186 QString(),
nullptr, QFileDialog::DontConfirmOverwrite);
1190 if (!filename.isEmpty()) {
1191 widget.filename->setText(filename);
1192 widget.printers->setCurrentIndex(widget.printers->count() - 1);
1196#if QT_CONFIG(messagebox)
1197bool QUnixPrintWidgetPrivate::checkFields()
1199 if (widget.filename->isEnabled()) {
1200 QString file = widget.filename->text();
1203 bool exists = fi.exists();
1204 bool opened =
false;
1205 if (exists && fi.isDir()) {
1206 QMessageBox::warning(q, q->windowTitle(),
1207 QPrintDialog::tr(
"%1 is a directory.\nPlease choose a different file name.").arg(file));
1209 }
else if ((exists && !fi.isWritable()) || !(opened = f.open(QFile::Append))) {
1210 QMessageBox::warning(q, q->windowTitle(),
1211 QPrintDialog::tr(
"File %1 is not writable.\nPlease choose a different file name.").arg(file));
1213 }
else if (exists) {
1214 int ret = QMessageBox::question(q, q->windowTitle(),
1215 QPrintDialog::tr(
"%1 already exists.\nDo you want to overwrite it?").arg(file),
1216 QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
1217 if (ret == QMessageBox::No)
1228 if (propertiesDialog) {
1229 QCUPSSupport::PagesPerSheet pagesPerSheet = qvariant_cast<QCUPSSupport::PagesPerSheet>(propertiesDialog->widget.pageSetup->m_ui.pagesPerSheetCombo
1232 QCUPSSupport::PageSet pageSet = qvariant_cast<QCUPSSupport::PageSet>(optionsPane->options.pageSetCombo->currentData());
1235 if (pagesPerSheet != QCUPSSupport::OnePagePerSheet
1236 && pageSet != QCUPSSupport::AllPages) {
1237 QMessageBox::warning(q, q->windowTitle(),
1238 QPrintDialog::tr(
"Options 'Pages Per Sheet' and 'Page Set' cannot be used together.\nPlease turn one of those options off."));
1249void QUnixPrintWidgetPrivate::setupPrinterProperties()
1251 delete propertiesDialog;
1253 QPrinter::OutputFormat outputFormat;
1254 QString printerName;
1256 if (q->testOption(QPrintDialog::PrintToFile)
1257 && (widget.printers->currentIndex() == widget.printers->count() - 1)) {
1258 outputFormat = QPrinter::PdfFormat;
1260 outputFormat = QPrinter::NativeFormat;
1261 printerName = widget.printers->currentText();
1264 propertiesDialog =
new QPrintPropertiesDialog(q->printer(), &m_currentPrintDevice, outputFormat, printerName, q);
1268void QUnixPrintWidgetPrivate::setPpdDuplex(QPrinter::DuplexMode mode)
1270 auto values = QStringList{} << QStringLiteral(
"Duplex");
1271 if (mode == QPrinter::DuplexNone) values << QStringLiteral(
"None");
1272 else if (mode == QPrinter::DuplexLongSide) values << QStringLiteral(
"DuplexNoTumble");
1273 else if (mode == QPrinter::DuplexShortSide) values << QStringLiteral(
"DuplexTumble");
1275 m_currentPrintDevice.setProperty(PDPK_PpdOption, values);
1279void QUnixPrintWidgetPrivate::_q_btnPropertiesClicked()
1281 if (!propertiesDialog)
1282 setupPrinterProperties();
1283 propertiesDialog->exec();
1287 optionsPane->updatePpdDuplexOption(optionsPane->options.noDuplex);
1288 optionsPane->updatePpdDuplexOption(optionsPane->options.duplexLong);
1289 optionsPane->updatePpdDuplexOption(optionsPane->options.duplexShort);
1293void QUnixPrintWidgetPrivate::setupPrinter()
1295 const int printerCount = widget.printers->count();
1296 const int index = widget.printers->currentIndex();
1298 if (filePrintersAdded && index == printerCount - 1) {
1299 printer->setPrinterName(QString());
1300 Q_ASSERT(index != printerCount - 2);
1301 printer->setOutputFormat(QPrinter::PdfFormat);
1302 QString path = widget.filename->text();
1303 if (QDir::isRelativePath(path))
1304 path = QDir::homePath() + QDir::separator() + path;
1305 printer->setOutputFileName(path);
1308 printer->setPrinterName(widget.printers->currentText());
1309 printer->setOutputFileName(QString());
1312 if (!propertiesDialog)
1313 setupPrinterProperties();
1315 propertiesDialog->setupPrinter();
1319
1320QUnixPrintWidget::QUnixPrintWidget(QPrinter *printer, QWidget *parent)
1321 : QWidget(parent), d(
new QUnixPrintWidgetPrivate(
this, printer))
1323 if (printer ==
nullptr)
1325 if (printer->outputFileName().isEmpty()) {
1326 QString home = QDir::homePath();
1327 QString cur = QDir::currentPath();
1328 if (!home.endsWith(u'/'))
1330 if (!cur.startsWith(home))
1332 else if (!cur.endsWith(u'/'))
1334 if (QGuiApplication::platformName() ==
"xcb"_L1) {
1335 if (printer->docName().isEmpty()) {
1336 cur +=
"print.pdf"_L1;
1338#if QT_CONFIG(regularexpression)
1339 const QRegularExpression re(QStringLiteral(
"(.*)\\.\\S+"));
1340 auto match = re.match(printer->docName());
1341 if (match.hasMatch())
1342 cur += match.captured(1);
1345 cur += printer->docName();
1350 d->widget.filename->setText(cur);
1353 d->widget.filename->setText(printer->outputFileName());
1354 const QString printerName = printer->printerName();
1355 if (!printerName.isEmpty()) {
1356 const int i = d->widget.printers->findText(printerName);
1358 d->widget.printers->setCurrentIndex(i);
1364
1365QUnixPrintWidget::~QUnixPrintWidget()
1371
1372
1373
1374void QUnixPrintWidget::updatePrinter()
1389#include "moc_qprintdialog.cpp"
1390#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()