File 0015-CUPS-Dont-show-choices-that-conflict-with-the-printer-installed-options.patch of Package libqt5-qtbase.16540

From c45947aeefa1a83eda767edca4fd4c6f9404d3ff Mon Sep 17 00:00:00 2001
From: Albert Astals Cid <albert.astals.cid@kdab.com>
Date: Fri, 29 Dec 2017 15:18:52 +0100
Subject: [PATCH] CUPS: Don't show choices that conflict with the printer
 installed options

Some options only make sense if the printer has installed some extensions, e.g.
we should not shown "Staple" options if the Stapler addon is not installed,
so with this change we use ppdInstallableConflict to know whether an option
should be shown to the user or not.

Change-Id: I5733e1ac8b667c26b292aeafc90a10c155b751a4
Reviewed-by: Andy Shaw <andy.shaw@qt.io>
---
 src/plugins/printsupport/cups/qppdprintdevice.cpp | 15 +++++++-
 src/plugins/printsupport/cups/qppdprintdevice.h   |  1 +
 src/printsupport/dialogs/qprintdialog_unix.cpp    | 46 +++++++++++++++--------
 src/printsupport/kernel/qcups_p.h                 |  1 +
 src/printsupport/kernel/qplatformprintdevice.cpp  |  8 ++++
 src/printsupport/kernel/qplatformprintdevice.h    |  1 +
 src/printsupport/kernel/qprintdevice.cpp          |  5 +++
 src/printsupport/kernel/qprintdevice_p.h          |  1 +
 8 files changed, 60 insertions(+), 18 deletions(-)

diff --git a/src/plugins/printsupport/cups/qppdprintdevice.cpp b/src/plugins/printsupport/cups/qppdprintdevice.cpp
index 9c4b699..340b1a1 100644
--- a/src/plugins/printsupport/cups/qppdprintdevice.cpp
+++ b/src/plugins/printsupport/cups/qppdprintdevice.cpp
@@ -436,7 +436,7 @@ QVariant QPpdPrintDevice::property(QPrintDevice::PrintDevicePropertyKey key) con
     else if (key == PDPK_CupsJobHoldUntil)
         return printerOption(QStringLiteral("job-hold-until"));
 
-    return QVariant();
+    return QPlatformPrintDevice::property(key);
 }
 
 bool QPpdPrintDevice::setProperty(QPrintDevice::PrintDevicePropertyKey key, const QVariant &value)
@@ -449,7 +449,18 @@ bool QPpdPrintDevice::setProperty(QPrintDevice::PrintDevicePropertyKey key, cons
         }
     }
 
-    return false;
+    return QPlatformPrintDevice::setProperty(key, value);
+}
+
+bool QPpdPrintDevice::isFeatureAvailable(QPrintDevice::PrintDevicePropertyKey key, const QVariant &params) const
+{
+    if (key == PDPK_PpdChoiceIsInstallableConflict) {
+        const QStringList values = params.toStringList();
+        if (values.count() == 2)
+            return ppdInstallableConflict(m_ppd, values[0].toLatin1(), values[1].toLatin1());
+    }
+
+    return QPlatformPrintDevice::isFeatureAvailable(key, params);
 }
 
 #ifndef QT_NO_MIMETYPE
diff --git a/src/plugins/printsupport/cups/qppdprintdevice.h b/src/plugins/printsupport/cups/qppdprintdevice.h
index 2e4dd3a..9867083 100644
--- a/src/plugins/printsupport/cups/qppdprintdevice.h
+++ b/src/plugins/printsupport/cups/qppdprintdevice.h
@@ -91,6 +91,7 @@ public:
 
     QVariant property(QPrintDevice::PrintDevicePropertyKey key) const Q_DECL_OVERRIDE;
     bool setProperty(QPrintDevice::PrintDevicePropertyKey key, const QVariant &value) Q_DECL_OVERRIDE;
+    bool isFeatureAvailable(QPrintDevice::PrintDevicePropertyKey key, const QVariant &params) const Q_DECL_OVERRIDE;
 
 protected:
     void loadPageSizes() const Q_DECL_OVERRIDE;
diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp
index ab38c24..22d7dd1 100644
--- a/src/printsupport/dialogs/qprintdialog_unix.cpp
+++ b/src/printsupport/dialogs/qprintdialog_unix.cpp
@@ -271,6 +271,7 @@ public:
     {
     }
 
