From 608301d4c81ce65804a088aaebbd5433a56d69d7 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Thu, 28 Dec 2017 11:22:32 +0100 Subject: CUPS: Enable printing arbitrary pages and page ranges Task-number: QTBUG-1311 Change-Id: I8e09def0e0d8c1404d3ee86845d98a30c23b6485 Reviewed-by: Andy Shaw --- src/printsupport/dialogs/qprintdialog_unix.cpp | 104 +++++++++++++++++++++++ src/printsupport/dialogs/qprintsettingsoutput.ui | 90 +++++++++++++++++--- src/printsupport/kernel/qcups.cpp | 7 +- src/printsupport/kernel/qcups_p.h | 1 + 4 files changed, 188 insertions(+), 14 deletions(-) diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp index 3a89c9e68c..47e2fa58f0 100644 --- a/src/printsupport/dialogs/qprintdialog_unix.cpp +++ b/src/printsupport/dialogs/qprintdialog_unix.cpp @@ -493,6 +493,9 @@ void QPrintDialogPrivate::init() options.pageSetCombo->addItem(tr("All Pages"), QVariant::fromValue(QCUPSSupport::AllPages)); options.pageSetCombo->addItem(tr("Odd Pages"), QVariant::fromValue(QCUPSSupport::OddPages)); options.pageSetCombo->addItem(tr("Even Pages"), QVariant::fromValue(QCUPSSupport::EvenPages)); +#else + for (int i = options.pagesLayout->count() - 1; i >= 0; --i) + delete options.pagesLayout->itemAt(i)->widget(); #endif top->d->setOptionsPane(this); @@ -565,6 +568,87 @@ void QPrintDialogPrivate::selectPrinter(const QPrinter::OutputFormat outputForma options.pageSetCombo->setEnabled(true); } +#if QT_CONFIG(cups) +static std::vector> pageRangesFromString(const QString &pagesString) Q_DECL_NOTHROW +{ + std::vector> result; + const QStringList items = pagesString.split(','); + for (const QString item : items) { + if (item.isEmpty()) + return {}; + + if (item.contains(QLatin1Char('-'))) { + const QStringList rangeItems = item.split('-'); + if (rangeItems.count() != 2) + return {}; + + bool ok; + const int number1 = rangeItems[0].toInt(&ok); + if (!ok) + return {}; + + const int number2 = rangeItems[1].toInt(&ok); + if (!ok) + return {}; + + if (number1 < 1 || number2 < 1 || number2 < number1) + return {}; + + result.push_back(std::make_pair(number1, number2)); + + } else { + bool ok; + const int number = item.toInt(&ok); + if (!ok) + return {}; + + if (number < 1) + return {}; + + result.push_back(std::make_pair(number, number)); + } + } + + // check no range intersects with the next + std::sort(result.begin(), result.end(), [](auto it1, auto it2) { return it1.first < it2.first; }); + int previousSecond = -1; + for (auto pair : result) { + if (pair.first <= previousSecond) + return {}; + + previousSecond = pair.second; + } + + return result; +} + +static QString stringFromPageRanges(const std::vector> &pageRanges) Q_DECL_NOTHROW +{ + QString result; + + for (auto pair : pageRanges) { + if (!result.isEmpty()) + result += QLatin1Char(','); + + if (pair.first == pair.second) + result += QString::number(pair.first); + else + result += QStringLiteral("%1-%2").arg(pair.first).arg(pair.second); + } + + return result; +} + +static bool isValidPagesString(const QString &pagesString) Q_DECL_NOTHROW +{ + if (pagesString.isEmpty()) + return false; + + auto pagesRanges = pageRangesFromString(pagesString); + return !pagesRanges.empty(); +} +#endif + void QPrintDialogPrivate::setupPrinter() { // First setup the requested OutputFormat, Printer and Page Size first @@ -609,6 +693,16 @@ void QPrintDialogPrivate::setupPrinter() } #if QT_CONFIG(cups) + if (options.pagesRadioButton->isChecked()) { + auto pageRanges = pageRangesFromString(options.pagesLineEdit->text()); + + p->setPrintRange(QPrinter::AllPages); + p->setFromTo(0, 0); + + // server-side page filtering + QCUPSSupport::setPageRange(p, stringFromPageRanges(pageRanges)); + } + // page set if (p->printRange() == QPrinter::AllPages || p->printRange() == QPrinter::PageRange) { //If the application is selecting pages and the first page number is even then need to adjust the odd-even accordingly @@ -805,6 +899,16 @@ int QPrintDialog::exec() void QPrintDialog::accept() { Q_D(QPrintDialog); +#if QT_CONFIG(cups) + if (d->options.pagesRadioButton->isChecked() && !isValidPagesString(d->options.pagesLineEdit->text())) { + QMessageBox::critical(this, tr("Invalid pages definition"), + tr("%1 does not follow the correct syntax. Please use ',' to separate " + "ranges and pages, '-' to define ranges and make sure ranges do " + "not intersect with each other.").arg(d->options.pagesLineEdit->text()), + QMessageBox::Ok, QMessageBox::Ok); + return; + } +#endif d->setupPrinter(); QDialog::accept(); } diff --git a/src/printsupport/dialogs/qprintsettingsoutput.ui b/src/printsupport/dialogs/qprintsettingsoutput.ui index 0fa34ab27f..290111a98c 100644 --- a/src/printsupport/dialogs/qprintsettingsoutput.ui +++ b/src/printsupport/dialogs/qprintsettingsoutput.ui @@ -6,15 +6,24 @@ 0 0 - 426 - 187 + 432 + 251 Form - + + 0 + + + 0 + + + 0 + + 0 @@ -42,7 +51,16 @@ 4 - + + 6 + + + 6 + + + 6 + + 6 @@ -60,7 +78,16 @@ 6 - + + 0 + + + 0 + + + 0 + + 0 @@ -118,6 +145,27 @@ + + + + + + Pages + + + + + + + false + + + Specify pages or ranges separated by commas. Ranges are specified by two numbers separated by a hyphen. E.g: 3,5-7,9 prints pages 3, 5, 6, 7 and 9. + + + + + @@ -361,12 +409,12 @@ setEnabled(bool) - 76 - 59 + 89 + 113 - 122 - 57 + 182 + 113 @@ -377,12 +425,28 @@ setEnabled(bool) - 69 - 67 + 82 + 113 + + + 267 + 113 + + + + + pagesRadioButton + toggled(bool) + pagesLineEdit + setEnabled(bool) + + + 58 + 132 - 215 - 67 + 163 + 128 diff --git a/src/printsupport/kernel/qcups.cpp b/src/printsupport/kernel/qcups.cpp index 50c6953718..115ecb0ac2 100644 --- a/src/printsupport/kernel/qcups.cpp +++ b/src/printsupport/kernel/qcups.cpp @@ -253,9 +253,14 @@ void QCUPSSupport::setPagesPerSheetLayout(QPrinter *printer, const PagesPerShee } void QCUPSSupport::setPageRange(QPrinter *printer, int pageFrom, int pageTo) +{ + setPageRange(printer, QStringLiteral("%1-%2").arg(pageFrom).arg(pageTo)); +} + +void QCUPSSupport::setPageRange(QPrinter *printer, const QString &pageRange) { QStringList cupsOptions = cupsOptionsList(printer); - setCupsOption(cupsOptions, QStringLiteral("page-ranges"), QStringLiteral("%1-%2").arg(pageFrom).arg(pageTo)); + setCupsOption(cupsOptions, QStringLiteral("page-ranges"), pageRange); setCupsOptions(printer, cupsOptions); } diff --git a/src/printsupport/kernel/qcups_p.h b/src/printsupport/kernel/qcups_p.h index 4b27632a60..a5af4bcbb0 100644 --- a/src/printsupport/kernel/qcups_p.h +++ b/src/printsupport/kernel/qcups_p.h @@ -142,6 +142,7 @@ public: static void setPagesPerSheetLayout(QPrinter *printer, const PagesPerSheet pagesPerSheet, const PagesPerSheetLayout pagesPerSheetLayout); static void setPageRange(QPrinter *printer, int pageFrom, int pageTo); + static void setPageRange(QPrinter *printer, const QString &pageRange); struct JobSheets { -- cgit v1.2.3