File 0014-CUPS-Enable-printing-arbitrary-pages-and-page-ranges.patch of Package libqt5-qtbase

From 608301d4c81ce65804a088aaebbd5433a56d69d7 Mon Sep 17 00:00:00 2001
From: Albert Astals Cid <albert.astals.cid@kdab.com>
Date: Thu, 28 Dec 2017 11:22:32 +0100
Subject: [PATCH] CUPS: Enable printing arbitrary pages and page ranges

Task-number: QTBUG-1311
Change-Id: I8e09def0e0d8c1404d3ee86845d98a30c23b6485
Reviewed-by: Andy Shaw <andy.shaw@qt.io>
---
 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,89 @@ void QPrintDialogPrivate::selectPrinter(const QPrinter::OutputFormat outputForma
             options.pageSetCombo->setEnabled(true);
 }
 
+#ifndef QT_NO_CUPS
+static std::vector<std::pair<int, int>> pageRangesFromString(const QString &pagesString) Q_DECL_NOTHROW
+{
+    std::vector<std::pair<int, int>> result;
+    const QStringList items = pagesString.split(',');
+    foreach (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(), [](std::pair<int, int> it1, std::pair<int, int> it2) { return it1.first < it2.first; });
+    int previousSecond = -1;
+    typedef std::pair<int, int> pair_of_ints;
+    foreach (pair_of_ints pair, result) {
+        if (pair.first <= previousSecond)
+            return {};
+
+        previousSecond = pair.second;
+    }
+
+    return result;
+}
+
+static QString stringFromPageRanges(const std::vector<std::pair<int, int>> &pageRanges) Q_DECL_NOTHROW
+{
+    QString result;
+    typedef std::pair<int, int> pair_of_ints;
+
+    foreach (pair_of_ints 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;
+
+    std::vector<std::pair<int, int>> 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()
     }
 
 #ifndef QT_NO_CUPS
+    if (options.pagesRadioButton->isChecked()) {
+        std::vector<std::pair<int, int>> 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);
+#ifndef QT_NO_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 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>426</width>
-    <height>187</height>
+    <width>432</width>
+    <height>251</height>
    </rect>
   </property>
   <property name="windowTitle">
    <string>Form</string>
   </property>
   <layout class="QHBoxLayout" name="horizontalLayout_2">
-   <property name="margin">
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
     <number>0</number>
    </property>
    <item>
@@ -42,7 +51,16 @@
           <property name="spacing">
            <number>4</number>
           </property>
-          <property name="margin">
+          <property name="leftMargin">
+           <number>6</number>
+          </property>
+          <property name="topMargin">
+           <number>6</number>
+          </property>
+          <property name="rightMargin">
+           <number>6</number>
+          </property>
+          <property name="bottomMargin">
            <number>6</number>
           </property>
           <item>
@@ -60,7 +78,16 @@
             <property name="spacing">
              <number>6</number>
             </property>
-            <property name="margin">
+            <property name="leftMargin">
+             <number>0</number>
+            </property>
+            <property name="topMargin">
+             <number>0</number>
+            </property>
+            <property name="rightMargin">
+             <number>0</number>
+            </property>
+            <property name="bottomMargin">
              <number>0</number>
             </property>
             <item>
@@ -118,6 +145,27 @@
             </item>
            </layout>
           </item>
+          <item>
+           <layout class="QHBoxLayout" name="pagesLayout">
+            <item>
+             <widget class="QRadioButton" name="pagesRadioButton">
+              <property name="text">
+               <string>Pages</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLineEdit" name="pagesLineEdit">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+              <property name="toolTip">
+               <string>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.</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
           <item>
            <widget class="QRadioButton" name="printCurrentPage">
             <property name="text">
@@ -361,12 +409,12 @@
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>76</x>
-     <y>59</y>
+     <x>89</x>
+     <y>113</y>
     </hint>
     <hint type="destinationlabel">
-     <x>122</x>
-     <y>57</y>
+     <x>182</x>
+     <y>113</y>
     </hint>
    </hints>
   </connection>
@@ -377,12 +425,28 @@
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>69</x>
-     <y>67</y>
+     <x>82</x>
+     <y>113</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>267</x>
+     <y>113</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>pagesRadioButton</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>pagesLineEdit</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>58</x>
+     <y>132</y>
     </hint>
     <hint type="destinationlabel">
-     <x>215</x>
-     <y>67</y>
+     <x>163</x>
+     <y>128</y>
     </hint>
    </hints>
   </connection>
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
     {
-- 
2.15.1

openSUSE Build Service is sponsored by