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

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(-)

Index: qtbase-opensource-src-5.9.4/src/printsupport/dialogs/qprintdialog_unix.cpp
===================================================================
--- qtbase-opensource-src-5.9.4.orig/src/printsupport/dialogs/qprintdialog_unix.cpp
+++ qtbase-opensource-src-5.9.4/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);
@@ -561,6 +564,87 @@ void QPrintDialogPrivate::selectPrinter(
             options.pageSetCombo->setEnabled(true);
 }
 
+#if QT_CONFIG(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(',');
+    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(), [](std::pair<int, int> it1, std::pair<int, int> 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<std::pair<int, int>> &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
@@ -605,6 +689,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
@@ -801,6 +895,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();
 }
Index: qtbase-opensource-src-5.9.4/src/printsupport/dialogs/qprintsettingsoutput.ui
===================================================================
--- qtbase-opensource-src-5.9.4.orig/src/printsupport/dialogs/qprintsettingsoutput.ui
+++ qtbase-opensource-src-5.9.4/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>
@@ -119,6 +146,27 @@
            </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">
              <string>Current Page</string>
@@ -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>
Index: qtbase-opensource-src-5.9.4/src/printsupport/kernel/qcups.cpp
===================================================================
--- qtbase-opensource-src-5.9.4.orig/src/printsupport/kernel/qcups.cpp
+++ qtbase-opensource-src-5.9.4/src/printsupport/kernel/qcups.cpp
@@ -254,8 +254,13 @@ void QCUPSSupport::setPagesPerSheetLayou
 
 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);
 }
 
Index: qtbase-opensource-src-5.9.4/src/printsupport/kernel/qcups_p.h
===================================================================
--- qtbase-opensource-src-5.9.4.orig/src/printsupport/kernel/qcups_p.h
+++ qtbase-opensource-src-5.9.4/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
     {
openSUSE Build Service is sponsored by