+    // These indices are related to ppd_option_t::choices not to childItems
     int selected;
     int originallySelected;
 };
@@ -1466,8 +1467,14 @@ void QPPDOptionsModel::parseOptions(QOptionTreeItem *parent)
     for (int i = 0; i < group->num_options; ++i) {
         if (!isBlacklistedOption(group->options[i].keyword)) {
             QOptionTreeItemOption *opt = new QOptionTreeItemOption(i, &group->options[i], parent);
-            parent->childItems.append(opt);
             parseChoices(opt);
+
+            // Don't show options that are actually not options at all
+            // because they don't give the user any choice
+            if (opt->childItems.count() > 1)
+                parent->childItems.append(opt);
+            else
+                delete opt;
         }
     }
 }
@@ -1477,15 +1484,18 @@ void QPPDOptionsModel::parseChoices(QOptionTreeItemOption *parent)
     const ppd_option_t *option = static_cast<const ppd_option_t*>(parent->ptr);
     bool marked = false;
     for (int i = 0; i < option->num_choices; ++i) {
-        QOptionTreeItem *choice = new QOptionTreeItem(QOptionTreeItem::Choice, i, &option->choices[i], parent);
-        if (static_cast<int>(option->choices[i].marked) == 1) {
-            parent->selected = i;
-            marked = true;
-        } else if (!marked && qstrcmp(option->choices[i].choice, option->defchoice) == 0) {
-            parent->selected = i;
+        const auto values = QStringList{} << QString::fromLatin1(option->keyword) << QString::fromLatin1(option->choices[i].choice);
+        if (!m_currentPrintDevice->isFeatureAvailable(PDPK_PpdChoiceIsInstallableConflict, values)) {
+            QOptionTreeItem *choice = new QOptionTreeItem(QOptionTreeItem::Choice, i, &option->choices[i], parent);
+            if (static_cast<int>(option->choices[i].marked) == 1) {
+                parent->selected = i;
+                marked = true;
+            } else if (!marked && qstrcmp(option->choices[i].choice, option->defchoice) == 0) {
+                parent->selected = i;
+            }
+            parent->originallySelected = parent->selected;
+            parent->childItems.append(choice);
         }
-        parent->originallySelected = parent->selected;
-        parent->childItems.append(choice);
     }
 }
 
@@ -1627,11 +1637,10 @@ void QPPDOptionsEditor::setEditorData(QWidget *editor, const QModelIndex &index)
     const QPPDOptionsModel *m = static_cast<const QPPDOptionsModel*>(index.model());
     for (auto *childItem : qAsConst(itm->childItems)) {
         const ppd_choice_t *choice = static_cast<const ppd_choice_t*>(childItem->ptr);
-        cb->addItem(m->cupsCodec()->toUnicode(choice->text));
+        cb->addItem(m->cupsCodec()->toUnicode(choice->text), childItem->index);
+        if (childItem->index == itm->selected)
+            cb->setCurrentIndex(cb->count() - 1);
     }
-
-    if (itm->selected > -1)
-        cb->setCurrentIndex(itm->selected);
 }
 
 void QPPDOptionsEditor::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
@@ -1639,15 +1648,20 @@ void QPPDOptionsEditor::setModelData(QWidget *editor, QAbstractItemModel *model,
     QComboBox *cb = static_cast<QComboBox*>(editor);
     QOptionTreeItemOption *itm = static_cast<QOptionTreeItemOption*>(index.internalPointer());
 
-    if (itm->selected == cb->currentIndex())
+    // We can't use cb->currentIndex() to know the index of the option in the choices[] array
+    // because some of them may not be present in the list because they conflict with the
+    // installable options so use the index passed on addItem
+    const int selectedChoiceIndex = cb->currentData().toInt();
+
+    if (itm->selected == selectedChoiceIndex || selectedChoiceIndex < 0)
         return;
 
     const ppd_option_t *opt = static_cast<const ppd_option_t*>(itm->ptr);
     QPPDOptionsModel *m = static_cast<QPPDOptionsModel*>(model);
 
-    const auto values = QStringList{} << QString::fromLatin1(opt->keyword) << QString::fromLatin1(opt->choices[cb->currentIndex()].choice);
+    const auto values = QStringList{} << QString::fromLatin1(opt->keyword) << QString::fromLatin1(opt->choices[selectedChoiceIndex].choice);
     m->currentPrintDevice()->setProperty(PDPK_PpdOption, values);
-    itm->selected = cb->currentIndex();
+    itm->selected = selectedChoiceIndex;
 
     m->emitConflictsChanged();
 }
