Support multiple page ranges in QPrinter
Add a new QRangeCollection type to store and manage multiple page ranges. This moves out the parser and validator logic from the platform dependent (UNIX) dialog and makes it publicly available from QPrinter. This improves the usability of QPrinter in those applications which doesn't use print dialog to configure printer. (e.g.: QTextDocument, QWebEnginePage) Change-Id: I0be5a8a64781c411f83b96a24f216605a84958e5 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io> Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
This commit is contained in:
parent
4c66b75c89
commit
926a0886d1
@ -186,6 +186,7 @@ qt_add_module(Gui
|
||||
painting/qplatformbackingstore.cpp painting/qplatformbackingstore.h
|
||||
painting/qpolygon.cpp painting/qpolygon.h
|
||||
painting/qpolygonclipper_p.h
|
||||
painting/qrangecollection.cpp painting/qrangecollection.h painting/qrangecollection_p.h
|
||||
painting/qrasterdefs_p.h
|
||||
painting/qrasterizer.cpp painting/qrasterizer_p.h
|
||||
painting/qrbtree_p.h
|
||||
|
@ -49,6 +49,8 @@ HEADERS += \
|
||||
painting/qpen.h \
|
||||
painting/qpolygon.h \
|
||||
painting/qpolygonclipper_p.h \
|
||||
painting/qrangecollection.h \
|
||||
painting/qrangecollection_p.h \
|
||||
painting/qrasterdefs_p.h \
|
||||
painting/qrasterizer_p.h \
|
||||
painting/qrbtree_p.h \
|
||||
@ -99,6 +101,7 @@ SOURCES += \
|
||||
painting/qpdfwriter.cpp \
|
||||
painting/qpen.cpp \
|
||||
painting/qpolygon.cpp \
|
||||
painting/qrangecollection.cpp \
|
||||
painting/qrasterizer.cpp \
|
||||
painting/qregion.cpp \
|
||||
painting/qstroker.cpp \
|
||||
|
@ -80,6 +80,7 @@ class QDummyPagedPaintDevicePrivate : public QPagedPaintDevicePrivate
|
||||
|
||||
QPagedPaintDevicePrivate::~QPagedPaintDevicePrivate()
|
||||
{
|
||||
delete rangeCollection;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -53,6 +53,7 @@
|
||||
|
||||
#include <QtGui/private/qtguiglobal_p.h>
|
||||
#include <qpagedpaintdevice.h>
|
||||
#include <qrangecollection.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -60,8 +61,7 @@ class Q_GUI_EXPORT QPagedPaintDevicePrivate
|
||||
{
|
||||
public:
|
||||
QPagedPaintDevicePrivate()
|
||||
: fromPage(0),
|
||||
toPage(0),
|
||||
: rangeCollection(new QRangeCollection),
|
||||
pageOrderAscending(true),
|
||||
printSelectionOnly(false)
|
||||
{
|
||||
@ -83,8 +83,7 @@ public:
|
||||
static inline QPagedPaintDevicePrivate *get(QPagedPaintDevice *pd) { return pd->d; }
|
||||
|
||||
// These are currently required to keep QPrinter functionality working in QTextDocument::print()
|
||||
int fromPage;
|
||||
int toPage;
|
||||
QRangeCollection *rangeCollection;
|
||||
bool pageOrderAscending;
|
||||
bool printSelectionOnly;
|
||||
};
|
||||
|
281
src/gui/painting/qrangecollection.cpp
Normal file
281
src/gui/painting/qrangecollection.cpp
Normal file
@ -0,0 +1,281 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qrangecollection.h"
|
||||
#include "qrangecollection_p.h"
|
||||
|
||||
#include <QtCore/qstack.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
void QRangeCollectionPrivate::mergeIntervals()
|
||||
{
|
||||
const int count = intervals.count();
|
||||
|
||||
if (count <= 0)
|
||||
return;
|
||||
|
||||
std::sort(intervals.begin(), intervals.end());
|
||||
|
||||
QStack<QPair<int, int>> stack;
|
||||
stack.push(intervals[0]);
|
||||
|
||||
for (int i = 1; i < count; i++) {
|
||||
QPair<int, int> &top = stack.top();
|
||||
|
||||
if (top.second < intervals[i].first)
|
||||
stack.push(intervals[i]);
|
||||
else if (top.second < intervals[i].second)
|
||||
top.second = intervals[i].second;
|
||||
}
|
||||
|
||||
std::sort(intervals.begin(), intervals.end());
|
||||
|
||||
intervals = stack;
|
||||
}
|
||||
|
||||
/*!
|
||||
\class QRangeCollection
|
||||
\brief The QRangeCollection class represents a collection of decimal intervals.
|
||||
\inmodule QtGui
|
||||
\ingroup painting
|
||||
\since 6.0
|
||||
|
||||
QRangeCollection manages a set of decimal intervals.
|
||||
|
||||
Use QPrinter::rangeCollection() to access the collection of page ranges
|
||||
associated with a QPrinter.
|
||||
*/
|
||||
|
||||
QRangeCollection::QRangeCollection()
|
||||
: d_ptr(new QRangeCollectionPrivate(this))
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Destroys the collection.
|
||||
*/
|
||||
QRangeCollection::~QRangeCollection()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Inserts a single number into the collection.
|
||||
*/
|
||||
void QRangeCollection::addPage(int pageNumber)
|
||||
{
|
||||
Q_D(QRangeCollection);
|
||||
if (pageNumber <= 0) {
|
||||
qWarning("QRangeCollection::addPage: 'pageNumber' must be greater than 0");
|
||||
return;
|
||||
}
|
||||
d->intervals.append(qMakePair(pageNumber, pageNumber));
|
||||
d->mergeIntervals();
|
||||
}
|
||||
|
||||
/*!
|
||||
Inserts a range into the collection.
|
||||
*/
|
||||
void QRangeCollection::addRange(int from, int to)
|
||||
{
|
||||
Q_D(QRangeCollection);
|
||||
if (from <= 0 || to <= 0) {
|
||||
qWarning("QRangeCollection::addRange: 'from' and 'to' must be greater than 0");
|
||||
return;
|
||||
}
|
||||
if (to < from) {
|
||||
qWarning("QRangeCollection::addRange: 'from' must be less than or equal to 'to'");
|
||||
std::swap(from, to);
|
||||
}
|
||||
d->intervals.append(qMakePair(from, to));
|
||||
d->mergeIntervals();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a list with the values of the ranges used in this collection.
|
||||
*/
|
||||
QList<QPair<int, int>> QRangeCollection::toList() const
|
||||
{
|
||||
Q_D(const QRangeCollection);
|
||||
return d->intervals.toList();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Removes all ranges from this collection.
|
||||
*/
|
||||
void QRangeCollection::clear()
|
||||
{
|
||||
Q_D(QRangeCollection);
|
||||
d->intervals.clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs the range collection from a string representation.
|
||||
|
||||
\code
|
||||
QPrinter printer;
|
||||
printer->rangeCollection()->parse("1-3,6-7");
|
||||
\endcode
|
||||
*/
|
||||
bool QRangeCollection::parse(const QString &ranges)
|
||||
{
|
||||
Q_D(QRangeCollection);
|
||||
const QStringList items = ranges.split(',');
|
||||
for (const QString &item : items) {
|
||||
if (item.isEmpty()) {
|
||||
d->intervals.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item.contains(QLatin1Char('-'))) {
|
||||
const QStringList rangeItems = item.split('-');
|
||||
if (rangeItems.count() != 2) {
|
||||
d->intervals.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ok;
|
||||
const int number1 = rangeItems[0].toInt(&ok);
|
||||
if (!ok) {
|
||||
d->intervals.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
const int number2 = rangeItems[1].toInt(&ok);
|
||||
if (!ok) {
|
||||
d->intervals.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (number1 < 1 || number2 < 1 || number2 < number1) {
|
||||
d->intervals.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
d->intervals.append(qMakePair(number1, number2));
|
||||
|
||||
} else {
|
||||
bool ok;
|
||||
const int number = item.toInt(&ok);
|
||||
if (!ok) {
|
||||
d->intervals.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (number < 1) {
|
||||
d->intervals.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
d->intervals.append(qMakePair(number, number));
|
||||
}
|
||||
}
|
||||
|
||||
d->mergeIntervals();
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the string representation of the ranges in the collection.
|
||||
*/
|
||||
QString QRangeCollection::toString() const
|
||||
{
|
||||
Q_D(const QRangeCollection);
|
||||
QString result;
|
||||
|
||||
for (const QPair<int, int> &pair : d->intervals) {
|
||||
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;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if the collection contains an occurrence
|
||||
or a bounding range of \a pageNumber; otherwise returns
|
||||
\c false.
|
||||
*/
|
||||
bool QRangeCollection::contains(int pageNumber) const
|
||||
{
|
||||
Q_D(const QRangeCollection);
|
||||
for (const QPair<int, int> &pair : d->intervals) {
|
||||
if (pair.first <= pageNumber && pair.second >= pageNumber)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if the collection is empty; otherwise returns \c false.
|
||||
*/
|
||||
bool QRangeCollection::isEmpty() const
|
||||
{
|
||||
Q_D(const QRangeCollection);
|
||||
return d->intervals.isEmpty();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the index of the first page covered by the range collection.
|
||||
*/
|
||||
int QRangeCollection::firstPage() const
|
||||
{
|
||||
Q_D(const QRangeCollection);
|
||||
if (d->intervals.isEmpty())
|
||||
return 0;
|
||||
return d->intervals.first().first;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the index of the last page covered by the range collection.
|
||||
*/
|
||||
int QRangeCollection::lastPage() const
|
||||
{
|
||||
Q_D(const QRangeCollection);
|
||||
if (d->intervals.isEmpty())
|
||||
return 0;
|
||||
return d->intervals.last().second;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
78
src/gui/painting/qrangecollection.h
Normal file
78
src/gui/painting/qrangecollection.h
Normal file
@ -0,0 +1,78 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QRANGECOLLECTION_H
|
||||
#define QRANGECOLLECTION_H
|
||||
|
||||
#include <QtGui/qtguiglobal.h>
|
||||
#include <QtCore/qpair.h>
|
||||
#include <QtCore/qscopedpointer.h>
|
||||
#include <QtCore/qvector.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QRangeCollectionPrivate;
|
||||
|
||||
class Q_GUI_EXPORT QRangeCollection
|
||||
{
|
||||
Q_DECLARE_PRIVATE(QRangeCollection)
|
||||
public:
|
||||
explicit QRangeCollection();
|
||||
~QRangeCollection();
|
||||
|
||||
void addPage(int pageNumber);
|
||||
void addRange(int from, int to);
|
||||
QList<QPair<int, int>> toList() const;
|
||||
void clear();
|
||||
|
||||
bool parse(const QString &ranges);
|
||||
QString toString() const;
|
||||
|
||||
bool contains(const int pageNumber) const;
|
||||
bool isEmpty() const;
|
||||
int firstPage() const;
|
||||
int lastPage() const;
|
||||
|
||||
private:
|
||||
QScopedPointer<QRangeCollectionPrivate> d_ptr;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QRANGECOLLECTION_H
|
76
src/gui/painting/qrangecollection_p.h
Normal file
76
src/gui/painting/qrangecollection_p.h
Normal file
@ -0,0 +1,76 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QRANGECOLLECTION_P_H
|
||||
#define QRANGECOLLECTION_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
|
||||
#include <QtGui/private/qtguiglobal_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class Q_GUI_EXPORT QRangeCollectionPrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(QRangeCollection)
|
||||
public:
|
||||
QRangeCollectionPrivate(QRangeCollection *rangeCollection)
|
||||
: q_ptr(rangeCollection)
|
||||
{
|
||||
}
|
||||
|
||||
void mergeIntervals();
|
||||
|
||||
QVector<QPair<int, int>> intervals;
|
||||
QRangeCollection *q_ptr;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QRANGECOLLECTION_P_H
|
@ -1928,8 +1928,9 @@ void QTextDocument::print(QPagedPaintDevice *printer) const
|
||||
clonedDoc->setPageSize(body.size());
|
||||
}
|
||||
|
||||
int fromPage = pd->fromPage;
|
||||
int toPage = pd->toPage;
|
||||
QRangeCollection *rangeCollection = pd->rangeCollection;
|
||||
int fromPage = rangeCollection->firstPage();
|
||||
int toPage = rangeCollection->lastPage();
|
||||
|
||||
if (fromPage == 0 && toPage == 0) {
|
||||
fromPage = 1;
|
||||
@ -1955,7 +1956,8 @@ void QTextDocument::print(QPagedPaintDevice *printer) const
|
||||
|
||||
int page = fromPage;
|
||||
while (true) {
|
||||
printPage(page, &p, doc, body, pageNumberPos);
|
||||
if (rangeCollection->isEmpty() || rangeCollection->contains(page))
|
||||
printPage(page, &p, doc, body, pageNumberPos);
|
||||
|
||||
if (page == toPage)
|
||||
break;
|
||||
|
@ -59,6 +59,7 @@
|
||||
#include <QtWidgets/qstyleditemdelegate.h>
|
||||
#include <QtWidgets/qformlayout.h>
|
||||
#include <QtPrintSupport/qprinter.h>
|
||||
#include <QtGui/qrangecollection.h>
|
||||
|
||||
#include <qpa/qplatformprintplugin.h>
|
||||
#include <qpa/qplatformprintersupport.h>
|
||||
@ -745,85 +746,6 @@ void QPrintDialogPrivate::selectPrinter(const QPrinter::OutputFormat outputForma
|
||||
}
|
||||
|
||||
#if QT_CONFIG(cups)
|
||||
static std::vector<std::pair<int, int>> pageRangesFromString(const QString &pagesString) noexcept
|
||||
{
|
||||
std::vector<std::pair<int, int>> result;
|
||||
const QStringList items = pagesString.split(',');
|
||||
for (const QString &item : items) {
|
||||
if (item.isEmpty())
|
||||
return {};
|
||||
|
||||
if (item.contains(QLatin1Char('-'))) {
|
||||
const QStringList rangeItems = item.split('-');
|
||||
if (rangeItems.count() != 2)
|
||||
return {};
|
||||
|
||||
bool ok;
|
||||
const int number1 = rangeItems[0].toInt(&ok);
|
||||
if (!ok)
|
||||
return {};
|
||||
|
||||
const int number2 = rangeItems[1].toInt(&ok);
|
||||
if (!ok)
|
||||
return {};
|
||||
|
||||
if (number1 < 1 || number2 < 1 || number2 < number1)
|
||||
return {};
|
||||
|
||||
result.push_back(std::make_pair(number1, number2));
|
||||
|
||||
} else {
|
||||
bool ok;
|
||||
const int number = item.toInt(&ok);
|
||||
if (!ok)
|
||||
return {};
|
||||
|
||||
if (number < 1)
|
||||
return {};
|
||||
|
||||
result.push_back(std::make_pair(number, number));
|
||||
}
|
||||
}
|
||||
|
||||
// check no range intersects with the next
|
||||
std::sort(result.begin(), result.end(),
|
||||
[](const std::pair<int, int> &it1, const std::pair<int, int> &it2) { return it1.first < it2.first; });
|
||||
int previousSecond = -1;
|
||||
for (auto pair : result) {
|
||||
if (pair.first <= previousSecond)
|
||||
return {};
|
||||
|
||||
previousSecond = pair.second;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static QString stringFromPageRanges(const std::vector<std::pair<int, int>> &pageRanges) noexcept
|
||||
{
|
||||
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) noexcept
|
||||
{
|
||||
if (pagesString.isEmpty())
|
||||
return false;
|
||||
|
||||
auto pagesRanges = pageRangesFromString(pagesString);
|
||||
return !pagesRanges.empty();
|
||||
}
|
||||
|
||||
void QPrintDialogPrivate::updatePpdDuplexOption(QRadioButton *radio)
|
||||
{
|
||||
@ -894,13 +816,11 @@ 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);
|
||||
p->setPrintRange(QPrinter::PageRange);
|
||||
p->rangeCollection()->parse(options.pagesLineEdit->text());
|
||||
|
||||
// server-side page filtering
|
||||
QCUPSSupport::setPageRange(p, stringFromPageRanges(pageRanges));
|
||||
QCUPSSupport::setPageRange(p, p->rangeCollection()->toString());
|
||||
}
|
||||
|
||||
// page set
|
||||
@ -1100,7 +1020,7 @@ void QPrintDialog::accept()
|
||||
{
|
||||
Q_D(QPrintDialog);
|
||||
#if QT_CONFIG(cups)
|
||||
if (d->options.pagesRadioButton->isChecked() && !isValidPagesString(d->options.pagesLineEdit->text())) {
|
||||
if (d->options.pagesRadioButton->isChecked() && printer()->rangeCollection()->isEmpty()) {
|
||||
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 "
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "qlist.h"
|
||||
#include <qcoreapplication.h>
|
||||
#include <qfileinfo.h>
|
||||
#include <QtGui/qrangecollection.h>
|
||||
|
||||
#include <private/qpagedpaintdevice_p.h>
|
||||
|
||||
@ -1981,12 +1982,12 @@ void QPrinter::setPrinterSelectionOption(const QString &option)
|
||||
\note If fromPage() and toPage() both return 0, this indicates that
|
||||
\e{the whole document will be printed}.
|
||||
|
||||
\sa setFromTo(), toPage()
|
||||
\sa setFromTo(), toPage(), rangeCollection()
|
||||
*/
|
||||
|
||||
int QPrinter::fromPage() const
|
||||
{
|
||||
return d->fromPage;
|
||||
return d->rangeCollection->firstPage();
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -2005,12 +2006,12 @@ int QPrinter::fromPage() const
|
||||
The programmer is responsible for reading this setting and
|
||||
printing accordingly.
|
||||
|
||||
\sa setFromTo(), fromPage()
|
||||
\sa setFromTo(), fromPage(), rangeCollection()
|
||||
*/
|
||||
|
||||
int QPrinter::toPage() const
|
||||
{
|
||||
return d->toPage;
|
||||
return d->rangeCollection->lastPage();
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -2027,17 +2028,25 @@ int QPrinter::toPage() const
|
||||
This function is mostly used to set a default value that the user can
|
||||
override in the print dialog when you call setup().
|
||||
|
||||
\sa fromPage(), toPage()
|
||||
\sa fromPage(), toPage(), rangeCollection()
|
||||
*/
|
||||
|
||||
void QPrinter::setFromTo(int from, int to)
|
||||
{
|
||||
if (from > to) {
|
||||
qWarning("QPrinter::setFromTo: 'from' must be less than or equal to 'to'");
|
||||
from = to;
|
||||
}
|
||||
d->fromPage = from;
|
||||
d->toPage = to;
|
||||
d->rangeCollection->clear();
|
||||
d->rangeCollection->addRange(from, to);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.0
|
||||
|
||||
Returns the range collection associated with this device.
|
||||
|
||||
\sa QRangeCollection, fromPage(), toPage()
|
||||
*/
|
||||
QRangeCollection *QPrinter::rangeCollection()
|
||||
{
|
||||
return d->rangeCollection;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -56,6 +56,7 @@ QT_BEGIN_NAMESPACE
|
||||
#endif
|
||||
|
||||
class QPrinterPrivate;
|
||||
class QRangeCollection;
|
||||
class QPaintEngine;
|
||||
class QPrintEngine;
|
||||
class QPrinterInfo;
|
||||
@ -249,6 +250,8 @@ public:
|
||||
int fromPage() const;
|
||||
int toPage() const;
|
||||
|
||||
QRangeCollection *rangeCollection();
|
||||
|
||||
void setPrintRange(PrintRange range);
|
||||
PrintRange printRange() const;
|
||||
|
||||
|
@ -13,6 +13,7 @@ SUBDIRS=\
|
||||
qpdfwriter \
|
||||
qpen \
|
||||
qpaintengine \
|
||||
qrangecollection \
|
||||
qtransform \
|
||||
qpolygon \
|
||||
|
||||
|
@ -0,0 +1,6 @@
|
||||
CONFIG += testcase
|
||||
TARGET = tst_qrangecollection
|
||||
|
||||
QT += testlib gui-private core-private
|
||||
|
||||
SOURCES += tst_qrangecollection.cpp
|
@ -0,0 +1,75 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
#include <qrangecollection.h>
|
||||
|
||||
typedef QList<QPair<int, int>> PageRangeList;
|
||||
|
||||
class tst_QRangeCollection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void parseFromString_data();
|
||||
void parseFromString();
|
||||
};
|
||||
|
||||
void tst_QRangeCollection::parseFromString_data()
|
||||
{
|
||||
QTest::addColumn<QString>("rangeString");
|
||||
QTest::addColumn<QList<QPair<int, int>>>("rangeList");
|
||||
|
||||
QList<QPair<int, int>> invalid;
|
||||
QTest::newRow("invalid") << QString(",-8")
|
||||
<< invalid;
|
||||
|
||||
QList<QPair<int, int>> overlapping;
|
||||
overlapping << qMakePair(1, 3)
|
||||
<< qMakePair(5, 11);
|
||||
QTest::newRow("overlapping") << QString("1-3,5-9,6-7,8-11")
|
||||
<< overlapping;
|
||||
}
|
||||
|
||||
void tst_QRangeCollection::parseFromString()
|
||||
{
|
||||
QFETCH(QString, rangeString);
|
||||
QFETCH(PageRangeList, rangeList);
|
||||
|
||||
QRangeCollection rangeCollection;
|
||||
rangeCollection.parse(rangeString);
|
||||
QList<QPair<int, int>> result = rangeCollection.toList();
|
||||
QCOMPARE(result.length(), rangeList.length());
|
||||
for (const QPair<int, int> &pair : result) {
|
||||
QVERIFY(rangeList.contains(pair));
|
||||
}
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_QRangeCollection)
|
||||
|
||||
#include "tst_qrangecollection.moc"
|
Loading…
x
Reference in New Issue
Block a user