4#include "qplatformdefs.h"
5#include <QtPrintSupport/private/qtprintsupportglobal_p.h>
7#include "private/qabstractprintdialog_p.h"
8#if QT_CONFIG(messagebox)
9#include <QtWidgets/qmessagebox.h>
12#if QT_CONFIG(filedialog)
13#include "qfiledialog.h"
15#include <QtCore/qdebug.h>
16#include <QtCore/qdir.h>
17#include <QtCore/qglobal.h>
18#include <QtCore/qstringconverter.h>
19#include <QtGui/qevent.h>
20#if QT_CONFIG(filesystemmodel)
21#include <QtGui/qfilesystemmodel.h>
23#include <QtWidgets/qstyleditemdelegate.h>
24#include <QtWidgets/qformlayout.h>
25#include <QtPrintSupport/qprinter.h>
27#include <qpa/qplatformprintplugin.h>
28#include <qpa/qplatformprintersupport.h>
30#include <private/qprintdevice_p.h>
32#include <QtWidgets/qdialogbuttonbox.h>
34#if QT_CONFIG(regularexpression)
35#include <qregularexpression.h>
38#if QT_CONFIG(completer)
39#include <private/qcompleter_p.h>
41#include "ui_qprintpropertieswidget.h"
42#include "ui_qprintsettingsoutput.h"
43#include "ui_qprintwidget.h"
47#include <private/qcups_p.h>
48#if QT_CONFIG(cupsjobwidget)
49#include "qcupsjobwidget_p.h"
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
88 Q_INIT_RESOURCE(qprintdialog);
93using namespace Qt::StringLiterals;
117 Ui::QPrintPropertiesWidget widget;
118 QDialogButtonBox *m_buttons;
119#if QT_CONFIG(cupsjobwidget)
150 friend class QPrintDialog;
154 Q_PRIVATE_SLOT(d,
void _q_printerChanged(
int))
190 bool filePrintersAdded;
195 Q_DECLARE_PUBLIC(QPrintDialog)
206#if QT_CONFIG(messagebox)
217 virtual void setTabs(
const QList<QWidget*> &tabs)
override;
226 void setExplicitDuplexMode(QPrint::DuplexMode duplexMode);
228 QPrint::DuplexMode explicitDuplexMode;
235
236
237
238
239
240
241
244 QPrinter::OutputFormat outputFormat,
const QString &printerName,
245 QAbstractPrintDialog *parent)
251 setWindowTitle(tr(
"Printer Properties"));
252 QVBoxLayout *lay =
new QVBoxLayout(
this);
253 QWidget *content =
new QWidget(
this);
254 widget.setupUi(content);
255 m_buttons =
new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal,
this);
256 lay->addWidget(content);
257 lay->addWidget(m_buttons);
260 connect(m_buttons->button(QDialogButtonBox::Cancel), &QPushButton::clicked,
this, &QPrintPropertiesDialog::reject);
262 widget.pageSetup->setPrinter(printer, currentPrintDevice, outputFormat, printerName);
264#if QT_CONFIG(cupsjobwidget)
265 m_jobOptions =
new QCupsJobWidget(printer, currentPrintDevice);
266 widget.tabs->insertTab(1, m_jobOptions, tr(
"Job Options"));
269 const int advancedTabIndex = widget.tabs->indexOf(widget.cupsPropertiesPage);
271 m_currentPrintDevice = currentPrintDevice;
272 const bool anyWidgetCreated = createAdvancedOptionsWidget();
274 widget.tabs->setTabEnabled(advancedTabIndex, anyWidgetCreated);
276 connect(widget.pageSetup, &QPageSetupWidget::ppdOptionChanged,
this, [
this] {
277 widget.conflictsLabel->setVisible(anyPpdOptionConflict());
281 Q_UNUSED(currentPrintDevice);
282 widget.tabs->setTabEnabled(advancedTabIndex,
false);
293 QCUPSSupport::clearCupsOptions(m_printer);
296 widget.pageSetup->setupPrinter();
297#if QT_CONFIG(cupsjobwidget)
298 m_jobOptions->setupPrinter();
303 m_printer->setColorMode(QPrinter::Color);
305 setPrinterAdvancedCupsOptions();
311 widget.pageSetup->revertToSavedValues();
313#if QT_CONFIG(cupsjobwidget)
314 m_jobOptions->revertToSavedValues();
318 revertAdvancedOptionsToSavedValues();
325#if QT_CONFIG(cups) && QT_CONFIG(messagebox)
326 if (widget.pageSetup->hasPpdConflict()) {
327 widget.tabs->setCurrentWidget(widget.tabPage);
328 const QMessageBox::StandardButton answer = QMessageBox::warning(
this, tr(
"Page Setup Conflicts"),
329 tr(
"There are conflicts in page setup options. Do you want to fix them?"),
330 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
331 if (answer != QMessageBox::No)
333 }
else if (anyAdvancedOptionConflict()) {
334 widget.tabs->setCurrentWidget(widget.cupsPropertiesPage);
335 const QMessageBox::StandardButton answer = QMessageBox::warning(
this, tr(
"Advanced Option Conflicts"),
336 tr(
"There are conflicts in some advanced options. Do you want to fix them?"),
337 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
338 if (answer != QMessageBox::No)
341 advancedOptionsUpdateSavedValues();
344#if QT_CONFIG(cupsjobwidget)
345 m_jobOptions->updateSavedValues();
348 widget.pageSetup->updateSavedValues();
356 widget.conflictsLabel->setVisible(anyPpdOptionConflict());
358 QDialog::showEvent(event);
364static const char *ppdOptionProperty =
"_q_ppd_option";
367static const char *ppdOriginallySelectedChoiceProperty =
"_q_ppd_originally_selected_choice";
370static const char *warningLabelProperty =
"_q_warning_label";
372static bool isBlacklistedGroup(
const ppd_group_t *group)
noexcept
374 return qstrcmp(group->name,
"InstallableOptions") == 0;
377static bool isBlacklistedOption(
const char *keyword)
noexcept
380 const char *cupsOptionBlacklist[] = {
388 auto equals = [](
const char *keyword) {
389 return [keyword](
const char *candidate) {
390 return qstrcmp(keyword, candidate) == 0;
393 return std::any_of(std::begin(cupsOptionBlacklist), std::end(cupsOptionBlacklist), equals(keyword));
396bool QPrintPropertiesDialog::createAdvancedOptionsWidget()
398 bool anyWidgetCreated =
false;
400 ppd_file_t *ppd = qvariant_cast<ppd_file_t*>(m_currentPrintDevice->property(PDPK_PpdFile));
403 toUnicode = QStringDecoder(ppd->lang_encoding, QStringDecoder::Flag::Stateless);
404 if (!toUnicode.isValid()) {
405 qWarning() <<
"QPrinSupport: Cups uses unsupported encoding" << ppd->lang_encoding;
406 toUnicode = QStringDecoder(QStringDecoder::Utf8, QStringDecoder::Flag::Stateless);
409 QWidget *holdingWidget =
new QWidget();
410 QVBoxLayout *layout =
new QVBoxLayout(holdingWidget);
412 for (
int i = 0; i < ppd->num_groups; ++i) {
413 const ppd_group_t *group = &ppd->groups[i];
415 if (!isBlacklistedGroup(group)) {
416 QFormLayout *groupLayout =
new QFormLayout();
418 for (
int i = 0; i < group->num_options; ++i) {
419 const ppd_option_t *option = &group->options[i];
421 if (!isBlacklistedOption(option->keyword)) {
422 QComboBox *choicesCb =
new QComboBox();
424 const auto setPpdOptionFromCombo = [
this, choicesCb, option] {
428 const int selectedChoiceIndex = choicesCb->currentData().toInt();
429 const auto values = QStringList{} << QString::fromLatin1(option->keyword)
430 << QString::fromLatin1(option->choices[selectedChoiceIndex].choice);
431 m_currentPrintDevice->setProperty(PDPK_PpdOption, values);
432 widget.conflictsLabel->setVisible(anyPpdOptionConflict());
435 bool foundMarkedChoice =
false;
436 bool markedChoiceNotAvailable =
false;
437 for (
int i = 0; i < option->num_choices; ++i) {
438 const ppd_choice_t *choice = &option->choices[i];
439 const auto values = QStringList{} << QString::fromLatin1(option->keyword) << QString::fromLatin1(choice->choice);
440 const bool choiceIsInstallableConflict = m_currentPrintDevice->isFeatureAvailable(PDPK_PpdChoiceIsInstallableConflict, values);
441 if (choiceIsInstallableConflict &&
static_cast<
int>(choice->marked) == 1) {
442 markedChoiceNotAvailable =
true;
443 }
else if (!choiceIsInstallableConflict) {
444 choicesCb->addItem(toUnicode(choice->text), i);
445 if (
static_cast<
int>(choice->marked) == 1) {
446 choicesCb->setCurrentIndex(choicesCb->count() - 1);
447 choicesCb->setProperty(ppdOriginallySelectedChoiceProperty, QVariant(i));
448 foundMarkedChoice =
true;
449 }
else if (!foundMarkedChoice && qstrcmp(choice->choice, option->defchoice) == 0) {
450 choicesCb->setCurrentIndex(choicesCb->count() - 1);
451 choicesCb->setProperty(ppdOriginallySelectedChoiceProperty, QVariant(i));
456 if (markedChoiceNotAvailable) {
460 setPpdOptionFromCombo();
463 if (choicesCb->count() > 1) {
465 connect(choicesCb, &QComboBox::currentIndexChanged,
this, setPpdOptionFromCombo);
468 QWidget *choicesCbWithLabel =
new QWidget();
469 QHBoxLayout *choicesCbWithLabelLayout =
new QHBoxLayout(choicesCbWithLabel);
470 choicesCbWithLabelLayout->setContentsMargins(0, 0, 0, 0);
471 QLabel *warningLabel =
new QLabel();
472 choicesCbWithLabelLayout->addWidget(choicesCb);
473 choicesCbWithLabelLayout->addWidget(warningLabel);
475 QLabel *optionLabel =
new QLabel(toUnicode(option->text));
476 optionLabel->setBuddy(choicesCb);
477 groupLayout->addRow(optionLabel, choicesCbWithLabel);
478 anyWidgetCreated =
true;
479 choicesCb->setProperty(ppdOptionProperty, QVariant::fromValue(option));
480 choicesCb->setProperty(warningLabelProperty, QVariant::fromValue(warningLabel));
481 m_advancedOptionsCombos << choicesCb;
488 if (groupLayout->rowCount() > 0) {
489 QGroupBox *groupBox =
new QGroupBox(toUnicode(group->text));
490 groupBox->setLayout(groupLayout);
491 layout->addWidget(groupBox);
498 layout->addStretch();
499 widget.scrollArea->setWidget(holdingWidget);
502 return anyWidgetCreated;
505void QPrintPropertiesDialog::setPrinterAdvancedCupsOptions()
const
507 for (
const QComboBox *choicesCb : m_advancedOptionsCombos) {
508 const ppd_option_t *option = qvariant_cast<
const ppd_option_t *>(choicesCb->property(ppdOptionProperty));
513 const int selectedChoiceIndex = choicesCb->currentData().toInt();
514 const char *selectedChoice = option->choices[selectedChoiceIndex].choice;
516 if (qstrcmp(option->keyword,
"ColorModel") == 0)
517 m_printer->setColorMode(qstrcmp(selectedChoice,
"Gray") == 0 ? QPrinter::GrayScale : QPrinter::Color);
519 if (qstrcmp(option->defchoice, selectedChoice) != 0)
520 QCUPSSupport::setCupsOption(m_printer, QString::fromLatin1(option->keyword), QString::fromLatin1(selectedChoice));
524void QPrintPropertiesDialog::revertAdvancedOptionsToSavedValues()
const
526 for (QComboBox *choicesCb : m_advancedOptionsCombos) {
527 const int originallySelectedChoice = qvariant_cast<
int>(choicesCb->property(ppdOriginallySelectedChoiceProperty));
528 const int newComboIndexToSelect = choicesCb->findData(originallySelectedChoice);
529 choicesCb->setCurrentIndex(newComboIndexToSelect);
532 widget.conflictsLabel->setVisible(anyPpdOptionConflict());
535void QPrintPropertiesDialog::advancedOptionsUpdateSavedValues()
const
537 for (QComboBox *choicesCb : m_advancedOptionsCombos)
538 choicesCb->setProperty(ppdOriginallySelectedChoiceProperty, choicesCb->currentData());
541bool QPrintPropertiesDialog::anyPpdOptionConflict()
const
544 const bool pageSetupConflicts = widget.pageSetup->hasPpdConflict();
545 const bool advancedOptionConflicts = anyAdvancedOptionConflict();
546 return pageSetupConflicts || advancedOptionConflicts;
549bool QPrintPropertiesDialog::anyAdvancedOptionConflict()
const
551 const QIcon warning = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning,
nullptr,
nullptr);
553 bool anyConflicted =
false;
555 for (
const QComboBox *choicesCb : m_advancedOptionsCombos) {
556 const ppd_option_t *option = qvariant_cast<
const ppd_option_t *>(choicesCb->property(ppdOptionProperty));
557 QLabel *warningLabel = qvariant_cast<QLabel *>(choicesCb->property(warningLabelProperty));
558 if (option->conflicted) {
559 anyConflicted =
true;
560 const int pixmap_size = choicesCb->sizeHint().height() * .75;
561 warningLabel->setPixmap(warning.pixmap(pixmap_size, pixmap_size));
563 warningLabel->setPixmap(QPixmap());
567 return anyConflicted;
577
578
579
580
581
582
583
586 explicitDuplexMode(QPrint::DuplexAuto)
599 top =
new QUnixPrintWidget(q->printer(), q);
600 bottom =
new QWidget(q);
601 options.setupUi(bottom);
602 options.color->setIconSize(QSize(32, 32));
603 options.color->setIcon(QIcon(
":/qt-project.org/dialogs/qprintdialog/images/status-color.png"_L1));
604 options.grayscale->setIconSize(QSize(32, 32));
605 options.grayscale->setIcon(QIcon(
":/qt-project.org/dialogs/qprintdialog/images/status-gray-scale.png"_L1));
609 options.pageSetCombo->addItem(tr(
"All Pages"), QVariant::fromValue(QCUPSSupport::AllPages));
610 options.pageSetCombo->addItem(tr(
"Odd Pages"), QVariant::fromValue(QCUPSSupport::OddPages));
611 options.pageSetCombo->addItem(tr(
"Even Pages"), QVariant::fromValue(QCUPSSupport::EvenPages));
613 delete options.pagesRadioButton;
614 delete options.pagesLineEdit;
615 options.pagesRadioButton =
nullptr;
616 options.pagesLineEdit =
nullptr;
621 buttons =
new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, q);
622 collapseButton =
new QPushButton(QPrintDialog::tr(
"&Options >>"), buttons);
623 buttons->addButton(collapseButton, QDialogButtonBox::ResetRole);
624 bottom->setVisible(
false);
626 QPushButton *printButton = buttons->button(QDialogButtonBox::Ok);
627 printButton->setText(QPrintDialog::tr(
"&Print"));
628 printButton->setDefault(
true);
630 QVBoxLayout *lay =
new QVBoxLayout(q);
632 lay->addWidget(bottom);
633 lay->addWidget(buttons);
635#if !QT_CONFIG(messagebox)
636 QObject::connect(buttons, SIGNAL(accepted()), q, SLOT(accept()));
638 QObject::connect(buttons, SIGNAL(accepted()), q, SLOT(_q_checkFields()));
640 QObject::connect(buttons, SIGNAL(rejected()), q, SLOT(reject()));
642 QObject::connect(options.printSelection, SIGNAL(toggled(
bool)),
643 q, SLOT(_q_togglePageSetCombo(
bool)));
645 QObject::connect(options.printCurrentPage, SIGNAL(toggled(
bool)),
646 q, SLOT(_q_togglePageSetCombo(
bool)));
648 QObject::connect(collapseButton, SIGNAL(released()), q, SLOT(_q_collapseOrExpandDialog()));
650 QObject::connect(options.noDuplex, &QAbstractButton::clicked, q, [
this] { setExplicitDuplexMode(QPrint::DuplexNone); });
651 QObject::connect(options.duplexLong, &QAbstractButton::clicked, q, [
this] { setExplicitDuplexMode(QPrint::DuplexLongSide); });
652 QObject::connect(options.duplexShort, &QAbstractButton::clicked, q, [
this] { setExplicitDuplexMode(QPrint::DuplexShortSide); });
655 QObject::connect(options.noDuplex, &QAbstractButton::toggled, q, [
this] { updatePpdDuplexOption(options.noDuplex); });
656 QObject::connect(options.duplexLong, &QAbstractButton::toggled, q, [
this] { updatePpdDuplexOption(options.duplexLong); });
657 QObject::connect(options.duplexShort, &QAbstractButton::toggled, q, [
this] { updatePpdDuplexOption(options.duplexShort); });
665 QPrinter *p = q->printer();
666 printerOutputFormat = outputFormat;
669 const auto supportedDuplexMode =
top->d->m_currentPrintDevice.supportedDuplexModes();
670 options.duplexLong->setEnabled(supportedDuplexMode.contains(QPrint::DuplexLongSide));
671 options.duplexShort->setEnabled(supportedDuplexMode.contains(QPrint::DuplexShortSide));
673 if (p->colorMode() == QPrinter::Color)
674 options.color->setChecked(
true);
676 options.grayscale->setChecked(
true);
681 QPrint::DuplexMode duplex;
682 if (explicitDuplexMode != QPrint::DuplexAuto && supportedDuplexMode.contains(explicitDuplexMode))
683 duplex = explicitDuplexMode;
685 duplex =
static_cast<QPrint::DuplexMode>(p->duplex());
687 case QPrint::DuplexNone:
688 options.noDuplex->setChecked(
true);
break;
689 case QPrint::DuplexLongSide:
690 case QPrint::DuplexAuto:
691 options.duplexLong->setChecked(
true);
break;
692 case QPrint::DuplexShortSide:
693 options.duplexShort->setChecked(
true);
break;
695 options.copies->setValue(p->copyCount());
696 options.collate->setChecked(p->collateCopies());
697 options.reverse->setChecked(p->pageOrder() == QPrinter::LastPageFirst);
699 if (outputFormat == QPrinter::PdfFormat || options.printSelection->isChecked()
700 || options.printCurrentPage->isChecked())
702 options.pageSetCombo->setEnabled(
false);
704 options.pageSetCombo->setEnabled(
true);
710 options.pagesRadioButton->setEnabled(outputFormat != QPrinter::PdfFormat);
713 options.colorMode->setVisible(outputFormat == QPrinter::PdfFormat);
719void QPrintDialogPrivate::updatePpdDuplexOption(QRadioButton *radio)
721 const bool checked = radio->isChecked();
723 if (radio == options.noDuplex) top->d->setPpdDuplex(QPrinter::DuplexNone);
724 else if (radio == options.duplexLong) top->d->setPpdDuplex(QPrinter::DuplexLongSide);
725 else if (radio == options.duplexShort) top->d->setPpdDuplex(QPrinter::DuplexShortSide);
727 const bool conflict = checked && top->d->m_duplexPpdOption && top->d->m_duplexPpdOption->conflicted;
728 radio->setIcon(conflict ? QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning,
nullptr,
nullptr) : QIcon());
735 explicitDuplexMode = duplexMode;
745 QPrinter* p = q->printer();
747 if (options.duplex->isEnabled()) {
748 if (options.noDuplex->isChecked())
749 p->setDuplex(QPrinter::DuplexNone);
750 else if (options.duplexLong->isChecked())
751 p->setDuplex(QPrinter::DuplexLongSide);
753 p->setDuplex(QPrinter::DuplexShortSide);
758 if (p->outputFormat() == QPrinter::PdfFormat)
760 p->setColorMode(options.color->isChecked() ? QPrinter::Color : QPrinter::GrayScale);
762 p->setPageOrder(options.reverse->isChecked() ? QPrinter::LastPageFirst : QPrinter::FirstPageFirst);
765 if (options.printAll->isChecked()) {
766 p->setPrintRange(QPrinter::AllPages);
767 p->setPageRanges(QPageRanges());
768 }
else if (options.printSelection->isChecked()) {
769 p->setPrintRange(QPrinter::Selection);
770 p->setPageRanges(QPageRanges());
771 }
else if (options.printCurrentPage->isChecked()) {
772 p->setPrintRange(QPrinter::CurrentPage);
773 p->setPageRanges(QPageRanges());
774 }
else if (options.printRange->isChecked()) {
775 if (q->testOption(QPrintDialog::PrintPageRange)) {
776 p->setPrintRange(QPrinter::PageRange);
777 p->setFromTo(options.from->value(), qMax(options.from->value(), options.to->value()));
781 p->setPrintRange(QPrinter::AllPages);
782 p->setPageRanges(QPageRanges());
787 if (options.pagesRadioButton->isChecked()) {
788 const QPageRanges ranges = QPageRanges::fromString(options.pagesLineEdit->text());
789 p->setPrintRange(QPrinter::AllPages);
790 p->setPageRanges(QPageRanges());
793 QCUPSSupport::setPageRange(p, ranges.toString());
797 if (p->printRange() == QPrinter::AllPages || p->printRange() == QPrinter::PageRange) {
799 QCUPSSupport::PageSet pageSet = qvariant_cast<QCUPSSupport::PageSet>(options.pageSetCombo->itemData(options.pageSetCombo->currentIndex()));
800 if (q->testOption(QPrintDialog::PrintPageRange)
801 && p->printRange() == QPrinter::PageRange
802 && (q->fromPage() % 2 == 0)) {
805 case QCUPSSupport::AllPages:
807 case QCUPSSupport::OddPages:
808 QCUPSSupport::setPageSet(p, QCUPSSupport::EvenPages);
810 case QCUPSSupport::EvenPages:
811 QCUPSSupport::setPageSet(p, QCUPSSupport::OddPages);
814 }
else if (pageSet != QCUPSSupport::AllPages) {
815 QCUPSSupport::setPageSet(p, pageSet);
820 if (!q->testOption(QPrintDialog::PrintPageRange) && options.printRange->isChecked())
821 QCUPSSupport::setPageRange(p, options.from->value(), qMax(options.from->value(), options.to->value()));
826 p->setCopyCount(options.copies->value());
827 p->setCollateCopies(options.collate->isChecked());
832 if (printerOutputFormat == QPrinter::PdfFormat)
835 options.pageSetCombo->setDisabled(checked);
840 int collapseHeight = 0;
842 QWidget *widgetToHide = bottom;
843 if (widgetToHide->isVisible()) {
845 collapseHeight = widgetToHide->y() + widgetToHide->height() - (
top->y() +
top->height());
849 widgetToHide->setVisible(! widgetToHide->isVisible());
850 if (! widgetToHide->isVisible()) {
851 q->layout()->activate();
852 q->resize( QSize(q->width(), q->height() - collapseHeight) );
856#if QT_CONFIG(messagebox)
857void QPrintDialogPrivate::_q_checkFields()
860 if (top->d->checkFields())
869 options.gbPrintRange->setVisible(q->testOption(QPrintDialog::PrintPageRange) ||
870 q->testOption(QPrintDialog::PrintSelection) ||
871 q->testOption(QPrintDialog::PrintCurrentPage));
873 options.printRange->setEnabled(q->testOption(QPrintDialog::PrintPageRange));
874 options.printSelection->setVisible(q->testOption(QPrintDialog::PrintSelection));
875 options.printCurrentPage->setVisible(q->testOption(QPrintDialog::PrintCurrentPage));
876 options.collate->setVisible(q->testOption(QPrintDialog::PrintCollateCopies));
880 if (!q->testOption(QPrintDialog::PrintPageRange)
881 && (q->testOption(QPrintDialog::PrintSelection) || q->testOption(QPrintDialog::PrintCurrentPage))) {
882 options.pageSetCombo->setVisible(
false);
883 options.pageSetLabel->setVisible(
false);
885 options.pageSetCombo->setVisible(
true);
886 options.pageSetLabel->setVisible(
true);
889 if (!q->testOption(QPrintDialog::PrintPageRange)) {
892 options.gbPrintRange->setVisible(
true);
893 options.printRange->setEnabled(
true);
897 switch (q->printRange()) {
898 case QPrintDialog::AllPages:
899 options.printAll->setChecked(
true);
900 options.pageSetCombo->setEnabled(
true);
902 case QPrintDialog::Selection:
903 options.printSelection->setChecked(
true);
904 options.pageSetCombo->setEnabled(
false);
906 case QPrintDialog::PageRange:
907 options.printRange->setChecked(
true);
908 options.pageSetCombo->setEnabled(
true);
910 case QPrintDialog::CurrentPage:
911 if (q->testOption(QPrintDialog::PrintCurrentPage)) {
912 options.printCurrentPage->setChecked(
true);
913 options.pageSetCombo->setEnabled(
false);
919 const int minPage = qMax(1, qMin(q->minPage() , q->maxPage()));
920 const int maxPage = qMax(1, q->maxPage() == INT_MAX ? 9999 : q->maxPage());
922 options.from->setMinimum(minPage);
923 options.to->setMinimum(minPage);
924 options.from->setMaximum(maxPage);
925 options.to->setMaximum(maxPage);
927 options.from->setValue(q->fromPage());
928 options.to->setValue(q->toPage());
934 QList<QWidget*>::ConstIterator iter = tabWidgets.begin();
935 while(iter != tabWidgets.constEnd()) {
936 QWidget *tab = *iter;
937 options.tabs->addTab(tab, tab->windowTitle());
946
947
948
949
950
951
953QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent)
954 : QAbstractPrintDialog(*(
new QPrintDialogPrivate), printer, parent)
961
962
963QPrintDialog::QPrintDialog(QWidget *parent)
964 : QAbstractPrintDialog(*(
new QPrintDialogPrivate),
nullptr, parent)
970QPrintDialog::~QPrintDialog()
974void QPrintDialog::setVisible(
bool visible)
981 QAbstractPrintDialog::setVisible(visible);
984int QPrintDialog::exec()
986 return QAbstractPrintDialog::exec();
989void QPrintDialog::accept()
992#if QT_CONFIG(cups) && QT_CONFIG(messagebox)
993 if (d->options.pagesRadioButton->isChecked()) {
994 const QString rangesText = d->options.pagesLineEdit->text();
995 if (rangesText.isEmpty() || QPageRanges::fromString(rangesText).isEmpty()) {
996 QMessageBox::critical(
this, tr(
"Invalid Pages Definition"),
997 tr(
"%1 does not follow the correct syntax. Please use ',' to separate "
998 "ranges and pages, '-' to define ranges and make sure ranges do "
999 "not intersect with each other.").arg(rangesText),
1000 QMessageBox::Ok, QMessageBox::Ok);
1004 if (d->top->d->m_duplexPpdOption && d->top->d->m_duplexPpdOption->conflicted) {
1005 const QMessageBox::StandardButton answer = QMessageBox::warning(
this, tr(
"Duplex Settings Conflicts"),
1006 tr(
"There are conflicts in duplex settings. Do you want to fix them?"),
1007 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
1008 if (answer != QMessageBox::No)
1020
1021
1022
1023
1024
1025
1027#if defined (Q_OS_UNIX)
1030
1031QUnixPrintWidgetPrivate::QUnixPrintWidgetPrivate(QUnixPrintWidget *p, QPrinter *prn)
1032 : parent(p), propertiesDialog(
nullptr), printer(prn),
1034 m_duplexPpdOption(
nullptr),
1036 optionsPane(
nullptr), filePrintersAdded(
false)
1040 q = qobject_cast<QPrintDialog*> (parent->parent());
1042 widget.setupUi(parent);
1044 int currentPrinterIndex = 0;
1045 QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
1047 const QStringList printers = ps->availablePrintDeviceIds();
1048 const QString defaultPrinter = ps->defaultPrintDeviceId();
1050 widget.printers->addItems(printers);
1052 const QString selectedPrinter = prn && !prn->printerName().isEmpty() ? prn->printerName() : defaultPrinter;
1053 const int idx = printers.indexOf(selectedPrinter);
1056 currentPrinterIndex = idx;
1058 widget.properties->setEnabled(
true);
1060#if QT_CONFIG(filesystemmodel) && QT_CONFIG(completer)
1061 QFileSystemModel *fsm =
new QFileSystemModel(widget.filename);
1062 fsm->setRootPath(QDir::homePath());
1063 widget.filename->setCompleter(
new QCompleter(fsm, widget.filename));
1065 _q_printerChanged(currentPrinterIndex);
1067 QObject::connect(widget.printers, SIGNAL(currentIndexChanged(
int)),
1068 parent, SLOT(_q_printerChanged(
int)));
1069 QObject::connect(widget.fileBrowser, SIGNAL(clicked()), parent, SLOT(_q_btnBrowseClicked()));
1070 QObject::connect(widget.properties, SIGNAL(clicked()), parent, SLOT(_q_btnPropertiesClicked()));
1073 widget.preview->setVisible(
false);
1076void QUnixPrintWidgetPrivate::updateWidget()
1078 const bool printToFile = q ==
nullptr || q->testOption(QPrintDialog::PrintToFile);
1079 if (printToFile && !filePrintersAdded) {
1080 if (widget.printers->count())
1081 widget.printers->insertSeparator(widget.printers->count());
1082 widget.printers->addItem(QPrintDialog::tr(
"Print to File (PDF)"));
1083 filePrintersAdded =
true;
1084 if (widget.printers->count() == 1)
1085 _q_printerChanged(0);
1087 if (!printToFile && filePrintersAdded) {
1088 widget.printers->removeItem(widget.printers->count()-1);
1089 widget.printers->removeItem(widget.printers->count()-1);
1090 if (widget.printers->count())
1091 widget.printers->removeItem(widget.printers->count()-1);
1092 filePrintersAdded =
false;
1094 if (printer && filePrintersAdded && (printer->outputFormat() != QPrinter::NativeFormat
1095 || printer->printerName().isEmpty()))
1097 if (printer->outputFormat() == QPrinter::PdfFormat)
1098 widget.printers->setCurrentIndex(widget.printers->count() - 1);
1099 widget.filename->setEnabled(
true);
1100 widget.lOutput->setEnabled(
true);
1103 widget.filename->setVisible(printToFile);
1104 widget.lOutput->setVisible(printToFile);
1105 widget.fileBrowser->setVisible(printToFile);
1108 widget.properties->setVisible(q->testOption(QAbstractPrintDialog::PrintShowPageSize));
1111QUnixPrintWidgetPrivate::~QUnixPrintWidgetPrivate()
1115void QUnixPrintWidgetPrivate::_q_printerChanged(
int index)
1119 const int printerCount = widget.printers->count();
1120 widget.filename->setEnabled(
false);
1121 widget.lOutput->setEnabled(
false);
1124 if (propertiesDialog){
1125 delete propertiesDialog;
1126 propertiesDialog =
nullptr;
1130 m_duplexPpdOption =
nullptr;
1133 if (filePrintersAdded) {
1134 Q_ASSERT(index != printerCount - 2);
1135 if (index == printerCount - 1) {
1136 widget.location->setText(QPrintDialog::tr(
"Local file"));
1137 widget.type->setText(QPrintDialog::tr(
"Write PDF file"));
1138 widget.properties->setEnabled(
true);
1139 widget.filename->setEnabled(
true);
1140 QString filename = widget.filename->text();
1141 widget.filename->setText(filename);
1142 widget.lOutput->setEnabled(
true);
1143 printer->setOutputFormat(QPrinter::PdfFormat);
1144 m_currentPrintDevice = QPrintDevice();
1146 optionsPane->selectPrinter(QPrinter::PdfFormat);
1152 printer->setOutputFormat(QPrinter::NativeFormat);
1154 QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
1156 m_currentPrintDevice = ps->createPrintDevice(widget.printers->itemText(index));
1158 m_currentPrintDevice = QPrintDevice();
1160 printer->setPrinterName(m_currentPrintDevice.id());
1162 widget.location->setText(m_currentPrintDevice.location());
1163 widget.type->setText(m_currentPrintDevice.makeAndModel());
1165 optionsPane->selectPrinter(QPrinter::NativeFormat);
1169 m_duplexPpdOption = QCUPSSupport::findPpdOption(
"Duplex", &m_currentPrintDevice);
1173void QUnixPrintWidgetPrivate::setOptionsPane(QPrintDialogPrivate *pane)
1177 optionsPane->selectPrinter(QPrinter::NativeFormat);
1180void QUnixPrintWidgetPrivate::_q_btnBrowseClicked()
1182 QString filename = widget.filename->text();
1183#if QT_CONFIG(filedialog)
1184 filename = QFileDialog::getSaveFileName(parent, QPrintDialog::tr(
"Print To File ..."), filename,
1185 QString(),
nullptr, QFileDialog::DontConfirmOverwrite);
1189 if (!filename.isEmpty()) {
1190 widget.filename->setText(filename);
1191 widget.printers->setCurrentIndex(widget.printers->count() - 1);
1195#if QT_CONFIG(messagebox)
1196bool QUnixPrintWidgetPrivate::checkFields()
1198 if (widget.filename->isEnabled()) {
1199 QString file = widget.filename->text();
1202 bool exists = fi.exists();
1203 bool opened =
false;
1204 if (exists && fi.isDir()) {
1205 QMessageBox::warning(q, q->windowTitle(),
1206 QPrintDialog::tr(
"%1 is a directory.\nPlease choose a different file name.").arg(file));
1208 }
else if ((exists && !fi.isWritable()) || !(opened = f.open(QFile::Append))) {
1209 QMessageBox::warning(q, q->windowTitle(),
1210 QPrintDialog::tr(
"File %1 is not writable.\nPlease choose a different file name.").arg(file));
1212 }
else if (exists) {
1213 int ret = QMessageBox::question(q, q->windowTitle(),
1214 QPrintDialog::tr(
"%1 already exists.\nDo you want to overwrite it?").arg(file),
1215 QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
1216 if (ret == QMessageBox::No)
1227 if (propertiesDialog) {
1228 QCUPSSupport::PagesPerSheet pagesPerSheet = qvariant_cast<QCUPSSupport::PagesPerSheet>(propertiesDialog->widget.pageSetup->m_ui.pagesPerSheetCombo
1231 QCUPSSupport::PageSet pageSet = qvariant_cast<QCUPSSupport::PageSet>(optionsPane->options.pageSetCombo->currentData());
1234 if (pagesPerSheet != QCUPSSupport::OnePagePerSheet
1235 && pageSet != QCUPSSupport::AllPages) {
1236 QMessageBox::warning(q, q->windowTitle(),
1237 QPrintDialog::tr(
"Options 'Pages Per Sheet' and 'Page Set' cannot be used together.\nPlease turn one of those options off."));
1248void QUnixPrintWidgetPrivate::setupPrinterProperties()
1250 delete propertiesDialog;
1252 QPrinter::OutputFormat outputFormat;
1253 QString printerName;
1255 if (q->testOption(QPrintDialog::PrintToFile)
1256 && (widget.printers->currentIndex() == widget.printers->count() - 1)) {
1257 outputFormat = QPrinter::PdfFormat;
1259 outputFormat = QPrinter::NativeFormat;
1260 printerName = widget.printers->currentText();
1263 propertiesDialog =
new QPrintPropertiesDialog(q->printer(), &m_currentPrintDevice, outputFormat, printerName, q);
1267void QUnixPrintWidgetPrivate::setPpdDuplex(QPrinter::DuplexMode mode)
1269 auto values = QStringList{} << QStringLiteral(
"Duplex");
1270 if (mode == QPrinter::DuplexNone) values << QStringLiteral(
"None");
1271 else if (mode == QPrinter::DuplexLongSide) values << QStringLiteral(
"DuplexNoTumble");
1272 else if (mode == QPrinter::DuplexShortSide) values << QStringLiteral(
"DuplexTumble");
1274 m_currentPrintDevice.setProperty(PDPK_PpdOption, values);
1278void QUnixPrintWidgetPrivate::_q_btnPropertiesClicked()
1280 if (!propertiesDialog)
1281 setupPrinterProperties();
1282 propertiesDialog->exec();
1286 optionsPane->updatePpdDuplexOption(optionsPane->options.noDuplex);
1287 optionsPane->updatePpdDuplexOption(optionsPane->options.duplexLong);
1288 optionsPane->updatePpdDuplexOption(optionsPane->options.duplexShort);
1292void QUnixPrintWidgetPrivate::setupPrinter()
1294 const int printerCount = widget.printers->count();
1295 const int index = widget.printers->currentIndex();
1297 if (filePrintersAdded && index == printerCount - 1) {
1298 printer->setPrinterName(QString());
1299 Q_ASSERT(index != printerCount - 2);
1300 printer->setOutputFormat(QPrinter::PdfFormat);
1301 QString path = widget.filename->text();
1302 if (QDir::isRelativePath(path))
1303 path = QDir::homePath() + QDir::separator() + path;
1304 printer->setOutputFileName(path);
1307 printer->setPrinterName(widget.printers->currentText());
1308 printer->setOutputFileName(QString());
1311 if (!propertiesDialog)
1312 setupPrinterProperties();
1314 propertiesDialog->setupPrinter();
1318
1319QUnixPrintWidget::QUnixPrintWidget(QPrinter *printer, QWidget *parent)
1320 : QWidget(parent), d(
new QUnixPrintWidgetPrivate(
this, printer))
1322 if (printer ==
nullptr)
1324 if (printer->outputFileName().isEmpty()) {
1325 QString home = QDir::homePath();
1326 QString cur = QDir::currentPath();
1327 if (!home.endsWith(u'/'))
1329 if (!cur.startsWith(home))
1331 else if (!cur.endsWith(u'/'))
1333 if (QGuiApplication::platformName() ==
"xcb"_L1) {
1334 if (printer->docName().isEmpty()) {
1335 cur +=
"print.pdf"_L1;
1337#if QT_CONFIG(regularexpression)
1338 const QRegularExpression re(QStringLiteral(
"(.*)\\.\\S+"));
1339 auto match = re.match(printer->docName());
1340 if (match.hasMatch())
1341 cur += match.captured(1);
1344 cur += printer->docName();
1349 d->widget.filename->setText(cur);
1352 d->widget.filename->setText(printer->outputFileName());
1353 const QString printerName = printer->printerName();
1354 if (!printerName.isEmpty()) {
1355 const int i = d->widget.printers->findText(printerName);
1357 d->widget.printers->setCurrentIndex(i);
1363
1364QUnixPrintWidget::~QUnixPrintWidget()
1370
1371
1372
1373void QUnixPrintWidget::updatePrinter()
1388#include "moc_qprintdialog.cpp"
1389#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()