diff --git a/src/printsupport/kernel/qcups_p.h b/src/printsupport/kernel/qcups_p.h
index 0afa7fa..da2b087 100644
--- a/src/printsupport/kernel/qcups_p.h
+++ b/src/printsupport/kernel/qcups_p.h
@@ -73,6 +73,7 @@ QT_BEGIN_NAMESPACE
 #define PDPK_CupsJobSheets    QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 3)
 #define PDPK_CupsJobBilling   QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 4)
 #define PDPK_CupsJobHoldUntil QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 5)
+#define PDPK_PpdChoiceIsInstallableConflict QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 6)
 
 class Q_PRINTSUPPORT_EXPORT QCUPSSupport
 {
diff --git a/src/printsupport/kernel/qplatformprintdevice.cpp b/src/printsupport/kernel/qplatformprintdevice.cpp
index 2f76156..8dba402 100644
--- a/src/printsupport/kernel/qplatformprintdevice.cpp
+++ b/src/printsupport/kernel/qplatformprintdevice.cpp
@@ -396,6 +396,14 @@ bool QPlatformPrintDevice::setProperty(QPrintDevice::PrintDevicePropertyKey key,
     return false;
 }
 
+bool QPlatformPrintDevice::isFeatureAvailable(QPrintDevice::PrintDevicePropertyKey key, const QVariant &params) const
+{
+    Q_UNUSED(key)
+    Q_UNUSED(params)
+
+    return false;
+}
+
 QList<QMimeType> QPlatformPrintDevice::supportedMimeTypes() const
 {
     if (!m_haveMimeTypes)
diff --git a/src/printsupport/kernel/qplatformprintdevice.h b/src/printsupport/kernel/qplatformprintdevice.h
index 8af7646..a988518 100644
--- a/src/printsupport/kernel/qplatformprintdevice.h
+++ b/src/printsupport/kernel/qplatformprintdevice.h
@@ -123,6 +123,7 @@ public:
 
     virtual QVariant property(QPrintDevice::PrintDevicePropertyKey key) const;
     virtual bool setProperty(QPrintDevice::PrintDevicePropertyKey key, const QVariant &value);
+    virtual bool isFeatureAvailable(QPrintDevice::PrintDevicePropertyKey key, const QVariant &params) const;
 
 #ifndef QT_NO_MIMETYPE
     virtual QList<QMimeType> supportedMimeTypes() const;
diff --git a/src/printsupport/kernel/qprintdevice.cpp b/src/printsupport/kernel/qprintdevice.cpp
index 2bc6906..50fc141 100644
--- a/src/printsupport/kernel/qprintdevice.cpp
+++ b/src/printsupport/kernel/qprintdevice.cpp
@@ -255,6 +255,11 @@ bool QPrintDevice::setProperty(PrintDevicePropertyKey key, const QVariant &value
     return isValid() ? d->setProperty(key, value) : false;
 }
 
+bool QPrintDevice::isFeatureAvailable(PrintDevicePropertyKey key, const QVariant &params) const
+{
+    return isValid() ? d->isFeatureAvailable(key, params) : false;
+}
+
 #ifndef QT_NO_MIMETYPE
 QList<QMimeType> QPrintDevice::supportedMimeTypes() const
 {
diff --git a/src/printsupport/kernel/qprintdevice_p.h b/src/printsupport/kernel/qprintdevice_p.h
index 3dff2e5..562ccd2 100644
--- a/src/printsupport/kernel/qprintdevice_p.h
+++ b/src/printsupport/kernel/qprintdevice_p.h
@@ -137,6 +137,7 @@ public:
 
     QVariant property(PrintDevicePropertyKey key) const;
     bool setProperty(PrintDevicePropertyKey key, const QVariant &value);
+    bool isFeatureAvailable(PrintDevicePropertyKey key, const QVariant &params) const;
 
 #ifndef QT_NO_MIMETYPE
     QList<QMimeType> supportedMimeTypes() const;
-- 
2.7.4
openSUSE Build Service is sponsored by