diff --git a/0001-Avoid-providing-bad-pixelDeltas-on-X11.patch b/0001-Avoid-providing-bad-pixelDeltas-on-X11.patch new file mode 100644 index 0000000..2d1f68a --- /dev/null +++ b/0001-Avoid-providing-bad-pixelDeltas-on-X11.patch @@ -0,0 +1,68 @@ +From d196036024697a75868c1f1626525710495ca428 Mon Sep 17 00:00:00 2001 +From: Allan Sandfeld Jensen +Date: Thu, 23 Nov 2017 14:25:04 +0100 +Subject: [PATCH] Avoid providing bad pixelDeltas on X11 + +With libinput we now get a hardcoded resolution that is unrelated to +the hardware. So avoid using that as a real pixel delta and document +pixel deltas as being driver specific and unreliable on X11. + +Task-number: QTBUG-59261 +Change-Id: I9fe86d80e7ccd290ed2e4091d7eafa52cb537d34 +Reviewed-by: David Edmundson +Reviewed-by: Marco Martin +Reviewed-by: Gatis Paeglis +--- + src/gui/kernel/qevent.cpp | 1 + + src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 14 ++++++++------ + 2 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp +index 06d52aa..c68f9af 100644 +--- a/src/gui/kernel/qevent.cpp ++++ b/src/gui/kernel/qevent.cpp +@@ -971,6 +971,7 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, + \li scrolling is about to begin, but the distance did not yet change (Qt::ScrollBegin), + \li or scrolling has ended and the distance did not change anymore (Qt::ScrollEnd). + \endlist ++ \note On X11 this value is driver specific and unreliable, use angleDelta() instead + */ + + /*! +diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +index d1d97af..94f543f 100644 +--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp ++++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +@@ -953,10 +953,12 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin + double delta = scrollingDevice.lastScrollPosition.y() - value; + scrollingDevice.lastScrollPosition.setY(value); + angleDelta.setY((delta / scrollingDevice.verticalIncrement) * 120); +- // We do not set "pixel" delta if it is only measured in ticks. +- if (scrollingDevice.verticalIncrement > 1) ++ // With most drivers the increment is 1 for wheels. ++ // For libinput it is hardcoded to a useless 15. ++ // For a proper touchpad driver it should be in the same order of magnitude as 120 ++ if (scrollingDevice.verticalIncrement > 15) + rawDelta.setY(delta); +- else if (scrollingDevice.verticalIncrement < -1) ++ else if (scrollingDevice.verticalIncrement < -15) + rawDelta.setY(-delta); + } + } +@@ -965,10 +967,10 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin + double delta = scrollingDevice.lastScrollPosition.x() - value; + scrollingDevice.lastScrollPosition.setX(value); + angleDelta.setX((delta / scrollingDevice.horizontalIncrement) * 120); +- // We do not set "pixel" delta if it is only measured in ticks. +- if (scrollingDevice.horizontalIncrement > 1) ++ // See comment under vertical ++ if (scrollingDevice.horizontalIncrement > 15) + rawDelta.setX(delta); +- else if (scrollingDevice.horizontalIncrement < -1) ++ else if (scrollingDevice.horizontalIncrement < -15) + rawDelta.setX(-delta); + } + } +-- +2.7.4 + diff --git a/0001-QSimpleDrag-Fix-mouse-release-coords-for-delayed-eve.patch b/0001-QSimpleDrag-Fix-mouse-release-coords-for-delayed-eve.patch new file mode 100644 index 0000000..ecc9616 --- /dev/null +++ b/0001-QSimpleDrag-Fix-mouse-release-coords-for-delayed-eve.patch @@ -0,0 +1,170 @@ +From 4a7771f206d4b29be549d3827c36a46679d90de6 Mon Sep 17 00:00:00 2001 +From: Eike Hein +Date: Sun, 7 Jan 2018 13:02:01 +0900 +Subject: [PATCH] QSimpleDrag: Fix mouse release coords for delayed event + transmission + +On platforms such as XCB, the drag cursor pixmap is shown via a window +(a QShapedPixmapWindow) under the cursor. + +The mouse button release event at the end of the drag is received in +this QXcbWindow, but intercepted by an event filter that QSimpleDrag +installs on the QApplication. It then resends it unmodified(!) after +the drag has ended and the drag pixmap window destroyed, causing it to +be delivered to the new top-level window. + +The local coordinates in the unmodified QMouseEvent are local to the +drag pixmap window and don't match the window it is delayed-transmitted +to. + +This ends up having fatal, user-visible effects particularly in Qt +Quick: QQuickWindow synthesizes a hover event once per frame using +the last received mouse coordinates, here: the release posted by +QSimpleDrag. This is done to update the hover event state for items +under the cursor when the mouse hasn't moved (e.g. QQuickMouseArea:: +containsMouse). The bogus event coordinates in the release event then +usually end up causing an item near the top-left of the QQuickWindow +to assume it is hovered (because drag pixmap windows tend to be small), +even when the mouse cursor is actually far away from it at the end of +the drag. + +This shows up e.g. in the Plasma 5 desktop, where dragging an icon +on the desktop will cause the icon at the top-left of the screen (if +any) to switch to hovered state, as the release coordinates on the +drag pixmap window (showing a dragged icon) fall into the geometry +of the top-left icon. + +QSimpleDrag contains a topLevelAt() function to find the top-level +window under the global cursor coordinates that is not the drag +pixmap window. This is used by the drop event delivery code. + +This patch uses this function to find the relevant top-level window, +then asks it to map the global cusor coordinates to its local +coordinate system, then synthesizes a new QMouseEvent with local +coordinates computed in this fashion. As a result the window now +gets a release event with coordinates that make sense and are +correct. + +Task-number: QTBUG-66103 +Change-Id: I04ebe6ccd4a991fdd4b540ff0227973ea8896a9d +Reviewed-by: Eike Hein +Reviewed-by: Shawn Rutledge +--- + src/gui/kernel/qsimpledrag.cpp | 32 +++++++++++++++++++++++++++----- + src/gui/kernel/qsimpledrag_p.h | 6 +++--- + 2 files changed, 30 insertions(+), 8 deletions(-) + +diff --git a/src/gui/kernel/qsimpledrag.cpp b/src/gui/kernel/qsimpledrag.cpp +index a1e25dc53c..87d3ba5915 100644 +--- a/src/gui/kernel/qsimpledrag.cpp ++++ b/src/gui/kernel/qsimpledrag.cpp +@@ -58,6 +58,7 @@ + + #include + #include ++#include + + #include + #include +@@ -69,6 +70,8 @@ QT_BEGIN_NAMESPACE + + #ifndef QT_NO_DRAGANDDROP + ++Q_LOGGING_CATEGORY(lcDnd, "qt.gui.dnd") ++ + static QWindow* topLevelAt(const QPoint &pos) + { + QWindowList list = QGuiApplication::topLevelWindows(); +@@ -94,10 +97,10 @@ static QWindow* topLevelAt(const QPoint &pos) + */ + + QBasicDrag::QBasicDrag() : +- m_restoreCursor(false), m_eventLoop(0), ++ m_current_window(nullptr), m_restoreCursor(false), m_eventLoop(nullptr), + m_executed_drop_action(Qt::IgnoreAction), m_can_drop(false), +- m_drag(0), m_drag_icon_window(0), m_useCompositing(true), +- m_screen(Q_NULLPTR) ++ m_drag(nullptr), m_drag_icon_window(nullptr), m_useCompositing(true), ++ m_screen(nullptr) + { + } + +@@ -161,6 +164,7 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e) + return true; // Eat all mouse move events + } + case QEvent::MouseButtonRelease: ++ { + disableEventFilter(); + if (canDrop()) { + QPoint nativePosition = getNativeMousePos(e, m_drag_icon_window); +@@ -169,8 +173,25 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e) + cancel(); + } + exitDndEventLoop(); +- QCoreApplication::postEvent(o, new QMouseEvent(*static_cast(e))); ++ ++ // If a QShapedPixmapWindow (drag feedback) is being dragged along, the ++ // mouse event's localPos() will be relative to that, which is useless. ++ // We want a position relative to the window where the drag ends, if possible (?). ++ // If there is no such window (belonging to this Qt application), ++ // make the event relative to the window where the drag started. (QTBUG-66103) ++ const QMouseEvent *release = static_cast(e); ++ const QWindow *releaseWindow = topLevelAt(release->globalPos()); ++ qCDebug(lcDnd) << "mouse released over" << releaseWindow << "after drag from" << m_current_window << "globalPos" << release->globalPos(); ++ if (!releaseWindow) ++ releaseWindow = m_current_window; ++ QPoint releaseWindowPos = (releaseWindow ? releaseWindow->mapFromGlobal(release->globalPos()) : release->globalPos()); ++ QMouseEvent *newRelease = new QMouseEvent(release->type(), ++ releaseWindowPos, releaseWindowPos, release->screenPos(), ++ release->button(), release->buttons(), ++ release->modifiers(), release->source()); ++ QCoreApplication::postEvent(o, newRelease); + return true; // defer mouse release events until drag event loop has returned ++ } + case QEvent::MouseButtonDblClick: + case QEvent::Wheel: + return true; +@@ -349,7 +370,7 @@ static inline QPoint fromNativeGlobalPixels(const QPoint &point) + into account. + */ + +-QSimpleDrag::QSimpleDrag() : m_current_window(0) ++QSimpleDrag::QSimpleDrag() + { + } + +@@ -373,6 +394,7 @@ void QSimpleDrag::startDrag() + updateCursor(Qt::IgnoreAction); + } + setExecutedDropAction(Qt::IgnoreAction); ++ qCDebug(lcDnd) << "drag began from" << m_current_window<< "cursor pos" << QCursor::pos() << "can drop?" << canDrop(); + } + + void QSimpleDrag::cancel() +diff --git a/src/gui/kernel/qsimpledrag_p.h b/src/gui/kernel/qsimpledrag_p.h +index 0b8a0bc703..bbd7f7f4bb 100644 +--- a/src/gui/kernel/qsimpledrag_p.h ++++ b/src/gui/kernel/qsimpledrag_p.h +@@ -105,6 +105,9 @@ protected: + + QDrag *drag() const { return m_drag; } + ++protected: ++ QWindow *m_current_window; ++ + private: + void enableEventFilter(); + void disableEventFilter(); +@@ -132,9 +135,6 @@ protected: + virtual void cancel() Q_DECL_OVERRIDE; + virtual void move(const QPoint &globalPos) Q_DECL_OVERRIDE; + virtual void drop(const QPoint &globalPos) Q_DECL_OVERRIDE; +- +-private: +- QWindow *m_current_window; + }; + + #endif // QT_NO_DRAGANDDROP +-- +2.16.1 + diff --git a/0002-CUPS-Use-default-cups-job-priority-instead-of-50.patch b/0002-CUPS-Use-default-cups-job-priority-instead-of-50.patch new file mode 100644 index 0000000..5696348 --- /dev/null +++ b/0002-CUPS-Use-default-cups-job-priority-instead-of-50.patch @@ -0,0 +1,137 @@ +From ad77a2447e8cc828dadd268c72428556e3cc8a84 Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +Date: Wed, 6 Dec 2017 10:19:13 +0100 +Subject: [PATCH 1/1] CUPS: Use default cups job-priority instead of 50 + +This also reads the job-priority from lpoptions if set there for the particular printer + +Change-Id: I75d983c377d2135a0b0d3e028829a7384a5e1897 +Reviewed-by: Laurent Montel +Reviewed-by: Frederik Gladhorn +--- + src/plugins/printsupport/cups/qppdprintdevice.cpp | 2 ++ + src/printsupport/dialogs/qprintdialog_unix.cpp | 2 +- + src/printsupport/kernel/qcups_p.h | 5 +++-- + src/printsupport/widgets/qcupsjobwidget.cpp | 20 +++++++++++++++++--- + src/printsupport/widgets/qcupsjobwidget_p.h | 4 +++- + 5 files changed, 26 insertions(+), 7 deletions(-) + +diff --git a/src/plugins/printsupport/cups/qppdprintdevice.cpp b/src/plugins/printsupport/cups/qppdprintdevice.cpp +index 021d040..56976a6 100644 +--- a/src/plugins/printsupport/cups/qppdprintdevice.cpp ++++ b/src/plugins/printsupport/cups/qppdprintdevice.cpp +@@ -427,6 +427,8 @@ QVariant QPpdPrintDevice::property(QPrintDevice::PrintDevicePropertyKey key) con + { + if (key == PDPK_PpdFile) + return QVariant::fromValue(m_ppd); ++ else if (key == PDPK_CupsJobPriority) ++ return printerOption(QStringLiteral("job-priority")); + + return QVariant(); + } +diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp +index 9ad9fa3..020894c 100644 +--- a/src/printsupport/dialogs/qprintdialog_unix.cpp ++++ b/src/printsupport/dialogs/qprintdialog_unix.cpp +@@ -333,7 +333,7 @@ QPrintPropertiesDialog::QPrintPropertiesDialog(QPrinter *printer, QPrintDevice * + widget.pageSetup->setPrinter(printer, outputFormat, printerName); + + #if QT_CONFIG(cupsjobwidget) +- m_jobOptions = new QCupsJobWidget(printer); ++ m_jobOptions = new QCupsJobWidget(printer, currentPrintDevice); + widget.tabs->insertTab(1, m_jobOptions, tr("Job Options")); + #endif + +diff --git a/src/printsupport/kernel/qcups_p.h b/src/printsupport/kernel/qcups_p.h +index b67390c..3abccf2 100644 +--- a/src/printsupport/kernel/qcups_p.h ++++ b/src/printsupport/kernel/qcups_p.h +@@ -67,8 +67,9 @@ QT_BEGIN_NAMESPACE + // removed from the dialogs. + #define PPK_CupsOptions QPrintEngine::PrintEnginePropertyKey(0xfe00) + +-#define PDPK_PpdFile QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase) +-#define PDPK_PpdOption QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 1) ++#define PDPK_PpdFile QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase) ++#define PDPK_PpdOption QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 1) ++#define PDPK_CupsJobPriority QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 2) + + class Q_PRINTSUPPORT_EXPORT QCUPSSupport + { +diff --git a/src/printsupport/widgets/qcupsjobwidget.cpp b/src/printsupport/widgets/qcupsjobwidget.cpp +index 8fb07c8..f21e229 100644 +--- a/src/printsupport/widgets/qcupsjobwidget.cpp ++++ b/src/printsupport/widgets/qcupsjobwidget.cpp +@@ -52,6 +52,8 @@ + #include + #include + ++#include ++ + QT_BEGIN_NAMESPACE + + /*! +@@ -64,9 +66,10 @@ QT_BEGIN_NAMESPACE + \inmodule QtPrintSupport + */ + +-QCupsJobWidget::QCupsJobWidget(QPrinter *printer, QWidget *parent) ++QCupsJobWidget::QCupsJobWidget(QPrinter *printer, QPrintDevice *printDevice, QWidget *parent) + : QWidget(parent), +- m_printer(printer) ++ m_printer(printer), ++ m_printDevice(printDevice) + { + m_ui.setupUi(this); + //set all the default values +@@ -151,7 +154,18 @@ QString QCupsJobWidget::jobBilling() const + + void QCupsJobWidget::initJobPriority() + { +- setJobPriority(50); ++ int priority = -1; ++ if (m_printDevice) { ++ bool ok; ++ priority = m_printDevice->property(PDPK_CupsJobPriority).toInt(&ok); ++ if (!ok) ++ priority = -1; ++ } ++ ++ if (priority < 0 || priority > 100) ++ priority = 50; ++ ++ setJobPriority(priority); + } + + void QCupsJobWidget::setJobPriority(int jobPriority) +diff --git a/src/printsupport/widgets/qcupsjobwidget_p.h b/src/printsupport/widgets/qcupsjobwidget_p.h +index 2aca6bc..dcec27a 100644 +--- a/src/printsupport/widgets/qcupsjobwidget_p.h ++++ b/src/printsupport/widgets/qcupsjobwidget_p.h +@@ -65,13 +65,14 @@ QT_BEGIN_NAMESPACE + class QString; + class QTime; + class QPrinter; ++class QPrintDevice; + + class QCupsJobWidget : public QWidget + { + Q_OBJECT + + public: +- explicit QCupsJobWidget(QPrinter *printer, QWidget *parent = nullptr); ++ explicit QCupsJobWidget(QPrinter *printer, QPrintDevice *printDevice, QWidget *parent = nullptr); + ~QCupsJobWidget(); + void setupPrinter(); + +@@ -102,6 +103,7 @@ private: + void initBannerPages(); + + QPrinter *m_printer; ++ QPrintDevice *m_printDevice; + Ui::QCupsJobWidget m_ui; + + Q_DISABLE_COPY(QCupsJobWidget) +-- +2.7.4 + diff --git a/0003-QPageSetupWidget-setPrinter-Use-printdevice-default-paper-size.patch b/0003-QPageSetupWidget-setPrinter-Use-printdevice-default-paper-size.patch new file mode 100644 index 0000000..4470459 --- /dev/null +++ b/0003-QPageSetupWidget-setPrinter-Use-printdevice-default-paper-size.patch @@ -0,0 +1,86 @@ +From ff67dedaaff2dc68571ca9c8c6c6eeaaf084eae4 Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +Date: Wed, 6 Dec 2017 15:27:05 +0100 +Subject: [PATCH 1/1] QPageSetupWidget::setPrinter: Use printdevice default + paper size + +This means that actually the paper size set on system settings (or lpoptions) is used instead of A4 + +Change-Id: I2dd86fd9ba210a335773430328b0ba2d3343395f +Reviewed-by: Frederik Gladhorn +--- + src/printsupport/dialogs/qpagesetupdialog_unix.cpp | 9 +++++++-- + src/printsupport/dialogs/qpagesetupdialog_unix_p.h | 4 +++- + src/printsupport/dialogs/qprintdialog_unix.cpp | 2 +- + 3 files changed, 11 insertions(+), 4 deletions(-) + +diff --git a/src/printsupport/dialogs/qpagesetupdialog_unix.cpp b/src/printsupport/dialogs/qpagesetupdialog_unix.cpp +index 49c0184..6f3bb0d 100644 +--- a/src/printsupport/dialogs/qpagesetupdialog_unix.cpp ++++ b/src/printsupport/dialogs/qpagesetupdialog_unix.cpp +@@ -210,7 +210,7 @@ void QUnixPageSetupDialogPrivate::init() + Q_Q(QPageSetupDialog); + + widget = new QPageSetupWidget(q); +- widget->setPrinter(printer, printer->outputFormat(), printer->printerName()); ++ widget->setPrinter(printer, nullptr, printer->outputFormat(), printer->printerName()); + + QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok + | QDialogButtonBox::Cancel, +@@ -371,12 +371,17 @@ void QPageSetupWidget::initPageSizes() + + // Set the dialog to use the given QPrinter + // Usually only called on first creation +-void QPageSetupWidget::setPrinter(QPrinter *printer, QPrinter::OutputFormat outputFormat, const QString &printerName) ++void QPageSetupWidget::setPrinter(QPrinter *printer, QPrintDevice *printDevice, ++ QPrinter::OutputFormat outputFormat, const QString &printerName) + { + m_printer = printer; + + // Initialize the layout to the current QPrinter layout + m_pageLayout = m_printer->pageLayout(); ++ ++ if (printDevice) ++ m_pageLayout.setPageSize(printDevice->defaultPageSize()); ++ + // Assume if margins are Points then is by default, so set to locale default units + if (m_pageLayout.units() == QPageLayout::Point) { + if (QLocale().measurementSystem() == QLocale::MetricSystem) +diff --git a/src/printsupport/dialogs/qpagesetupdialog_unix_p.h b/src/printsupport/dialogs/qpagesetupdialog_unix_p.h +index 44aca80..574569d 100644 +--- a/src/printsupport/dialogs/qpagesetupdialog_unix_p.h ++++ b/src/printsupport/dialogs/qpagesetupdialog_unix_p.h +@@ -64,6 +64,7 @@ QT_REQUIRE_CONFIG(printdialog); + QT_BEGIN_NAMESPACE + + class QPrinter; ++class QPrintDevice; + class QPagePreview; + + class QPageSetupWidget : public QWidget { +@@ -71,7 +72,8 @@ class QPageSetupWidget : public QWidget { + explicit QPageSetupWidget(QWidget *parent = 0); + explicit QPageSetupWidget(QPrinter *printer, QWidget *parent = 0); + +- void setPrinter(QPrinter *printer, QPrinter::OutputFormat outputFormat, const QString &printerName); ++ void setPrinter(QPrinter *printer, QPrintDevice *printDevice, ++ QPrinter::OutputFormat outputFormat, const QString &printerName); + void setupPrinter() const; + + private slots: +diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp +index 020894c..22076bf 100644 +--- a/src/printsupport/dialogs/qprintdialog_unix.cpp ++++ b/src/printsupport/dialogs/qprintdialog_unix.cpp +@@ -330,7 +330,7 @@ QPrintPropertiesDialog::QPrintPropertiesDialog(QPrinter *printer, QPrintDevice * + connect(m_buttons->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(accept())); + connect(m_buttons->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(reject())); + +- widget.pageSetup->setPrinter(printer, outputFormat, printerName); ++ widget.pageSetup->setPrinter(printer, currentPrintDevice, outputFormat, printerName); + + #if QT_CONFIG(cupsjobwidget) + m_jobOptions = new QCupsJobWidget(printer, currentPrintDevice); +-- +2.7.4 + diff --git a/0001-Fix-custom-page-size-handling-in-the-Unix-print-dial.patch b/0004-Fix-custom-page-size-handling-in-the-Unix-print-dial.patch similarity index 100% rename from 0001-Fix-custom-page-size-handling-in-the-Unix-print-dial.patch rename to 0004-Fix-custom-page-size-handling-in-the-Unix-print-dial.patch diff --git a/0005-CUPS-Refactor-the-code-a-bit.patch b/0005-CUPS-Refactor-the-code-a-bit.patch new file mode 100644 index 0000000..880990a --- /dev/null +++ b/0005-CUPS-Refactor-the-code-a-bit.patch @@ -0,0 +1,136 @@ +From d7330140190686f805be9fcd1ac968e3768f0754 Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +Date: Thu, 21 Dec 2017 16:27:02 +0100 +Subject: [PATCH 1/1] CUPS: Refactor the code a bit + +Move the selected and selDescription members to a subclass of QOptionTreeItem +since it's only ever used for Option type nodes of the tree + +Change-Id: Ic99841c4e04a3afcff0950f72abf12977850f6d3 +Reviewed-by: Michael Weghorn +Reviewed-by: Renato Araujo Oliveira Filho +Reviewed-by: Frederik Gladhorn +--- + src/printsupport/dialogs/qprintdialog_unix.cpp | 44 ++++++++++++++++---------- + 1 file changed, 28 insertions(+), 16 deletions(-) + +diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp +index 22076bf..6a7e679 100644 +--- a/src/printsupport/dialogs/qprintdialog_unix.cpp ++++ b/src/printsupport/dialogs/qprintdialog_unix.cpp +@@ -247,8 +247,6 @@ public: + index(i), + ptr(p), + description(desc), +- selected(-1), +- selDescription(nullptr), + parentItem(pi) {} + + ~QOptionTreeItem() { +@@ -259,12 +257,22 @@ public: + int index; + const void *ptr; + const char *description; +- int selected; +- const char *selDescription; + QOptionTreeItem *parentItem; + QList childItems; + }; + ++class QOptionTreeItemOption : public QOptionTreeItem ++{ ++public: ++ QOptionTreeItemOption (int i, const void *p, const char *desc, QOptionTreeItem *pi) ++ : QOptionTreeItem(Option, i, p, desc, pi) ++ { ++ } ++ ++ int selected; ++ const char *selDescription; ++}; ++ + class QPPDOptionsModel : public QAbstractItemModel + { + Q_OBJECT +@@ -285,7 +293,7 @@ public: + QOptionTreeItem *rootItem; + void parseGroups(QOptionTreeItem *parent); + void parseOptions(QOptionTreeItem *parent); +- void parseChoices(QOptionTreeItem *parent); ++ void parseChoices(QOptionTreeItemOption *parent); + }; + + class QPPDOptionsEditor : public QStyledItemDelegate +@@ -387,10 +395,11 @@ void QPrintPropertiesDialog::setCupsOptionsFromItems(QOptionTreeItem *parent) co + { + for (QOptionTreeItem *itm : qAsConst(parent->childItems)) { + if (itm->type == QOptionTreeItem::Option) { ++ QOptionTreeItemOption *itmOption = static_cast(itm); + const ppd_option_t *opt = static_cast(itm->ptr); +- if (qstrcmp(opt->defchoice, opt->choices[itm->selected].choice) != 0) { ++ if (qstrcmp(opt->defchoice, opt->choices[itmOption->selected].choice) != 0) { + QStringList cupsOptions = QCUPSSupport::cupsOptionsList(m_printer); +- QCUPSSupport::setCupsOption(cupsOptions, QString::fromLatin1(opt->keyword), QString::fromLatin1(opt->choices[itm->selected].choice)); ++ QCUPSSupport::setCupsOption(cupsOptions, QString::fromLatin1(opt->keyword), QString::fromLatin1(opt->choices[itmOption->selected].choice)); + QCUPSSupport::setCupsOptions(m_printer, cupsOptions); + } + } else { +@@ -1153,12 +1162,15 @@ QVariant QPPDOptionsModel::data(const QModelIndex &index, int role) const + break; + + case Qt::DisplayRole: { +- if (index.column() == 0) ++ if (index.column() == 0) { + return cupsCodec->toUnicode(itm->description); +- else if (itm->type == QOptionTreeItem::Option && itm->selected > -1) +- return cupsCodec->toUnicode(itm->selDescription); +- else +- return QVariant(); ++ } else if (itm->type == QOptionTreeItem::Option) { ++ QOptionTreeItemOption *itmOption = static_cast(itm); ++ if (itmOption->selected > -1) ++ return cupsCodec->toUnicode(itmOption->selDescription); ++ } ++ ++ return QVariant(); + } + break; + +@@ -1240,14 +1252,14 @@ void QPPDOptionsModel::parseOptions(QOptionTreeItem *parent) + const ppd_group_t *group = static_cast(parent->ptr); + for (int i = 0; i < group->num_options; ++i) { + if (!isBlacklistedOption(group->options[i].keyword)) { +- QOptionTreeItem *opt = new QOptionTreeItem(QOptionTreeItem::Option, i, &group->options[i], group->options[i].text, parent); ++ QOptionTreeItemOption *opt = new QOptionTreeItemOption(i, &group->options[i], group->options[i].text, parent); + parent->childItems.append(opt); + parseChoices(opt); + } + } + } + +-void QPPDOptionsModel::parseChoices(QOptionTreeItem *parent) ++void QPPDOptionsModel::parseChoices(QOptionTreeItemOption *parent) + { + const ppd_option_t *option = static_cast(parent->ptr); + bool marked = false; +@@ -1307,7 +1319,7 @@ void QPPDOptionsEditor::setEditorData(QWidget *editor, const QModelIndex &index) + return; + + QComboBox *cb = static_cast(editor); +- QOptionTreeItem *itm = static_cast(index.internalPointer()); ++ QOptionTreeItemOption *itm = static_cast(index.internalPointer()); + + if (itm->selected == -1) + cb->addItem(QString()); +@@ -1323,7 +1335,7 @@ void QPPDOptionsEditor::setEditorData(QWidget *editor, const QModelIndex &index) + void QPPDOptionsEditor::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const + { + QComboBox *cb = static_cast(editor); +- QOptionTreeItem *itm = static_cast(index.internalPointer()); ++ QOptionTreeItemOption *itm = static_cast(index.internalPointer()); + + if (itm->selected == cb->currentIndex()) + return; +-- +2.7.4 + diff --git a/0006-Refactor-QPPDOptionsModel-a-bit.patch b/0006-Refactor-QPPDOptionsModel-a-bit.patch new file mode 100644 index 0000000..9056193 --- /dev/null +++ b/0006-Refactor-QPPDOptionsModel-a-bit.patch @@ -0,0 +1,211 @@ +From 030d815eb8c5b6506178141da391594482c2e733 Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +Date: Thu, 28 Dec 2017 14:46:32 +0100 +Subject: [PATCH] Refactor QPPDOptionsModel a bit + +Make the members private and add getters +Make some other functions also private +Move setCupsOptionsFromItems from QPrintPropertiesDialog to QPPDOptionsModel + +Change-Id: Ibb555a6e6be53550f30c159c3ad611d55e2a767a +Reviewed-by: Kevin Ottens +Reviewed-by: Frederik Gladhorn +--- + src/printsupport/dialogs/qprintdialog_unix.cpp | 95 ++++++++++++++++---------- + 1 file changed, 59 insertions(+), 36 deletions(-) + +diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp +index 63d23cc..a9745d7 100644 +--- a/src/printsupport/dialogs/qprintdialog_unix.cpp ++++ b/src/printsupport/dialogs/qprintdialog_unix.cpp +@@ -288,12 +288,21 @@ public: + Qt::ItemFlags flags(const QModelIndex &index) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override; + +- QPrintDevice *m_currentPrintDevice; +- QTextCodec *cupsCodec; +- QOptionTreeItem *rootItem; ++ void setCupsOptionsFromItems(QPrinter *printer) const; ++ ++ QPrintDevice *currentPrintDevice() const; ++ QTextCodec *cupsCodec() const; ++ ++private: + void parseGroups(QOptionTreeItem *parent); + void parseOptions(QOptionTreeItem *parent); + void parseChoices(QOptionTreeItemOption *parent); ++ ++ void setCupsOptionsFromItems(QPrinter *printer, QOptionTreeItem *parent) const; ++ ++ QPrintDevice *m_currentPrintDevice; ++ QTextCodec *m_cupsCodec; ++ QOptionTreeItem *m_rootItem; + }; + + class QPPDOptionsEditor : public QStyledItemDelegate +@@ -380,7 +389,7 @@ void QPrintPropertiesDialog::setupPrinter() const + #endif + + #if QT_CONFIG(cups) +- setCupsOptionsFromItems(m_cupsOptionsModel->rootItem); ++ m_cupsOptionsModel->setCupsOptionsFromItems(m_printer); + #endif + } + +@@ -390,25 +399,6 @@ void QPrintPropertiesDialog::showEvent(QShowEvent *event) + QDialog::showEvent(event); + } + +-#if QT_CONFIG(cups) +-void QPrintPropertiesDialog::setCupsOptionsFromItems(QOptionTreeItem *parent) const +-{ +- for (QOptionTreeItem *itm : qAsConst(parent->childItems)) { +- if (itm->type == QOptionTreeItem::Option) { +- QOptionTreeItemOption *itmOption = static_cast(itm); +- const ppd_option_t *opt = static_cast(itm->ptr); +- if (qstrcmp(opt->defchoice, opt->choices[itmOption->selected].choice) != 0) { +- QStringList cupsOptions = QCUPSSupport::cupsOptionsList(m_printer); +- QCUPSSupport::setCupsOption(cupsOptions, QString::fromLatin1(opt->keyword), QString::fromLatin1(opt->choices[itmOption->selected].choice)); +- QCUPSSupport::setCupsOptions(m_printer, cupsOptions); +- } +- } else { +- setCupsOptionsFromItems(itm); +- } +- } +-} +-#endif +- + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + +@@ -1107,22 +1097,23 @@ void QUnixPrintWidget::updatePrinter() + QPPDOptionsModel::QPPDOptionsModel(QPrintDevice *currentPrintDevice, QObject *parent) + : QAbstractItemModel(parent) + , m_currentPrintDevice(currentPrintDevice) ++ , m_cupsCodec(nullptr) + { + ppd_file_t *ppd = m_currentPrintDevice->property(PDPK_PpdFile).value(); +- rootItem = new QOptionTreeItem(QOptionTreeItem::Root, 0, ppd, "Root Item", 0); ++ m_rootItem = new QOptionTreeItem(QOptionTreeItem::Root, 0, ppd, "Root Item", 0); + + if (ppd) { +- cupsCodec = QTextCodec::codecForName(ppd->lang_encoding); ++ m_cupsCodec = QTextCodec::codecForName(ppd->lang_encoding); + for (int i = 0; i < ppd->num_groups; ++i) { +- QOptionTreeItem *group = new QOptionTreeItem(QOptionTreeItem::Group, i, &ppd->groups[i], ppd->groups[i].text, rootItem); +- rootItem->childItems.append(group); ++ QOptionTreeItem *group = new QOptionTreeItem(QOptionTreeItem::Group, i, &ppd->groups[i], ppd->groups[i].text, m_rootItem); ++ m_rootItem->childItems.append(group); + parseGroups(group); // parse possible subgroups + parseOptions(group); // parse options + } + } + +- if (!cupsCodec) +- cupsCodec = QTextCodec::codecForLocale(); ++ if (!m_cupsCodec) ++ m_cupsCodec = QTextCodec::codecForLocale(); + } + + int QPPDOptionsModel::columnCount(const QModelIndex &) const +@@ -1134,7 +1125,7 @@ int QPPDOptionsModel::rowCount(const QModelIndex &parent) const + { + QOptionTreeItem *itm; + if (!parent.isValid()) +- itm = rootItem; ++ itm = m_rootItem; + else + itm = static_cast(parent.internalPointer()); + +@@ -1164,11 +1155,11 @@ QVariant QPPDOptionsModel::data(const QModelIndex &index, int role) const + + case Qt::DisplayRole: { + if (index.column() == 0) { +- return cupsCodec->toUnicode(itm->description); ++ return m_cupsCodec->toUnicode(itm->description); + } else if (itm->type == QOptionTreeItem::Option) { + QOptionTreeItemOption *itmOption = static_cast(itm); + if (itmOption->selected > -1) +- return cupsCodec->toUnicode(itmOption->selDescription); ++ return m_cupsCodec->toUnicode(itmOption->selDescription); + } + + return QVariant(); +@@ -1184,7 +1175,7 @@ QModelIndex QPPDOptionsModel::index(int row, int column, const QModelIndex &pare + { + QOptionTreeItem *itm; + if (!parent.isValid()) +- itm = rootItem; ++ itm = m_rootItem; + else + itm = static_cast(parent.internalPointer()); + +@@ -1199,7 +1190,7 @@ QModelIndex QPPDOptionsModel::parent(const QModelIndex &index) const + + QOptionTreeItem *itm = static_cast(index.internalPointer()); + +- if (itm->parentItem && itm->parentItem != rootItem) ++ if (itm->parentItem && itm->parentItem != m_rootItem) + return createIndex(itm->parentItem->index, 0, itm->parentItem); + + return QModelIndex(); +@@ -1216,6 +1207,38 @@ Qt::ItemFlags QPPDOptionsModel::flags(const QModelIndex &index) const + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + } + ++QPrintDevice *QPPDOptionsModel::currentPrintDevice() const ++{ ++ return m_currentPrintDevice; ++} ++ ++QTextCodec *QPPDOptionsModel::cupsCodec() const ++{ ++ return m_cupsCodec; ++} ++ ++void QPPDOptionsModel::setCupsOptionsFromItems(QPrinter *printer) const ++{ ++ setCupsOptionsFromItems(printer, m_rootItem); ++} ++ ++void QPPDOptionsModel::setCupsOptionsFromItems(QPrinter *printer, QOptionTreeItem *parent) const ++{ ++ for (QOptionTreeItem *itm : qAsConst(parent->childItems)) { ++ if (itm->type == QOptionTreeItem::Option) { ++ QOptionTreeItemOption *itmOption = static_cast(itm); ++ const ppd_option_t *opt = static_cast(itm->ptr); ++ if (qstrcmp(opt->defchoice, opt->choices[itmOption->selected].choice) != 0) { ++ QStringList cupsOptions = QCUPSSupport::cupsOptionsList(printer); ++ QCUPSSupport::setCupsOption(cupsOptions, QString::fromLatin1(opt->keyword), QString::fromLatin1(opt->choices[itmOption->selected].choice)); ++ QCUPSSupport::setCupsOptions(printer, cupsOptions); ++ } ++ } else { ++ setCupsOptionsFromItems(printer, itm); ++ } ++ } ++} ++ + void QPPDOptionsModel::parseGroups(QOptionTreeItem *parent) + { + const ppd_group_t *group = static_cast(parent->ptr); +@@ -1327,7 +1350,7 @@ void QPPDOptionsEditor::setEditorData(QWidget *editor, const QModelIndex &index) + + const QPPDOptionsModel *m = static_cast(index.model()); + for (auto *childItem : qAsConst(itm->childItems)) +- cb->addItem(m->cupsCodec->toUnicode(childItem->description)); ++ cb->addItem(m->cupsCodec()->toUnicode(childItem->description)); + + if (itm->selected > -1) + cb->setCurrentIndex(itm->selected); +@@ -1345,7 +1368,7 @@ void QPPDOptionsEditor::setModelData(QWidget *editor, QAbstractItemModel *model, + QPPDOptionsModel *m = static_cast(model); + + const auto values = QStringList{} << QString::fromLatin1(opt->keyword) << QString::fromLatin1(opt->choices[cb->currentIndex()].choice); +- if (m->m_currentPrintDevice->setProperty(PDPK_PpdOption, values)) { ++ if (m->currentPrintDevice()->setProperty(PDPK_PpdOption, values)) { + itm->selected = cb->currentIndex(); + itm->selDescription = static_cast(itm->ptr)->choices[itm->selected].text; + } +-- +2.7.4 + diff --git a/0007-CUPS-Fix-advanced-options-cancel-of-the-print-properties-dialog.patch b/0007-CUPS-Fix-advanced-options-cancel-of-the-print-properties-dialog.patch new file mode 100644 index 0000000..4825af2 --- /dev/null +++ b/0007-CUPS-Fix-advanced-options-cancel-of-the-print-properties-dialog.patch @@ -0,0 +1,110 @@ +From 6efbd4381ade816515bbde59f9d31df0241e1340 Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +Date: Thu, 21 Dec 2017 16:37:14 +0100 +Subject: [PATCH] CUPS: Fix advanced options cancel of the print properties + dialog + +When the user changes the advanced settings we call +setProperty PDPK_PpdOption so if the user cancels we +need to set them back to what they were originally + +Change-Id: Idd0cb413fb1e68dd28cf66f7f66f7e0afb38393e +Reviewed-by: Michael Weghorn +Reviewed-by: Kevin Ottens +Reviewed-by: Frederik Gladhorn +--- + src/printsupport/dialogs/qprintdialog_unix.cpp | 36 ++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp +index a9745d7..3b1c492 100644 +--- a/src/printsupport/dialogs/qprintdialog_unix.cpp ++++ b/src/printsupport/dialogs/qprintdialog_unix.cpp +@@ -139,6 +139,9 @@ public: + + void showEvent(QShowEvent *event) override; + ++private slots: ++ void reject() override; ++ + private: + friend class QUnixPrintWidgetPrivate; + QPrinter *m_printer; +@@ -270,6 +273,7 @@ public: + } + + int selected; ++ int originallySelected; + const char *selDescription; + }; + +@@ -289,6 +293,7 @@ public: + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override; + + void setCupsOptionsFromItems(QPrinter *printer) const; ++ void reject(); + + QPrintDevice *currentPrintDevice() const; + QTextCodec *cupsCodec() const; +@@ -299,6 +304,7 @@ private: + void parseChoices(QOptionTreeItemOption *parent); + + void setCupsOptionsFromItems(QPrinter *printer, QOptionTreeItem *parent) const; ++ void reject(QOptionTreeItem *item); + + QPrintDevice *m_currentPrintDevice; + QTextCodec *m_cupsCodec; +@@ -399,6 +405,14 @@ void QPrintPropertiesDialog::showEvent(QShowEvent *event) + QDialog::showEvent(event); + } + ++void QPrintPropertiesDialog::reject() ++{ ++#if QT_CONFIG(cups) ++ m_cupsOptionsModel->reject(); ++#endif ++ QDialog::reject(); ++} ++ + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + +@@ -1297,6 +1311,7 @@ void QPPDOptionsModel::parseChoices(QOptionTreeItemOption *parent) + parent->selected = i; + parent->selDescription = option->choices[i].text; + } ++ parent->originallySelected = parent->selected; + parent->childItems.append(choice); + } + } +@@ -1316,6 +1331,27 @@ QVariant QPPDOptionsModel::headerData(int section, Qt::Orientation, int role) co + return QVariant(); + } + ++void QPPDOptionsModel::reject() ++{ ++ reject(m_rootItem); ++} ++ ++void QPPDOptionsModel::reject(QOptionTreeItem *item) ++{ ++ if (item->type == QOptionTreeItem::Option) { ++ QOptionTreeItemOption *itemOption = static_cast(item); ++ ++ const ppd_option_t *option = static_cast(item->ptr); ++ const char *choice = itemOption->originallySelected != -1 ? option->choices[itemOption->originallySelected].choice ++ : option->defchoice; ++ const auto values = QStringList{} << QString::fromLatin1(option->keyword) << QString::fromLatin1(choice); ++ m_currentPrintDevice->setProperty(PDPK_PpdOption, values); ++ } ++ ++ for (QOptionTreeItem *child : qAsConst(item->childItems)) ++ reject(child); ++} ++ + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + +-- +2.7.4 + diff --git a/0008-CUPS-Fix-conflict-handling.patch b/0008-CUPS-Fix-conflict-handling.patch new file mode 100644 index 0000000..c2b1293 --- /dev/null +++ b/0008-CUPS-Fix-conflict-handling.patch @@ -0,0 +1,290 @@ +From 5e2f583a67c75c1c03e213467bb56207e5084279 Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +Date: Thu, 21 Dec 2017 16:55:42 +0100 +Subject: [PATCH] CUPS: Fix conflict handling + +The previous code assumed that ppdMarkOption returning non zero (i.e. it has conflicts) +also meant that the option wasn't applied at the ppd level, but it actually is. + +What we need to do is after calling ppdMarkOption parse the tree again looking +to see if any option is conflicting and mark it as such in the UI. + +Change-Id: I836f1902d14dc8c176bb06776471cbf4ed11786f +Reviewed-by: Andy Shaw +--- + src/plugins/printsupport/cups/qppdprintdevice.cpp | 6 +- + src/printsupport/dialogs/qprintdialog_unix.cpp | 101 ++++++++++++++++++++- + src/printsupport/dialogs/qprintpropertieswidget.ui | 65 +++++++++++-- + 3 files changed, 160 insertions(+), 12 deletions(-) + +diff --git a/src/plugins/printsupport/cups/qppdprintdevice.cpp b/src/plugins/printsupport/cups/qppdprintdevice.cpp +index 8aed8c5..9c4b699 100644 +--- a/src/plugins/printsupport/cups/qppdprintdevice.cpp ++++ b/src/plugins/printsupport/cups/qppdprintdevice.cpp +@@ -443,8 +443,10 @@ bool QPpdPrintDevice::setProperty(QPrintDevice::PrintDevicePropertyKey key, cons + { + if (key == PDPK_PpdOption) { + const QStringList values = value.toStringList(); +- if (values.count() == 2) +- return ppdMarkOption(m_ppd, values[0].toLatin1(), values[1].toLatin1()) == 0; ++ if (values.count() == 2) { ++ ppdMarkOption(m_ppd, values[0].toLatin1(), values[1].toLatin1()); ++ return true; ++ } + } + + return false; +diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp +index 3b1c492..fcb53f4 100644 +--- a/src/printsupport/dialogs/qprintdialog_unix.cpp ++++ b/src/printsupport/dialogs/qprintdialog_unix.cpp +@@ -141,6 +141,7 @@ public: + + private slots: + void reject() override; ++ void accept() override; + + private: + friend class QUnixPrintWidgetPrivate; +@@ -298,6 +299,12 @@ public: + QPrintDevice *currentPrintDevice() const; + QTextCodec *cupsCodec() const; + ++ void emitConflictsChanged(); ++ bool hasConflicts() const; ++ ++signals: ++ void hasConflictsChanged(bool conflicts); ++ + private: + void parseGroups(QOptionTreeItem *parent); + void parseOptions(QOptionTreeItem *parent); +@@ -305,6 +312,8 @@ private: + + void setCupsOptionsFromItems(QPrinter *printer, QOptionTreeItem *parent) const; + void reject(QOptionTreeItem *item); ++ void emitDataChanged(QOptionTreeItem *item, const QModelIndex &itemIndex, bool *conflictsFound); ++ bool hasConflicts(QOptionTreeItem *item) const; + + QPrintDevice *m_currentPrintDevice; + QTextCodec *m_cupsCodec; +@@ -377,6 +386,9 @@ QPrintPropertiesDialog::QPrintPropertiesDialog(QPrinter *printer, QPrintDevice * + widget.treeView->setModel(nullptr); + widget.tabs->setTabEnabled(advancedTabIndex, false); + } ++ ++ widget.conflictsLabel->setVisible(m_cupsOptionsModel->hasConflicts()); ++ connect(m_cupsOptionsModel, &QPPDOptionsModel::hasConflictsChanged, widget.conflictsLabel, &QLabel::setVisible); + #else + Q_UNUSED(currentPrintDevice) + widget.tabs->setTabEnabled(advancedTabIndex, false); +@@ -413,6 +425,21 @@ void QPrintPropertiesDialog::reject() + QDialog::reject(); + } + ++void QPrintPropertiesDialog::accept() ++{ ++#if QT_CONFIG(cups) ++ if (m_cupsOptionsModel->hasConflicts()) { ++ widget.tabs->setCurrentWidget(widget.cupsPropertiesPage); ++ const QMessageBox::StandardButton answer = QMessageBox::warning(this, tr("Advanced option conflicts"), ++ tr("There are conflicts in some advanced options. Do you want to fix them?"), ++ QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); ++ if (answer != QMessageBox::No) ++ return; ++ } ++#endif ++ QDialog::accept(); ++} ++ + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + +@@ -1180,6 +1207,22 @@ QVariant QPPDOptionsModel::data(const QModelIndex &index, int role) const + } + break; + ++ case Qt::DecorationRole: { ++ if (itm->type == QOptionTreeItem::Option && index.column() == 1) { ++ const ppd_option_t *option = static_cast(itm->ptr); ++ if (option->conflicted) { ++ const QIcon warning = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, nullptr); ++ if (!warning.isNull()) ++ return warning; ++ ++ qWarning() << "Current application style returned a null icon for SP_MessageBoxWarning."; ++ return QColor(Qt::red); ++ } ++ } ++ return QVariant(); ++ } ++ break; ++ + } + + return QVariant(); +@@ -1316,6 +1359,55 @@ void QPPDOptionsModel::parseChoices(QOptionTreeItemOption *parent) + } + } + ++bool QPPDOptionsModel::hasConflicts() const ++{ ++ return hasConflicts(m_rootItem); ++} ++ ++bool QPPDOptionsModel::hasConflicts(QOptionTreeItem *item) const ++{ ++ if (item->type == QOptionTreeItem::Option) { ++ const ppd_option_t *option = static_cast(item->ptr); ++ return option->conflicted; ++ } ++ ++ for (QOptionTreeItem *child : qAsConst(item->childItems)) { ++ if (hasConflicts(child)) ++ return true; ++ } ++ ++ return false; ++} ++ ++void QPPDOptionsModel::emitConflictsChanged() ++{ ++ bool conflictsFound = false; ++ emitDataChanged(m_rootItem, QModelIndex(), &conflictsFound); ++ ++ emit hasConflictsChanged(conflictsFound); ++} ++ ++void QPPDOptionsModel::emitDataChanged(QOptionTreeItem *item, const QModelIndex &itemIndex, bool *conflictsFound) ++{ ++ if (item->type == QOptionTreeItem::Option) { ++ // We just emit DecorationRole dataChanged for all the leaves ++ // and let the view requery the value ++ const QModelIndex secondColItem = index(itemIndex.row(), 1, itemIndex.parent()); ++ emit dataChanged(secondColItem, secondColItem, QVector() << Qt::DecorationRole); ++ ++ if (conflictsFound && *conflictsFound == false) { ++ const ppd_option_t *option = static_cast(item->ptr); ++ if (option->conflicted && conflictsFound) ++ *conflictsFound = true; ++ } ++ } ++ ++ for (int i = 0; i < item->childItems.count(); ++i) { ++ QOptionTreeItem *child = item->childItems.at(i); ++ emitDataChanged(child, index(i, 0, itemIndex), conflictsFound); ++ } ++} ++ + QVariant QPPDOptionsModel::headerData(int section, Qt::Orientation, int role) const + { + if (role != Qt::DisplayRole) +@@ -1404,10 +1496,11 @@ void QPPDOptionsEditor::setModelData(QWidget *editor, QAbstractItemModel *model, + QPPDOptionsModel *m = static_cast(model); + + const auto values = QStringList{} << QString::fromLatin1(opt->keyword) << QString::fromLatin1(opt->choices[cb->currentIndex()].choice); +- if (m->currentPrintDevice()->setProperty(PDPK_PpdOption, values)) { +- itm->selected = cb->currentIndex(); +- itm->selDescription = static_cast(itm->ptr)->choices[itm->selected].text; +- } ++ m->currentPrintDevice()->setProperty(PDPK_PpdOption, values); ++ itm->selected = cb->currentIndex(); ++ itm->selDescription = static_cast(itm->ptr)->choices[itm->selected].text; ++ ++ m->emitConflictsChanged(); + } + + //////////////////////////////////////////////////////////////////////////////// +diff --git a/src/printsupport/dialogs/qprintpropertieswidget.ui b/src/printsupport/dialogs/qprintpropertieswidget.ui +index 0e56fb3..d8e5261 100644 +--- a/src/printsupport/dialogs/qprintpropertieswidget.ui ++++ b/src/printsupport/dialogs/qprintpropertieswidget.ui +@@ -14,7 +14,16 @@ + Form + + +- ++ ++ 0 ++ ++ ++ 0 ++ ++ ++ 0 ++ ++ + 0 + + +@@ -32,18 +41,62 @@ + + + +- +- ++ ++ + Advanced + +- ++ + +- +- ++ ++ + true + + + ++ ++ ++ ++ ++ ++ ++ ++ ++ 255 ++ 0 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ 255 ++ 0 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ 165 ++ 167 ++ 169 ++ ++ ++ ++ ++ ++ ++ ++ There are conflicts in some options. Please fix them. ++ ++ ++ + + + +-- +2.7.4 + diff --git a/0009-CUPS-Use-printer-job-sheets-as-default-instead-of-none-none.patch b/0009-CUPS-Use-printer-job-sheets-as-default-instead-of-none-none.patch new file mode 100644 index 0000000..f9e93e2 --- /dev/null +++ b/0009-CUPS-Use-printer-job-sheets-as-default-instead-of-none-none.patch @@ -0,0 +1,118 @@ +From 83538a360e246ac2242977015e4a374a9f0e21b8 Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +Date: Wed, 6 Dec 2017 11:28:55 +0100 +Subject: [PATCH] CUPS: Use printer job-sheets as default instead of none,none + +This also reads the job-sheets from lpoptions if set there for the particular printer + +Change-Id: I35aff103261ef58492779071d866e8a15ac78607 +Reviewed-by: Laurent Montel +Reviewed-by: Frederik Gladhorn +--- + src/plugins/printsupport/cups/qppdprintdevice.cpp | 2 ++ + src/printsupport/kernel/qcups.cpp | 26 +++++++++++++++++++++++ + src/printsupport/kernel/qcups_p.h | 8 +++++++ + src/printsupport/widgets/qcupsjobwidget.cpp | 11 ++++++++-- + 4 files changed, 45 insertions(+), 2 deletions(-) + +diff --git a/src/plugins/printsupport/cups/qppdprintdevice.cpp b/src/plugins/printsupport/cups/qppdprintdevice.cpp +index 56976a6..e11d301 100644 +--- a/src/plugins/printsupport/cups/qppdprintdevice.cpp ++++ b/src/plugins/printsupport/cups/qppdprintdevice.cpp +@@ -429,6 +429,8 @@ QVariant QPpdPrintDevice::property(QPrintDevice::PrintDevicePropertyKey key) con + return QVariant::fromValue(m_ppd); + else if (key == PDPK_CupsJobPriority) + return printerOption(QStringLiteral("job-priority")); ++ else if (key == PDPK_CupsJobSheets) ++ return printerOption(QStringLiteral("job-sheets")); + + return QVariant(); + } +diff --git a/src/printsupport/kernel/qcups.cpp b/src/printsupport/kernel/qcups.cpp +index b9e162a..aa1cdff 100644 +--- a/src/printsupport/kernel/qcups.cpp ++++ b/src/printsupport/kernel/qcups.cpp +@@ -150,6 +150,32 @@ static inline QString bannerPageToString(const QCUPSSupport::BannerPage bannerPa + return QString(); + } + ++static inline QCUPSSupport::BannerPage stringToBannerPage(const QString &bannerPage) ++{ ++ if (bannerPage == QLatin1String("none")) return QCUPSSupport::NoBanner; ++ else if (bannerPage == QLatin1String("standard")) return QCUPSSupport::Standard; ++ else if (bannerPage == QLatin1String("unclassified")) return QCUPSSupport::Unclassified; ++ else if (bannerPage == QLatin1String("confidential")) return QCUPSSupport::Confidential; ++ else if (bannerPage == QLatin1String("classified")) return QCUPSSupport::Classified; ++ else if (bannerPage == QLatin1String("secret")) return QCUPSSupport::Secret; ++ else if (bannerPage == QLatin1String("topsecret")) return QCUPSSupport::TopSecret; ++ ++ return QCUPSSupport::NoBanner; ++} ++ ++QCUPSSupport::JobSheets QCUPSSupport::parseJobSheets(const QString &jobSheets) ++{ ++ JobSheets result; ++ ++ const QStringList parts = jobSheets.split(QLatin1Char(',')); ++ if (parts.count() == 2) { ++ result.startBannerPage = stringToBannerPage(parts[0]); ++ result.endBannerPage = stringToBannerPage(parts[1]); ++ } ++ ++ return result; ++} ++ + void QCUPSSupport::setBannerPages(QPrinter *printer, const BannerPage startBannerPage, const BannerPage endBannerPage) + { + QStringList cupsOptions = cupsOptionsList(printer); +diff --git a/src/printsupport/kernel/qcups_p.h b/src/printsupport/kernel/qcups_p.h +index 3abccf2..906a548 100644 +--- a/src/printsupport/kernel/qcups_p.h ++++ b/src/printsupport/kernel/qcups_p.h +@@ -70,6 +70,7 @@ QT_BEGIN_NAMESPACE + #define PDPK_PpdFile QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase) + #define PDPK_PpdOption QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 1) + #define PDPK_CupsJobPriority QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 2) ++#define PDPK_CupsJobSheets QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 3) + + class Q_PRINTSUPPORT_EXPORT QCUPSSupport + { +@@ -139,6 +140,13 @@ public: + static void setPagesPerSheetLayout(QPrinter *printer, const PagesPerSheet pagesPerSheet, + const PagesPerSheetLayout pagesPerSheetLayout); + static void setPageRange(QPrinter *printer, int pageFrom, int pageTo); ++ ++ struct JobSheets ++ { ++ BannerPage startBannerPage = QCUPSSupport::NoBanner; ++ BannerPage endBannerPage = QCUPSSupport::NoBanner; ++ }; ++ static JobSheets parseJobSheets(const QString &jobSheets); + }; + Q_DECLARE_TYPEINFO(QCUPSSupport::JobHoldUntil, Q_PRIMITIVE_TYPE); + Q_DECLARE_TYPEINFO(QCUPSSupport::BannerPage, Q_PRIMITIVE_TYPE); +diff --git a/src/printsupport/widgets/qcupsjobwidget.cpp b/src/printsupport/widgets/qcupsjobwidget.cpp +index f21e229..4535f75 100644 +--- a/src/printsupport/widgets/qcupsjobwidget.cpp ++++ b/src/printsupport/widgets/qcupsjobwidget.cpp +@@ -196,8 +196,15 @@ void QCupsJobWidget::initBannerPages() + m_ui.endBannerPageCombo->addItem(tr("Secret", "CUPS Banner page"), QVariant::fromValue(QCUPSSupport::Secret)); + m_ui.endBannerPageCombo->addItem(tr("Top Secret", "CUPS Banner page"), QVariant::fromValue(QCUPSSupport::TopSecret)); + +- setStartBannerPage(QCUPSSupport::NoBanner); +- setEndBannerPage(QCUPSSupport::NoBanner); ++ QCUPSSupport::JobSheets jobSheets; ++ ++ if (m_printDevice) { ++ const QString jobSheetsString = m_printDevice->property(PDPK_CupsJobSheets).toString(); ++ jobSheets = QCUPSSupport::parseJobSheets(jobSheetsString); ++ } ++ ++ setStartBannerPage(jobSheets.startBannerPage); ++ setEndBannerPage(jobSheets.endBannerPage); + } + + void QCupsJobWidget::setStartBannerPage(const QCUPSSupport::BannerPage bannerPage) +-- +2.7.4 + diff --git a/0010-CUPS-Use-printer-job-billing-as-default-instead-of-the-empty-string.patch b/0010-CUPS-Use-printer-job-billing-as-default-instead-of-the-empty-string.patch new file mode 100644 index 0000000..9378f7f --- /dev/null +++ b/0010-CUPS-Use-printer-job-billing-as-default-instead-of-the-empty-string.patch @@ -0,0 +1,62 @@ +From 2831fa76655c614ed3df0816401514950e79b5e6 Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +Date: Wed, 6 Dec 2017 12:00:00 +0100 +Subject: [PATCH] CUPS: Use printer job-billing as default instead of the empty + string + +This also reads the job-billing from lpoptions if set there for the particular printer + +Change-Id: Ia4a6961de504005b8dcd9209da0624e9ae9ef7e4 +Reviewed-by: Laurent Montel +Reviewed-by: Frederik Gladhorn +--- + src/plugins/printsupport/cups/qppdprintdevice.cpp | 2 ++ + src/printsupport/kernel/qcups_p.h | 1 + + src/printsupport/widgets/qcupsjobwidget.cpp | 6 +++++- + 3 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/src/plugins/printsupport/cups/qppdprintdevice.cpp b/src/plugins/printsupport/cups/qppdprintdevice.cpp +index e11d301..0fd6f5f 100644 +--- a/src/plugins/printsupport/cups/qppdprintdevice.cpp ++++ b/src/plugins/printsupport/cups/qppdprintdevice.cpp +@@ -431,6 +431,8 @@ QVariant QPpdPrintDevice::property(QPrintDevice::PrintDevicePropertyKey key) con + return printerOption(QStringLiteral("job-priority")); + else if (key == PDPK_CupsJobSheets) + return printerOption(QStringLiteral("job-sheets")); ++ else if (key == PDPK_CupsJobBilling) ++ return printerOption(QStringLiteral("job-billing")); + + return QVariant(); + } +diff --git a/src/printsupport/kernel/qcups_p.h b/src/printsupport/kernel/qcups_p.h +index 906a548..c6bbacc 100644 +--- a/src/printsupport/kernel/qcups_p.h ++++ b/src/printsupport/kernel/qcups_p.h +@@ -71,6 +71,7 @@ QT_BEGIN_NAMESPACE + #define PDPK_PpdOption QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 1) + #define PDPK_CupsJobPriority QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 2) + #define PDPK_CupsJobSheets QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 3) ++#define PDPK_CupsJobBilling QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 4) + + class Q_PRINTSUPPORT_EXPORT QCUPSSupport + { +diff --git a/src/printsupport/widgets/qcupsjobwidget.cpp b/src/printsupport/widgets/qcupsjobwidget.cpp +index 4535f75..adaaff8 100644 +--- a/src/printsupport/widgets/qcupsjobwidget.cpp ++++ b/src/printsupport/widgets/qcupsjobwidget.cpp +@@ -139,7 +139,11 @@ QTime QCupsJobWidget::jobHoldTime() const + + void QCupsJobWidget::initJobBilling() + { +- setJobBilling(QString()); ++ QString jobBilling; ++ if (m_printDevice) ++ jobBilling = m_printDevice->property(PDPK_CupsJobBilling).toString(); ++ ++ setJobBilling(jobBilling); + } + + void QCupsJobWidget::setJobBilling(const QString &jobBilling) +-- +2.7.4 + diff --git a/0011-CUPS-Use-printer-job-hold-until-as-default-instead-of-the-nohold.patch b/0011-CUPS-Use-printer-job-hold-until-as-default-instead-of-the-nohold.patch new file mode 100644 index 0000000..760b068 --- /dev/null +++ b/0011-CUPS-Use-printer-job-hold-until-as-default-instead-of-the-nohold.patch @@ -0,0 +1,139 @@ +From 414a703036db6d5b4b1f48b85d8c3b4702f869ec Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +Date: Wed, 6 Dec 2017 13:00:30 +0100 +Subject: [PATCH] CUPS: Use printer job-hold-until as default instead of the + nohold + +This also reads the job-hold-until from lpoptions if set there for the particular printer + +Change-Id: Ic60fef675ab9f4760cd99ee9ac417b0478459681 +Reviewed-by: Frederik Gladhorn +--- + src/plugins/printsupport/cups/qppdprintdevice.cpp | 2 ++ + src/printsupport/kernel/qcups.cpp | 31 +++++++++++++++++++++++ + src/printsupport/kernel/qcups_p.h | 18 +++++++++---- + src/printsupport/widgets/qcupsjobwidget.cpp | 10 ++++++-- + 4 files changed, 54 insertions(+), 7 deletions(-) + +diff --git a/src/plugins/printsupport/cups/qppdprintdevice.cpp b/src/plugins/printsupport/cups/qppdprintdevice.cpp +index 0fd6f5f..14c14fa 100644 +--- a/src/plugins/printsupport/cups/qppdprintdevice.cpp ++++ b/src/plugins/printsupport/cups/qppdprintdevice.cpp +@@ -433,6 +433,8 @@ QVariant QPpdPrintDevice::property(QPrintDevice::PrintDevicePropertyKey key) con + return printerOption(QStringLiteral("job-sheets")); + else if (key == PDPK_CupsJobBilling) + return printerOption(QStringLiteral("job-billing")); ++ else if (key == PDPK_CupsJobHoldUntil) ++ return printerOption(QStringLiteral("job-hold-until")); + + return QVariant(); + } +diff --git a/src/printsupport/kernel/qcups.cpp b/src/printsupport/kernel/qcups.cpp +index aa1cdff..50c6953 100644 +--- a/src/printsupport/kernel/qcups.cpp ++++ b/src/printsupport/kernel/qcups.cpp +@@ -107,6 +107,37 @@ static inline QString jobHoldToString(const QCUPSSupport::JobHoldUntil jobHold, + return QString(); + } + ++QCUPSSupport::JobHoldUntilWithTime QCUPSSupport::parseJobHoldUntil(const QString &jobHoldUntil) ++{ ++ if (jobHoldUntil == QLatin1String("indefinite")) { ++ return { QCUPSSupport::Indefinite, QTime() }; ++ } else if (jobHoldUntil == QLatin1String("day-time")) { ++ return { QCUPSSupport::DayTime, QTime() }; ++ } else if (jobHoldUntil == QLatin1String("night")) { ++ return { QCUPSSupport::Night, QTime() }; ++ } else if (jobHoldUntil == QLatin1String("second-shift")) { ++ return { QCUPSSupport::SecondShift, QTime() }; ++ } else if (jobHoldUntil == QLatin1String("third-shift")) { ++ return { QCUPSSupport::ThirdShift, QTime() }; ++ } else if (jobHoldUntil == QLatin1String("weekend")) { ++ return { QCUPSSupport::Weekend, QTime() }; ++ } ++ ++ ++ QTime parsedTime = QTime::fromString(jobHoldUntil, QStringLiteral("h:m:s")); ++ if (!parsedTime.isValid()) ++ parsedTime = QTime::fromString(jobHoldUntil, QStringLiteral("h:m")); ++ if (parsedTime.isValid()) { ++ // CUPS time is in UTC, user expects local time, so get the equivalent ++ QDateTime dateTimeUtc = QDateTime::currentDateTimeUtc(); ++ dateTimeUtc.setTime(parsedTime); ++ return { QCUPSSupport::SpecificTime, dateTimeUtc.toLocalTime().time() }; ++ } ++ ++ return { QCUPSSupport::NoHold, QTime() }; ++} ++ ++ + void QCUPSSupport::setJobHold(QPrinter *printer, const JobHoldUntil jobHold, const QTime &holdUntilTime) + { + QStringList cupsOptions = cupsOptionsList(printer); +diff --git a/src/printsupport/kernel/qcups_p.h b/src/printsupport/kernel/qcups_p.h +index c6bbacc..afddfdb 100644 +--- a/src/printsupport/kernel/qcups_p.h ++++ b/src/printsupport/kernel/qcups_p.h +@@ -67,11 +67,12 @@ QT_BEGIN_NAMESPACE + // removed from the dialogs. + #define PPK_CupsOptions QPrintEngine::PrintEnginePropertyKey(0xfe00) + +-#define PDPK_PpdFile QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase) +-#define PDPK_PpdOption QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 1) +-#define PDPK_CupsJobPriority QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 2) +-#define PDPK_CupsJobSheets QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 3) +-#define PDPK_CupsJobBilling QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 4) ++#define PDPK_PpdFile QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase) ++#define PDPK_PpdOption QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 1) ++#define PDPK_CupsJobPriority QPrintDevice::PrintDevicePropertyKey(QPrintDevice::PDPK_CustomBase + 2) ++#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) + + class Q_PRINTSUPPORT_EXPORT QCUPSSupport + { +@@ -148,6 +149,13 @@ public: + BannerPage endBannerPage = QCUPSSupport::NoBanner; + }; + static JobSheets parseJobSheets(const QString &jobSheets); ++ ++ struct JobHoldUntilWithTime ++ { ++ JobHoldUntil jobHold; ++ QTime time; ++ }; ++ static JobHoldUntilWithTime parseJobHoldUntil(const QString &jobHoldUntil); + }; + Q_DECLARE_TYPEINFO(QCUPSSupport::JobHoldUntil, Q_PRIMITIVE_TYPE); + Q_DECLARE_TYPEINFO(QCUPSSupport::BannerPage, Q_PRIMITIVE_TYPE); +diff --git a/src/printsupport/widgets/qcupsjobwidget.cpp b/src/printsupport/widgets/qcupsjobwidget.cpp +index adaaff8..5d026d4 100644 +--- a/src/printsupport/widgets/qcupsjobwidget.cpp ++++ b/src/printsupport/widgets/qcupsjobwidget.cpp +@@ -73,7 +73,6 @@ QCupsJobWidget::QCupsJobWidget(QPrinter *printer, QPrintDevice *printDevice, QWi + { + m_ui.setupUi(this); + //set all the default values +- //TODO restore last used values + initJobHold(); + initJobBilling(); + initJobPriority(); +@@ -105,7 +104,14 @@ void QCupsJobWidget::initJobHold() + + connect(m_ui.jobHoldComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(toggleJobHoldTime())); + +- setJobHold(QCUPSSupport::NoHold, QTime()); ++ QCUPSSupport::JobHoldUntilWithTime jobHoldWithTime; ++ ++ if (m_printDevice) { ++ const QString jobHoldUntilString = m_printDevice->property(PDPK_CupsJobHoldUntil).toString(); ++ jobHoldWithTime = QCUPSSupport::parseJobHoldUntil(jobHoldUntilString); ++ } ++ ++ setJobHold(jobHoldWithTime.jobHold, jobHoldWithTime.time); + toggleJobHoldTime(); + } + +-- +2.7.4 + diff --git a/0012-Unix-Fix-usability-of-the-print-properties-dialog.patch b/0012-Unix-Fix-usability-of-the-print-properties-dialog.patch new file mode 100644 index 0000000..3fbfb46 --- /dev/null +++ b/0012-Unix-Fix-usability-of-the-print-properties-dialog.patch @@ -0,0 +1,512 @@ +From d94ccf310a9ca01593750a34f743ec652f6a344e Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +Date: Wed, 27 Dec 2017 11:12:19 +0100 +Subject: [PATCH 1/1] Unix: Fix usability of the print properties dialog + +Previous behavior: + * Open, change setting, cancel, open again, setting was as originally (i.e. unchanged) + * Open, change setting, accept, open, change setting, cancel, open again, the setting would be as before pressing cancel + * Open, change setting, accept, open, press cancel without changing anything, print, the initially changed setting is not applied + +New behavior: + * Pressing cancel just cancels the changes since you opened the dialog, everything you accepted previously stays correctly selected + +Change-Id: I483647504682f26d3d21c5229cc6530bf14fe519 +Reviewed-by: Andy Shaw +Reviewed-by: Frederik Gladhorn +--- + src/printsupport/dialogs/qpagesetupdialog_unix.cpp | 25 +++++ + src/printsupport/dialogs/qpagesetupdialog_unix_p.h | 6 ++ + src/printsupport/dialogs/qprintdialog_unix.cpp | 107 +++++++++++++-------- + src/printsupport/kernel/qcups_p.h | 10 +- + src/printsupport/widgets/qcupsjobwidget.cpp | 25 ++++- + src/printsupport/widgets/qcupsjobwidget_p.h | 7 ++ + 6 files changed, 136 insertions(+), 44 deletions(-) + +diff --git a/src/printsupport/dialogs/qpagesetupdialog_unix.cpp b/src/printsupport/dialogs/qpagesetupdialog_unix.cpp +index 4086212..2063408 100644 +--- a/src/printsupport/dialogs/qpagesetupdialog_unix.cpp ++++ b/src/printsupport/dialogs/qpagesetupdialog_unix.cpp +@@ -234,6 +234,9 @@ QPageSetupWidget::QPageSetupWidget(QWidget *parent) + m_printer(0), + m_outputFormat(QPrinter::PdfFormat), + m_units(QPageLayout::Point), ++ m_savedUnits(QPageLayout::Point), ++ m_savedPagesPerSheet(-1), ++ m_savedPagesPerSheetLayout(-1), + m_blockSignals(false), + m_realCustomPageSizeIndex(-1) + { +@@ -404,6 +407,7 @@ void QPageSetupWidget::setPrinter(QPrinter *printer, QPrintDevice *printDevice, + m_printerName = printerName; + initPageSizes(); + updateWidget(); ++ updateSavedValues(); + } + + // Update the widget with the current settings +@@ -487,6 +491,7 @@ void QPageSetupWidget::updateWidget() + m_ui.pageHeight->setEnabled(isCustom); + m_ui.heightLabel->setEnabled(isCustom); + ++ m_ui.portrait->setChecked(m_pageLayout.orientation() == QPageLayout::Portrait); + m_ui.landscape->setChecked(m_pageLayout.orientation() == QPageLayout::Landscape); + + m_ui.pagesPerSheetButtonGroup->setEnabled(m_outputFormat == QPrinter::NativeFormat); +@@ -515,6 +520,26 @@ void QPageSetupWidget::setupPrinter() const + #endif + } + ++void QPageSetupWidget::updateSavedValues() ++{ ++ m_savedUnits = m_units; ++ m_savedPageLayout = m_pageLayout; ++ m_savedPagesPerSheet = m_ui.pagesPerSheetCombo->currentIndex(); ++ m_savedPagesPerSheetLayout = m_ui.pagesPerSheetLayoutCombo->currentIndex(); ++} ++ ++void QPageSetupWidget::revertToSavedValues() ++{ ++ m_units = m_savedUnits; ++ m_pageLayout = m_savedPageLayout; ++ m_pagePreview->setPageLayout(m_pageLayout); ++ ++ updateWidget(); ++ ++ m_ui.pagesPerSheetCombo->setCurrentIndex(m_savedPagesPerSheet); ++ m_ui.pagesPerSheetLayoutCombo->setCurrentIndex(m_savedPagesPerSheetLayout); ++} ++ + // Updates size/preview after the combobox has been changed. + void QPageSetupWidget::pageSizeChanged() + { +diff --git a/src/printsupport/dialogs/qpagesetupdialog_unix_p.h b/src/printsupport/dialogs/qpagesetupdialog_unix_p.h +index 0b9723e..82c22c3 100644 +--- a/src/printsupport/dialogs/qpagesetupdialog_unix_p.h ++++ b/src/printsupport/dialogs/qpagesetupdialog_unix_p.h +@@ -75,6 +75,8 @@ public: + void setPrinter(QPrinter *printer, QPrintDevice *printDevice, + QPrinter::OutputFormat outputFormat, const QString &printerName); + void setupPrinter() const; ++ void updateSavedValues(); ++ void revertToSavedValues(); + + private slots: + void pageSizeChanged(); +@@ -100,7 +102,11 @@ private: + QPrinter::OutputFormat m_outputFormat; + QString m_printerName; + QPageLayout m_pageLayout; ++ QPageLayout m_savedPageLayout; + QPageLayout::Unit m_units; ++ QPageLayout::Unit m_savedUnits; ++ int m_savedPagesPerSheet; ++ int m_savedPagesPerSheetLayout; + bool m_blockSignals; + int m_realCustomPageSizeIndex; + }; +diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp +index a3ba7be..29000bf 100644 +--- a/src/printsupport/dialogs/qprintdialog_unix.cpp ++++ b/src/printsupport/dialogs/qprintdialog_unix.cpp +@@ -207,7 +207,6 @@ public: + private: + QPrintDialogPrivate *optionsPane; + bool filePrintersAdded; +- bool propertiesDialogShown; + }; + + class QPrintDialogPrivate : public QAbstractPrintDialogPrivate +@@ -247,11 +246,10 @@ class QOptionTreeItem + public: + enum ItemType { Root, Group, Option, Choice }; + +- QOptionTreeItem(ItemType t, int i, const void *p, const char *desc, QOptionTreeItem *pi) ++ QOptionTreeItem(ItemType t, int i, const void *p, QOptionTreeItem *pi) + : type(t), + index(i), + ptr(p), +- description(desc), + parentItem(pi) {} + + ~QOptionTreeItem() { +@@ -261,7 +259,6 @@ public: + ItemType type; + int index; + const void *ptr; +- const char *description; + QOptionTreeItem *parentItem; + QList childItems; + }; +@@ -269,14 +266,13 @@ public: + class QOptionTreeItemOption : public QOptionTreeItem + { + public: +- QOptionTreeItemOption (int i, const void *p, const char *desc, QOptionTreeItem *pi) +- : QOptionTreeItem(Option, i, p, desc, pi) ++ QOptionTreeItemOption (int i, const void *p, QOptionTreeItem *pi) ++ : QOptionTreeItem(Option, i, p, pi) + { + } + + int selected; + int originallySelected; +- const char *selDescription; + }; + + class QPPDOptionsModel : public QAbstractItemModel +@@ -296,6 +292,8 @@ public: + + void setCupsOptionsFromItems(QPrinter *printer) const; + void reject(); ++ void updateSavedValues(); ++ void revertToSavedValues(); + + QPrintDevice *currentPrintDevice() const; + QTextCodec *cupsCodec() const; +@@ -313,6 +311,8 @@ private: + + void setCupsOptionsFromItems(QPrinter *printer, QOptionTreeItem *parent) const; + void reject(QOptionTreeItem *item); ++ void updateSavedValues(QOptionTreeItem *item); ++ void revertToSavedValues(QOptionTreeItem *item); + void emitDataChanged(QOptionTreeItem *item, const QModelIndex &itemIndex, bool *conflictsFound); + bool hasConflicts(QOptionTreeItem *item) const; + +@@ -420,8 +420,14 @@ void QPrintPropertiesDialog::showEvent(QShowEvent *event) + + void QPrintPropertiesDialog::reject() + { ++ widget.pageSetup->revertToSavedValues(); ++ ++#if QT_CONFIG(cupsjobwidget) ++ m_jobOptions->revertToSavedValues(); ++#endif ++ + #if QT_CONFIG(cups) +- m_cupsOptionsModel->reject(); ++ m_cupsOptionsModel->revertToSavedValues(); + #endif + QDialog::reject(); + } +@@ -437,7 +443,15 @@ void QPrintPropertiesDialog::accept() + if (answer != QMessageBox::No) + return; + } ++ m_cupsOptionsModel->updateSavedValues(); ++#endif ++ ++#if QT_CONFIG(cupsjobwidget) ++ m_jobOptions->updateSavedValues(); + #endif ++ ++ widget.pageSetup->updateSavedValues(); ++ + QDialog::accept(); + } + +@@ -812,9 +826,9 @@ void QPrintDialog::accept() + */ + QUnixPrintWidgetPrivate::QUnixPrintWidgetPrivate(QUnixPrintWidget *p, QPrinter *prn) + : parent(p), propertiesDialog(0), printer(prn), optionsPane(0), +- filePrintersAdded(false), propertiesDialogShown(false) ++ filePrintersAdded(false) + { +- q = 0; ++ q = 0; + if (parent) + q = qobject_cast (parent->parent()); + +@@ -900,7 +914,6 @@ void QUnixPrintWidgetPrivate::_q_printerChanged(int index) + if (propertiesDialog){ + delete propertiesDialog; + propertiesDialog = nullptr; +- propertiesDialogShown = false; + } + + if (filePrintersAdded) { +@@ -993,7 +1006,7 @@ bool QUnixPrintWidgetPrivate::checkFields() + } + + #if QT_CONFIG(cups) +- if (propertiesDialogShown) { ++ if (propertiesDialog) { + QCUPSSupport::PagesPerSheet pagesPerSheet = propertiesDialog->widget.pageSetup->m_ui.pagesPerSheetCombo + ->currentData().value(); + +@@ -1030,8 +1043,6 @@ void QUnixPrintWidgetPrivate::setupPrinterProperties() + } + + propertiesDialog = new QPrintPropertiesDialog(q->printer(), &m_currentPrintDevice, outputFormat, printerName, q); +- propertiesDialog->setResult(QDialog::Rejected); +- propertiesDialogShown = false; + } + + void QUnixPrintWidgetPrivate::_q_btnPropertiesClicked() +@@ -1039,15 +1050,6 @@ void QUnixPrintWidgetPrivate::_q_btnPropertiesClicked() + if (!propertiesDialog) + setupPrinterProperties(); + propertiesDialog->exec(); +- if (!propertiesDialogShown && propertiesDialog->result() == QDialog::Rejected) { +- // If properties dialog was rejected the dialog is deleted and +- // the properties are set to defaults when printer is setup +- delete propertiesDialog; +- propertiesDialog = nullptr; +- propertiesDialogShown = false; +- } else +- // properties dialog was shown and accepted +- propertiesDialogShown = true; + } + + void QUnixPrintWidgetPrivate::setupPrinter() +@@ -1072,8 +1074,7 @@ void QUnixPrintWidgetPrivate::setupPrinter() + if (!propertiesDialog) + setupPrinterProperties(); + +- if (propertiesDialog->result() == QDialog::Accepted || !propertiesDialogShown) +- propertiesDialog->setupPrinter(); ++ propertiesDialog->setupPrinter(); + } + + /*! \internal +@@ -1153,12 +1154,12 @@ QPPDOptionsModel::QPPDOptionsModel(QPrintDevice *currentPrintDevice, QObject *pa + , m_cupsCodec(nullptr) + { + ppd_file_t *ppd = m_currentPrintDevice->property(PDPK_PpdFile).value(); +- m_rootItem = new QOptionTreeItem(QOptionTreeItem::Root, 0, ppd, "Root Item", 0); ++ m_rootItem = new QOptionTreeItem(QOptionTreeItem::Root, 0, ppd, nullptr); + + if (ppd) { + m_cupsCodec = QTextCodec::codecForName(ppd->lang_encoding); + for (int i = 0; i < ppd->num_groups; ++i) { +- QOptionTreeItem *group = new QOptionTreeItem(QOptionTreeItem::Group, i, &ppd->groups[i], ppd->groups[i].text, m_rootItem); ++ QOptionTreeItem *group = new QOptionTreeItem(QOptionTreeItem::Group, i, &ppd->groups[i], m_rootItem); + m_rootItem->childItems.append(group); + parseGroups(group); // parse possible subgroups + parseOptions(group); // parse options +@@ -1208,11 +1209,18 @@ QVariant QPPDOptionsModel::data(const QModelIndex &index, int role) const + + case Qt::DisplayRole: { + if (index.column() == 0) { +- return m_cupsCodec->toUnicode(itm->description); ++ if (itm->type == QOptionTreeItem::Option) { ++ const ppd_option_t *option = static_cast(itm->ptr); ++ return m_cupsCodec->toUnicode(option->text); ++ } else if (itm->type == QOptionTreeItem::Group) { ++ const ppd_group_t *group = static_cast(itm->ptr); ++ return m_cupsCodec->toUnicode(group->text); ++ } + } else if (itm->type == QOptionTreeItem::Option) { + QOptionTreeItemOption *itmOption = static_cast(itm); ++ const ppd_option_t *option = static_cast(itm->ptr); + if (itmOption->selected > -1) +- return m_cupsCodec->toUnicode(itmOption->selDescription); ++ return m_cupsCodec->toUnicode(option->choices[itmOption->selected].text); + } + + return QVariant(); +@@ -1314,7 +1322,7 @@ void QPPDOptionsModel::parseGroups(QOptionTreeItem *parent) + + if (group) { + for (int i = 0; i < group->num_subgroups; ++i) { +- QOptionTreeItem *subgroup = new QOptionTreeItem(QOptionTreeItem::Group, i, &group->subgroups[i], group->subgroups[i].text, parent); ++ QOptionTreeItem *subgroup = new QOptionTreeItem(QOptionTreeItem::Group, i, &group->subgroups[i], parent); + parent->childItems.append(subgroup); + parseGroups(subgroup); // parse possible subgroups + parseOptions(subgroup); // parse options +@@ -1346,7 +1354,7 @@ void QPPDOptionsModel::parseOptions(QOptionTreeItem *parent) + const ppd_group_t *group = static_cast(parent->ptr); + for (int i = 0; i < group->num_options; ++i) { + if (!isBlacklistedOption(group->options[i].keyword)) { +- QOptionTreeItemOption *opt = new QOptionTreeItemOption(i, &group->options[i], group->options[i].text, parent); ++ QOptionTreeItemOption *opt = new QOptionTreeItemOption(i, &group->options[i], parent); + parent->childItems.append(opt); + parseChoices(opt); + } +@@ -1358,14 +1366,12 @@ void QPPDOptionsModel::parseChoices(QOptionTreeItemOption *parent) + const ppd_option_t *option = static_cast(parent->ptr); + bool marked = false; + for (int i = 0; i < option->num_choices; ++i) { +- QOptionTreeItem *choice = new QOptionTreeItem(QOptionTreeItem::Choice, i, &option->choices[i], option->choices[i].text, parent); ++ QOptionTreeItem *choice = new QOptionTreeItem(QOptionTreeItem::Choice, i, &option->choices[i], parent); + if (static_cast(option->choices[i].marked) == 1) { + parent->selected = i; +- parent->selDescription = option->choices[i].text; + marked = true; + } else if (!marked && qstrcmp(option->choices[i].choice, option->defchoice) == 0) { + parent->selected = i; +- parent->selDescription = option->choices[i].text; + } + parent->originallySelected = parent->selected; + parent->childItems.append(choice); +@@ -1436,12 +1442,13 @@ QVariant QPPDOptionsModel::headerData(int section, Qt::Orientation, int role) co + return QVariant(); + } + +-void QPPDOptionsModel::reject() ++void QPPDOptionsModel::revertToSavedValues() + { +- reject(m_rootItem); ++ revertToSavedValues(m_rootItem); ++ emitConflictsChanged(); + } + +-void QPPDOptionsModel::reject(QOptionTreeItem *item) ++void QPPDOptionsModel::revertToSavedValues(QOptionTreeItem *item) + { + if (item->type == QOptionTreeItem::Option) { + QOptionTreeItemOption *itemOption = static_cast(item); +@@ -1451,10 +1458,27 @@ void QPPDOptionsModel::reject(QOptionTreeItem *item) + : option->defchoice; + const auto values = QStringList{} << QString::fromLatin1(option->keyword) << QString::fromLatin1(choice); + m_currentPrintDevice->setProperty(PDPK_PpdOption, values); ++ itemOption->selected = itemOption->originallySelected; + } + + for (QOptionTreeItem *child : qAsConst(item->childItems)) +- reject(child); ++ revertToSavedValues(child); ++} ++ ++void QPPDOptionsModel::updateSavedValues() ++{ ++ updateSavedValues(m_rootItem); ++} ++ ++void QPPDOptionsModel::updateSavedValues(QOptionTreeItem *item) ++{ ++ if (item->type == QOptionTreeItem::Option) { ++ QOptionTreeItemOption *itemOption = static_cast(item); ++ itemOption->originallySelected = itemOption->selected; ++ } ++ ++ for (QOptionTreeItem *child : qAsConst(item->childItems)) ++ updateSavedValues(child); + } + + //////////////////////////////////////////////////////////////////////////////// +@@ -1490,8 +1514,10 @@ void QPPDOptionsEditor::setEditorData(QWidget *editor, const QModelIndex &index) + cb->addItem(QString()); + + const QPPDOptionsModel *m = static_cast(index.model()); +- for (auto *childItem : qAsConst(itm->childItems)) +- cb->addItem(m->cupsCodec()->toUnicode(childItem->description)); ++ for (auto *childItem : qAsConst(itm->childItems)) { ++ const ppd_choice_t *choice = static_cast(childItem->ptr); ++ cb->addItem(m->cupsCodec()->toUnicode(choice->text)); ++ } + + if (itm->selected > -1) + cb->setCurrentIndex(itm->selected); +@@ -1511,7 +1537,6 @@ void QPPDOptionsEditor::setModelData(QWidget *editor, QAbstractItemModel *model, + const auto values = QStringList{} << QString::fromLatin1(opt->keyword) << QString::fromLatin1(opt->choices[cb->currentIndex()].choice); + m->currentPrintDevice()->setProperty(PDPK_PpdOption, values); + itm->selected = cb->currentIndex(); +- itm->selDescription = static_cast(itm->ptr)->choices[itm->selected].text; + + m->emitConflictsChanged(); + } +diff --git a/src/printsupport/kernel/qcups_p.h b/src/printsupport/kernel/qcups_p.h +index afddfdb..4b27632 100644 +--- a/src/printsupport/kernel/qcups_p.h ++++ b/src/printsupport/kernel/qcups_p.h +@@ -145,13 +145,19 @@ public: + + struct JobSheets + { +- BannerPage startBannerPage = QCUPSSupport::NoBanner; +- BannerPage endBannerPage = QCUPSSupport::NoBanner; ++ JobSheets(BannerPage s = NoBanner, BannerPage e = NoBanner) ++ : startBannerPage(s), endBannerPage(e) {} ++ ++ BannerPage startBannerPage; ++ BannerPage endBannerPage; + }; + static JobSheets parseJobSheets(const QString &jobSheets); + + struct JobHoldUntilWithTime + { ++ JobHoldUntilWithTime(JobHoldUntil jh = NoHold, const QTime &t = QTime()) ++ : jobHold(jh), time(t) {} ++ + JobHoldUntil jobHold; + QTime time; + }; +diff --git a/src/printsupport/widgets/qcupsjobwidget.cpp b/src/printsupport/widgets/qcupsjobwidget.cpp +index 7525d7f..dcdb933 100644 +--- a/src/printsupport/widgets/qcupsjobwidget.cpp ++++ b/src/printsupport/widgets/qcupsjobwidget.cpp +@@ -77,6 +77,8 @@ QCupsJobWidget::QCupsJobWidget(QPrinter *printer, QPrintDevice *printDevice, QWi + initJobBilling(); + initJobPriority(); + initBannerPages(); ++ ++ updateSavedValues(); + } + + QCupsJobWidget::~QCupsJobWidget() +@@ -91,6 +93,27 @@ void QCupsJobWidget::setupPrinter() + QCUPSSupport::setBannerPages(m_printer, startBannerPage(), endBannerPage()); + } + ++void QCupsJobWidget::updateSavedValues() ++{ ++ m_savedJobHoldWithTime = { jobHold(), jobHoldTime() }; ++ m_savedJobBilling = jobBilling(); ++ m_savedPriority = jobPriority(); ++ m_savedJobSheets = { startBannerPage(), endBannerPage() }; ++} ++ ++void QCupsJobWidget::revertToSavedValues() ++{ ++ setJobHold(m_savedJobHoldWithTime.jobHold, m_savedJobHoldWithTime.time); ++ toggleJobHoldTime(); ++ ++ setJobBilling(m_savedJobBilling); ++ ++ setJobPriority(m_savedPriority); ++ ++ setStartBannerPage(m_savedJobSheets.startBannerPage); ++ setEndBannerPage(m_savedJobSheets.endBannerPage); ++} ++ + void QCupsJobWidget::initJobHold() + { + m_ui.jobHoldComboBox->addItem(tr("Print Immediately"), QVariant::fromValue(QCUPSSupport::NoHold)); +@@ -154,7 +177,7 @@ void QCupsJobWidget::initJobBilling() + + void QCupsJobWidget::setJobBilling(const QString &jobBilling) + { +- m_ui.jobBillingLineEdit->insert(jobBilling); ++ m_ui.jobBillingLineEdit->setText(jobBilling); + } + + QString QCupsJobWidget::jobBilling() const +diff --git a/src/printsupport/widgets/qcupsjobwidget_p.h b/src/printsupport/widgets/qcupsjobwidget_p.h +index dcec27a..4b6b047 100644 +--- a/src/printsupport/widgets/qcupsjobwidget_p.h ++++ b/src/printsupport/widgets/qcupsjobwidget_p.h +@@ -75,6 +75,8 @@ public: + explicit QCupsJobWidget(QPrinter *printer, QPrintDevice *printDevice, QWidget *parent = nullptr); + ~QCupsJobWidget(); + void setupPrinter(); ++ void updateSavedValues(); ++ void revertToSavedValues(); + + private Q_SLOTS: + void toggleJobHoldTime(); +@@ -106,6 +108,11 @@ private: + QPrintDevice *m_printDevice; + Ui::QCupsJobWidget m_ui; + ++ QCUPSSupport::JobHoldUntilWithTime m_savedJobHoldWithTime; ++ QString m_savedJobBilling; ++ int m_savedPriority; ++ QCUPSSupport::JobSheets m_savedJobSheets; ++ + Q_DISABLE_COPY(QCupsJobWidget) + }; + +-- +2.7.4 + diff --git a/0013-cups-Dont-show-InstallableOptions-in-the-advanced-properties-tab.patch b/0013-cups-Dont-show-InstallableOptions-in-the-advanced-properties-tab.patch new file mode 100644 index 0000000..e2647ce --- /dev/null +++ b/0013-cups-Dont-show-InstallableOptions-in-the-advanced-properties-tab.patch @@ -0,0 +1,70 @@ +From bf59032d704f1163befc05e258a7f65887626add Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +Date: Wed, 27 Dec 2017 15:13:33 +0100 +Subject: [PATCH 1/1] cups: Don't show InstallableOptions in the advanced + properties + +According to CUPS maintainer it is recommended to not show them[1]. +GTK and Libreoffice behave like that. + +[1] https://lists.cups.org/pipermail/cups/2015-September/027124.html + +Change-Id: I82614003490554d41e38a125d44e3a599c2e7342 +Reviewed-by: Andy Shaw +--- + src/printsupport/dialogs/qprintdialog_unix.cpp | 25 +++++++++++++++++-------- + 1 file changed, 17 insertions(+), 8 deletions(-) + +diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp +index 29000bf..3a89c9e 100644 +--- a/src/printsupport/dialogs/qprintdialog_unix.cpp ++++ b/src/printsupport/dialogs/qprintdialog_unix.cpp +@@ -1148,6 +1148,11 @@ void QUnixPrintWidget::updatePrinter() + + #if QT_CONFIG(cups) + ++static bool isBlacklistedGroup(ppd_group_t *group) Q_DECL_NOTHROW ++{ ++ return qstrcmp(group->name, "InstallableOptions") == 0; ++}; ++ + QPPDOptionsModel::QPPDOptionsModel(QPrintDevice *currentPrintDevice, QObject *parent) + : QAbstractItemModel(parent) + , m_currentPrintDevice(currentPrintDevice) +@@ -1159,10 +1164,12 @@ QPPDOptionsModel::QPPDOptionsModel(QPrintDevice *currentPrintDevice, QObject *pa + if (ppd) { + m_cupsCodec = QTextCodec::codecForName(ppd->lang_encoding); + for (int i = 0; i < ppd->num_groups; ++i) { +- QOptionTreeItem *group = new QOptionTreeItem(QOptionTreeItem::Group, i, &ppd->groups[i], m_rootItem); +- m_rootItem->childItems.append(group); +- parseGroups(group); // parse possible subgroups +- parseOptions(group); // parse options ++ if (!isBlacklistedGroup(&ppd->groups[i])) { ++ QOptionTreeItem *group = new QOptionTreeItem(QOptionTreeItem::Group, i, &ppd->groups[i], m_rootItem); ++ m_rootItem->childItems.append(group); ++ parseGroups(group); // parse possible subgroups ++ parseOptions(group); // parse options ++ } + } + } + +@@ -1322,10 +1329,12 @@ void QPPDOptionsModel::parseGroups(QOptionTreeItem *parent) + + if (group) { + for (int i = 0; i < group->num_subgroups; ++i) { +- QOptionTreeItem *subgroup = new QOptionTreeItem(QOptionTreeItem::Group, i, &group->subgroups[i], parent); +- parent->childItems.append(subgroup); +- parseGroups(subgroup); // parse possible subgroups +- parseOptions(subgroup); // parse options ++ if (!isBlacklistedGroup(&group->subgroups[i])) { ++ QOptionTreeItem *subgroup = new QOptionTreeItem(QOptionTreeItem::Group, i, &group->subgroups[i], parent); ++ parent->childItems.append(subgroup); ++ parseGroups(subgroup); // parse possible subgroups ++ parseOptions(subgroup); // parse options ++ } + } + } + } +-- +2.7.4 + diff --git a/0014-CUPS-Enable-printing-arbitrary-pages-and-page-ranges.patch b/0014-CUPS-Enable-printing-arbitrary-pages-and-page-ranges.patch new file mode 100644 index 0000000..90b3044 --- /dev/null +++ b/0014-CUPS-Enable-printing-arbitrary-pages-and-page-ranges.patch @@ -0,0 +1,328 @@ +From 608301d4c81ce65804a088aaebbd5433a56d69d7 Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +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 +--- + 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> 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(), [](std::pair it1, std::pair 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 +@@ -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 @@ + + 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 + + +@@ -119,6 +146,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. ++ ++ ++ ++ ++ ++ + + + Current Page +@@ -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 + + + +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 + { diff --git a/0015-CUPS-Dont-show-choices-that-conflict-with-the-printer-installed-options.patch b/0015-CUPS-Dont-show-choices-that-conflict-with-the-printer-installed-options.patch new file mode 100644 index 0000000..76ee6af --- /dev/null +++ b/0015-CUPS-Dont-show-choices-that-conflict-with-the-printer-installed-options.patch @@ -0,0 +1,237 @@ +From c45947aeefa1a83eda767edca4fd4c6f9404d3ff Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +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 +--- + 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 ¶ms) 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 ¶ms) 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(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(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(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(index.model()); + for (auto *childItem : qAsConst(itm->childItems)) { + const ppd_choice_t *choice = static_cast(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(editor); + QOptionTreeItemOption *itm = static_cast(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(itm->ptr); + QPPDOptionsModel *m = static_cast(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 ¶ms) const ++{ ++ Q_UNUSED(key) ++ Q_UNUSED(params) ++ ++ return false; ++} ++ + QList 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 ¶ms) const; + + #ifndef QT_NO_MIMETYPE + virtual QList 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 ¶ms) const ++{ ++ return isValid() ? d->isFeatureAvailable(key, params) : false; ++} ++ + #ifndef QT_NO_MIMETYPE + QList 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 ¶ms) const; + + #ifndef QT_NO_MIMETYPE + QList supportedMimeTypes() const; +-- +2.7.4 + diff --git a/0016-CUPS-Rework-set-clearCupsOption-API.patch b/0016-CUPS-Rework-set-clearCupsOption-API.patch new file mode 100644 index 0000000..093ab20 --- /dev/null +++ b/0016-CUPS-Rework-set-clearCupsOption-API.patch @@ -0,0 +1,192 @@ +From e35878bf57f4107fa1a49a8a4d552ea5ce1b53a9 Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +Date: Thu, 28 Dec 2017 17:51:43 +0100 +Subject: [PATCH 1/1] CUPS: Rework set/clearCupsOption API + +Previously it was a bit awkward to use, you had to do + QStringList cupsOptions = QCUPSSupport::cupsOptionsList(printer); + QCUPSSupport::setCupsOption(cupsOptions, option, value); + QCUPSSupport::setCupsOptions(printer, cupsOptions); +now you simply have to do + QCUPSSupport::setCupsOption(printer, option, value); + +Change-Id: Id31583f1ec72644791d82776debbae5583a2be54 +Reviewed-by: Andy Shaw +--- + src/printsupport/dialogs/qprintdialog_unix.cpp | 4 +-- + src/printsupport/kernel/qcups.cpp | 44 ++++++++++---------------- + src/printsupport/kernel/qcups_p.h | 6 ++-- + 3 files changed, 20 insertions(+), 34 deletions(-) + +diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp +index 47e2fa5..ab38c24 100644 +--- a/src/printsupport/dialogs/qprintdialog_unix.cpp ++++ b/src/printsupport/dialogs/qprintdialog_unix.cpp +@@ -1417,9 +1417,7 @@ void QPPDOptionsModel::setCupsOptionsFromItems(QPrinter *printer, QOptionTreeIte + QOptionTreeItemOption *itmOption = static_cast(itm); + const ppd_option_t *opt = static_cast(itm->ptr); + if (qstrcmp(opt->defchoice, opt->choices[itmOption->selected].choice) != 0) { +- QStringList cupsOptions = QCUPSSupport::cupsOptionsList(printer); +- QCUPSSupport::setCupsOption(cupsOptions, QString::fromLatin1(opt->keyword), QString::fromLatin1(opt->choices[itmOption->selected].choice)); +- QCUPSSupport::setCupsOptions(printer, cupsOptions); ++ QCUPSSupport::setCupsOption(printer, QString::fromLatin1(opt->keyword), QString::fromLatin1(opt->choices[itmOption->selected].choice)); + } + } else { + setCupsOptionsFromItems(printer, itm); +diff --git a/src/printsupport/kernel/qcups.cpp b/src/printsupport/kernel/qcups.cpp +index 115ecb0..be170ed 100644 +--- a/src/printsupport/kernel/qcups.cpp ++++ b/src/printsupport/kernel/qcups.cpp +@@ -43,33 +43,37 @@ + + QT_BEGIN_NAMESPACE + +-QStringList QCUPSSupport::cupsOptionsList(QPrinter *printer) ++static QStringList cupsOptionsList(QPrinter *printer) Q_DECL_NOTHROW + { + return printer->printEngine()->property(PPK_CupsOptions).toStringList(); + } + +-void QCUPSSupport::setCupsOptions(QPrinter *printer, const QStringList &cupsOptions) ++void setCupsOptions(QPrinter *printer, const QStringList &cupsOptions) Q_DECL_NOTHROW + { + printer->printEngine()->setProperty(PPK_CupsOptions, QVariant(cupsOptions)); + } + +-void QCUPSSupport::setCupsOption(QStringList &cupsOptions, const QString &option, const QString &value) ++void QCUPSSupport::setCupsOption(QPrinter *printer, const QString &option, const QString &value) + { ++ QStringList cupsOptions = cupsOptionsList(printer); + if (cupsOptions.contains(option)) { + cupsOptions.replace(cupsOptions.indexOf(option) + 1, value); + } else { + cupsOptions.append(option); + cupsOptions.append(value); + } ++ setCupsOptions(printer, cupsOptions); + } + +-void QCUPSSupport::clearCupsOption(QStringList &cupsOptions, const QString &option) ++void QCUPSSupport::clearCupsOption(QPrinter *printer, const QString &option) + { ++ QStringList cupsOptions = cupsOptionsList(printer); + // ### use const_iterator once QList::erase takes them + const QStringList::iterator it = std::find(cupsOptions.begin(), cupsOptions.end(), option); + if (it != cupsOptions.end()) { + Q_ASSERT(it + 1 < cupsOptions.end()); + cupsOptions.erase(it, it+1); ++ setCupsOptions(printer, cupsOptions); + } + } + +@@ -140,30 +144,24 @@ QCUPSSupport::JobHoldUntilWithTime QCUPSSupport::parseJobHoldUntil(const QString + + void QCUPSSupport::setJobHold(QPrinter *printer, const JobHoldUntil jobHold, const QTime &holdUntilTime) + { +- QStringList cupsOptions = cupsOptionsList(printer); + const QString jobHoldUntilArgument = jobHoldToString(jobHold, holdUntilTime); + if (!jobHoldUntilArgument.isEmpty()) { +- setCupsOption(cupsOptions, ++ setCupsOption(printer, + QStringLiteral("job-hold-until"), + jobHoldUntilArgument); + } else { +- clearCupsOption(cupsOptions, QStringLiteral("job-hold-until")); ++ clearCupsOption(printer, QStringLiteral("job-hold-until")); + } +- setCupsOptions(printer, cupsOptions); + } + + void QCUPSSupport::setJobBilling(QPrinter *printer, const QString &jobBilling) + { +- QStringList cupsOptions = cupsOptionsList(printer); +- setCupsOption(cupsOptions, QStringLiteral("job-billing"), jobBilling); +- setCupsOptions(printer, cupsOptions); ++ setCupsOption(printer, QStringLiteral("job-billing"), jobBilling); + } + + void QCUPSSupport::setJobPriority(QPrinter *printer, int priority) + { +- QStringList cupsOptions = cupsOptionsList(printer); +- setCupsOption(cupsOptions, QStringLiteral("job-priority"), QString::number(priority)); +- setCupsOptions(printer, cupsOptions); ++ setCupsOption(printer, QStringLiteral("job-priority"), QString::number(priority)); + } + + static inline QString bannerPageToString(const QCUPSSupport::BannerPage bannerPage) +@@ -209,17 +207,14 @@ QCUPSSupport::JobSheets QCUPSSupport::parseJobSheets(const QString &jobSheets) + + void QCUPSSupport::setBannerPages(QPrinter *printer, const BannerPage startBannerPage, const BannerPage endBannerPage) + { +- QStringList cupsOptions = cupsOptionsList(printer); + const QString startBanner = bannerPageToString(startBannerPage); + const QString endBanner = bannerPageToString(endBannerPage); + +- setCupsOption(cupsOptions, QStringLiteral("job-sheets"), startBanner + QLatin1Char(',') + endBanner); +- setCupsOptions(printer, cupsOptions); ++ setCupsOption(printer, QStringLiteral("job-sheets"), startBanner + QLatin1Char(',') + endBanner); + } + + void QCUPSSupport::setPageSet(QPrinter *printer, const PageSet pageSet) + { +- QStringList cupsOptions = cupsOptionsList(printer); + QString pageSetString; + + switch (pageSet) { +@@ -234,22 +229,19 @@ void QCUPSSupport::setPageSet(QPrinter *printer, const PageSet pageSet) + break; + } + +- setCupsOption(cupsOptions, QStringLiteral("page-set"), pageSetString); +- setCupsOptions(printer, cupsOptions); ++ setCupsOption(printer, QStringLiteral("page-set"), pageSetString); + } + + void QCUPSSupport::setPagesPerSheetLayout(QPrinter *printer, const PagesPerSheet pagesPerSheet, + const PagesPerSheetLayout pagesPerSheetLayout) + { +- QStringList cupsOptions = cupsOptionsList(printer); + // WARNING: the following trick (with a [2]-extent) only works as + // WARNING: long as there's only one two-digit number in the list + // WARNING: and it is the last one (before the "\0")! + static const char pagesPerSheetData[][2] = { "1", "2", "4", "6", "9", {'1', '6'}, "\0" }; + static const char pageLayoutData[][5] = {"lrtb", "lrbt", "rlbt", "rltb", "btlr", "btrl", "tblr", "tbrl"}; +- setCupsOption(cupsOptions, QStringLiteral("number-up"), QLatin1String(pagesPerSheetData[pagesPerSheet])); +- setCupsOption(cupsOptions, QStringLiteral("number-up-layout"), QLatin1String(pageLayoutData[pagesPerSheetLayout])); +- setCupsOptions(printer, cupsOptions); ++ setCupsOption(printer, QStringLiteral("number-up"), QLatin1String(pagesPerSheetData[pagesPerSheet])); ++ setCupsOption(printer, QStringLiteral("number-up-layout"), QLatin1String(pageLayoutData[pagesPerSheetLayout])); + } + + void QCUPSSupport::setPageRange(QPrinter *printer, int pageFrom, int pageTo) +@@ -259,9 +251,7 @@ void QCUPSSupport::setPageRange(QPrinter *printer, int pageFrom, int pageTo) + + void QCUPSSupport::setPageRange(QPrinter *printer, const QString &pageRange) + { +- QStringList cupsOptions = cupsOptionsList(printer); +- setCupsOption(cupsOptions, QStringLiteral("page-ranges"), pageRange); +- setCupsOptions(printer, cupsOptions); ++ setCupsOption(printer, QStringLiteral("page-ranges"), pageRange); + } + + QT_END_NAMESPACE +diff --git a/src/printsupport/kernel/qcups_p.h b/src/printsupport/kernel/qcups_p.h +index a5af4bc..0afa7fa 100644 +--- a/src/printsupport/kernel/qcups_p.h ++++ b/src/printsupport/kernel/qcups_p.h +@@ -129,10 +129,8 @@ public: + TopToBottomRightToLeft + }; + +- static QStringList cupsOptionsList(QPrinter *printer); +- static void setCupsOptions(QPrinter *printer, const QStringList &cupsOptions); +- static void setCupsOption(QStringList &cupsOptions, const QString &option, const QString &value); +- static void clearCupsOption(QStringList &cupsOptions, const QString &option); ++ static void setCupsOption(QPrinter *printer, const QString &option, const QString &value); ++ static void clearCupsOption(QPrinter *printer, const QString &option); + + static void setJobHold(QPrinter *printer, const JobHoldUntil jobHold = NoHold, const QTime &holdUntilTime = QTime()); + static void setJobBilling(QPrinter *printer, const QString &jobBilling = QString()); +-- +2.7.4 + diff --git a/0017-Cups-Print-Dialog-Change-the-message-box-titles-to-C.patch b/0017-Cups-Print-Dialog-Change-the-message-box-titles-to-C.patch new file mode 100644 index 0000000..ded119b --- /dev/null +++ b/0017-Cups-Print-Dialog-Change-the-message-box-titles-to-C.patch @@ -0,0 +1,40 @@ +From 6e4a330d615e5d35931658023a30cc375bcfd0e5 Mon Sep 17 00:00:00 2001 +From: Friedemann Kleint +Date: Wed, 17 Jan 2018 11:42:58 +0100 +Subject: [PATCH] Cups Print Dialog: Change the message box titles to Caps + +Amends 608301d4c81ce65804a088aaebbd5433a56d69d7. + +Task-number: QTBUG-1311 +Change-Id: I01cd60f0676f4e0501d411151492b4f867653053 +Reviewed-by: Albert Astals Cid +Reviewed-by: Andy Shaw +--- + src/printsupport/dialogs/qprintdialog_unix.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp +index cac3e9ebcb..2cc5bfbb8c 100644 +--- a/src/printsupport/dialogs/qprintdialog_unix.cpp ++++ b/src/printsupport/dialogs/qprintdialog_unix.cpp +@@ -441,7 +441,7 @@ void QPrintPropertiesDialog::accept() + #if QT_CONFIG(cups) + if (m_cupsOptionsModel->hasConflicts()) { + widget.tabs->setCurrentWidget(widget.cupsPropertiesPage); +- const QMessageBox::StandardButton answer = QMessageBox::warning(this, tr("Advanced option conflicts"), ++ const QMessageBox::StandardButton answer = QMessageBox::warning(this, tr("Advanced Option Conflicts"), + tr("There are conflicts in some advanced options. Do you want to fix them?"), + QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); + if (answer != QMessageBox::No) +@@ -916,7 +916,7 @@ 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"), ++ 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()), +-- +2.15.1 + diff --git a/0018-Fix-build-due-to-missing-QDebug-include.patch b/0018-Fix-build-due-to-missing-QDebug-include.patch new file mode 100644 index 0000000..b12e2c4 --- /dev/null +++ b/0018-Fix-build-due-to-missing-QDebug-include.patch @@ -0,0 +1,28 @@ +From a79d9da8e0bbc69053d00dd1ff1dd55c47258291 Mon Sep 17 00:00:00 2001 +From: =?utf8?q?S=C3=A9rgio=20Martins?= +Date: Mon, 8 Jan 2018 15:58:57 +0000 +Subject: [PATCH] Fix build due to missing QDebug include + +The build just passes on Qt CI by chance. + +Change-Id: I3bfef12b48df22fa64d92af9cd345bfc984c9923 +Reviewed-by: David Faure +--- + src/printsupport/dialogs/qprintdialog_unix.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp +index fcb53f4..02d6903 100644 +--- a/src/printsupport/dialogs/qprintdialog_unix.cpp ++++ b/src/printsupport/dialogs/qprintdialog_unix.cpp +@@ -48,6 +48,7 @@ + #if QT_CONFIG(filedialog) + #include "qfiledialog.h" + #endif ++#include + #include + #include + #include +-- +2.7.4 + diff --git a/libqt5-qtbase.changes b/libqt5-qtbase.changes index 242384d..3ff0509 100644 --- a/libqt5-qtbase.changes +++ b/libqt5-qtbase.changes @@ -1,3 +1,50 @@ +------------------------------------------------------------------- +Fri Feb 2 08:10:28 UTC 2018 - alarrosa@suse.com + +- Add 0001-QSimpleDrag-Fix-mouse-release-coords-for-delayed-eve.patch + to fix a bug causing the wrong desktop icon to look hovered + after dragging an icon on the desktop in plasma (QTBUG-66103). + +------------------------------------------------------------------- +Fri Jan 26 11:21:54 UTC 2018 - alarrosa@suse.com + +- Moved 0001-Avoid-providing-bad-pixelDeltas-on-X11.patch to use a patch + number in the 1000-1999 range since it was approved in the 5.9 branch + upstream. + +------------------------------------------------------------------- +Fri Jan 26 10:08:04 UTC 2018 - alarrosa@suse.com + +- Add 0001-Avoid-providing-bad-pixelDeltas-on-X11.patch to avoid using + the hardcoded resolution that libinput is giving as a real pixel + delta (QTBUG-59261). + +------------------------------------------------------------------- +Tue Jan 25 10:13:15 UTC 2018 - alarrosa@suse.com + +- Add patches to fix the custom page size handling in the print dialog as + well as other printer issues (QTBUG-58733, boo#994809): + * 0002-CUPS-Use-default-cups-job-priority-instead-of-50.patch + * 0003-QPageSetupWidget-setPrinter-Use-printdevice-default-paper-size.patch + * 0004-Fix-custom-page-size-handling-in-the-Unix-print-dial.patch + * 0005-CUPS-Refactor-the-code-a-bit.patch + * 0006-Refactor-QPPDOptionsModel-a-bit.patch + * 0007-CUPS-Fix-advanced-options-cancel-of-the-print-properties-dialog.patch + * 0008-CUPS-Fix-conflict-handling.patch + * 0009-CUPS-Use-printer-job-sheets-as-default-instead-of-none-none.patch + * 0010-CUPS-Use-printer-job-billing-as-default-instead-of-the-empty-string.patch + * 0011-CUPS-Use-printer-job-hold-until-as-default-instead-of-the-nohold.patch + * 0012-Unix-Fix-usability-of-the-print-properties-dialog.patch + * 0013-cups-Dont-show-InstallableOptions-in-the-advanced-properties-tab.patch + * 0014-CUPS-Enable-printing-arbitrary-pages-and-page-ranges.patch + * 0015-CUPS-Dont-show-choices-that-conflict-with-the-printer-installed-options.patch + * 0016-CUPS-Rework-set-clearCupsOption-API.patch + * 0017-Cups-Print-Dialog-Change-the-message-box-titles-to-C.patch + * 0018-Fix-build-due-to-missing-QDebug-include.patch + +- Dropped 0001-Fix-custom-page-size-handling-in-the-Unix-print-dial.patch + which is now included in the previous patchset with order 0004. + ------------------------------------------------------------------- Fri Dec 29 18:19:46 UTC 2017 - fabian@ritter-vogt.de diff --git a/libqt5-qtbase.spec b/libqt5-qtbase.spec index 923f976..1a821aa 100644 --- a/libqt5-qtbase.spec +++ b/libqt5-qtbase.spec @@ -67,6 +67,8 @@ Patch15: force-cmake-private-headers.patch Patch17: qapplication-emit-palettechanged.patch # patches 1000- 2000 and above from upstream 5.10 branch # Patch1000: 0001-xcb-verify-if-xrandr-present-before-using-xcb_randr-.patch +Patch1001: 0001-Avoid-providing-bad-pixelDeltas-on-X11.patch +Patch1002: 0001-QSimpleDrag-Fix-mouse-release-coords-for-delayed-eve.patch # patches 2000-3000 and above from upstream 5.11/dev branch # Patch2000: 0001-Remove-QPrintDialogPrivate-applyPrinterProperties-no.patch Patch2001: 0002-Remove-QUnixPrintWidgetPrivate-applyPrinterPropertie.patch @@ -79,7 +81,23 @@ Patch2007: 0008-Allow-access-to-ppd-file-and-ppdMarkOption-via-QPpdP.patch Patch2008: 0009-QPlatformPrintDevice-use-QVector-not-QList-in-the-AP.patch Patch2009: 0010-Reintroduce-the-Advanced-tab-in-the-QPrintProperties.patch Patch2010: 0011-QtPrintSupport-Fix-build.patch -Patch2011: 0001-Fix-custom-page-size-handling-in-the-Unix-print-dial.patch +Patch2012: 0002-CUPS-Use-default-cups-job-priority-instead-of-50.patch +Patch2013: 0003-QPageSetupWidget-setPrinter-Use-printdevice-default-paper-size.patch +Patch2014: 0004-Fix-custom-page-size-handling-in-the-Unix-print-dial.patch +Patch2015: 0005-CUPS-Refactor-the-code-a-bit.patch +Patch2016: 0006-Refactor-QPPDOptionsModel-a-bit.patch +Patch2017: 0007-CUPS-Fix-advanced-options-cancel-of-the-print-properties-dialog.patch +Patch2018: 0008-CUPS-Fix-conflict-handling.patch +Patch2019: 0009-CUPS-Use-printer-job-sheets-as-default-instead-of-none-none.patch +Patch2020: 0010-CUPS-Use-printer-job-billing-as-default-instead-of-the-empty-string.patch +Patch2021: 0011-CUPS-Use-printer-job-hold-until-as-default-instead-of-the-nohold.patch +Patch2022: 0012-Unix-Fix-usability-of-the-print-properties-dialog.patch +Patch2023: 0013-cups-Dont-show-InstallableOptions-in-the-advanced-properties-tab.patch +Patch2024: 0014-CUPS-Enable-printing-arbitrary-pages-and-page-ranges.patch +Patch2025: 0015-CUPS-Dont-show-choices-that-conflict-with-the-printer-installed-options.patch +Patch2026: 0016-CUPS-Rework-set-clearCupsOption-API.patch +Patch2027: 0017-Cups-Print-Dialog-Change-the-message-box-titles-to-C.patch +Patch2028: 0018-Fix-build-due-to-missing-QDebug-include.patch BuildRequires: alsa-devel BuildRequires: cups-devel BuildRequires: double-conversion-devel @@ -172,6 +190,8 @@ handling. %patch15 -p1 %patch17 -p1 %patch1000 -p1 +%patch1001 -p1 +%patch1002 -p1 %patch2000 -p1 %patch2001 -p1 %patch2002 -p1 @@ -183,7 +203,23 @@ handling. %patch2008 -p1 %patch2009 -p1 %patch2010 -p1 -%patch2011 -p1 +%patch2012 -p1 +%patch2013 -p1 +%patch2014 -p1 +%patch2015 -p1 +%patch2016 -p1 +%patch2017 -p1 +%patch2018 -p1 +%patch2019 -p1 +%patch2020 -p1 +%patch2021 -p1 +%patch2022 -p1 +%patch2023 -p1 +%patch2024 -p1 +%patch2025 -p1 +%patch2026 -p1 +%patch2027 -p1 +%patch2028 -p1 # be sure not to use them rm -rf src/3rdparty/{libjpeg,freetype,zlib}