Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qpageranges.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include "qpageranges.h"
7
8#include <QtCore/qstack.h>
9#include <QtCore/qdebug.h>
10#include <QtCore/qdatastream.h>
11
13
14QT_IMPL_METATYPE_EXTERN(QPageRanges)
15
16void QPageRangesPrivate::mergeIntervals()
17{
18 const int count = intervals.size();
19
20 if (count <= 1)
21 return;
22
23 std::sort(intervals.begin(), intervals.end());
24
25 QStack<QPageRanges::Range> stack;
26 stack.push(intervals[0]);
27
28 for (int i = 1; i < count; ++i) {
29 QPageRanges::Range &top = stack.top();
30
31 if (top.to < intervals[i].from - 1)
32 stack.push(intervals[i]);
33 else if (top.to < intervals[i].to)
34 top.to = intervals[i].to;
35 }
36
37 intervals = stack;
38}
39
40QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QPageRangesPrivate)
41
42/*!
43 \class QPageRanges
44 \brief The QPageRanges class represents a collection of page ranges.
45 \inmodule QtGui
46 \ingroup painting
47 \ingroup printing
48 \ingroup shared
49 \since 6.0
50
51 Use QPagedPaintDevice::pageRanges() to access the collection of page ranges
52 associated with a paged device.
53*/
54
55/*!
56 Constructs an empty QPageRanges object.
57*/
58QPageRanges::QPageRanges() = default;
59
60/*!
61 Constructs a QPageRanges object by copying \a other.
62*/
63QPageRanges::QPageRanges(const QPageRanges &other) noexcept = default;
64
65/*!
66 \fn QPageRanges::QPageRanges(QPageRanges &&other)
67
68 Constructs a QPageRanges object by moving from \a other.
69*/
70
71/*!
72 Destroys the page ranges.
73*/
74QPageRanges::~QPageRanges() = default;
75
76/*!
77 Assigns \a other to this QPageRanges object.
78*/
79QPageRanges &QPageRanges::operator=(const QPageRanges &other) noexcept = default;
80
81/*!
82 \fn QPageRanges &QPageRanges::operator=(QPageRanges &&other)
83 Moves \a other into this QPageRanges object.
84*/
85
86/*!
87 Adds the single page \a pageNumber to the ranges.
88
89 \note Page numbers start with 1. Attempts to add page numbers
90 smaller than 1 will be ignored with a warning.
91*/
92void QPageRanges::addPage(int pageNumber)
93{
94 if (pageNumber <= 0) {
95 qWarning("QPageRanges::addPage: 'pageNumber' must be greater than 0");
96 return;
97 }
98
99 detach();
100 d->intervals.append({ pageNumber, pageNumber });
101 d->mergeIntervals();
102}
103
104/*!
105 Adds the range specified with \a from and \a to to the ranges.
106
107 \note Page numbers start with 1. Attempts to add page numbers
108 smaller than 1 will be ignored with a warning.
109*/
110void QPageRanges::addRange(int from, int to)
111{
112 if (from <= 0 || to <= 0) {
113 qWarning("QPageRanges::addRange: 'from' and 'to' must be greater than 0");
114 return;
115 }
116 if (to < from)
117 std::swap(from, to);
118
119 detach();
120 d->intervals.append({from, to});
121 d->mergeIntervals();
122}
123
124/*!
125 Returns a list with the values of the ranges.
126*/
127QList<QPageRanges::Range> QPageRanges::toRangeList() const
128{
129 if (d)
130 return d->intervals;
131 return QList<QPageRanges::Range>{};
132}
133
134/*!
135 Removes all page ranges.
136*/
137void QPageRanges::clear()
138{
139 d.reset();
140}
141
142/*!
143 Constructs and returns a QPageRanges object populated with the
144 \a ranges from the string representation.
145
146 \code
147 QPrinter printer;
148 QPageRanges ranges = QPageRanges::fromString("1-3,6-7");
149 printer.setPageRanges(ranges);
150 \endcode
151
152 In case of parsing error, returns an empty QPageRanges object.
153
154 \sa isEmpty()
155*/
156QPageRanges QPageRanges::fromString(const QString &ranges)
157{
158 QList<Range> intervals;
159 const QStringList items = ranges.split(u',');
160 for (const QString &item : items) {
161 if (item.isEmpty())
162 return QPageRanges();
163
164 if (item.contains(u'-')) {
165 const QStringList rangeItems = item.split(u'-');
166 if (rangeItems.size() != 2)
167 return QPageRanges();
168
169 bool ok;
170 const int number1 = rangeItems[0].toInt(&ok);
171 if (!ok)
172 return QPageRanges();
173
174 const int number2 = rangeItems[1].toInt(&ok);
175 if (!ok)
176 return QPageRanges();
177
178 if (number1 < 1 || number2 < 1 || number2 < number1)
179 return QPageRanges();
180
181 intervals.append({number1, number2});
182
183 } else {
184 bool ok;
185 const int number = item.toInt(&ok);
186 if (!ok)
187 return QPageRanges();
188
189 if (number < 1)
190 return QPageRanges();
191
192 intervals.append({number, number});
193 }
194 }
195
196 QPageRanges newRanges;
197 newRanges.d.reset(new QPageRangesPrivate);
198 newRanges.d->intervals = intervals;
199 newRanges.d->mergeIntervals();
200 return newRanges;
201}
202
203/*!
204 Returns the string representation of the page ranges.
205*/
206QString QPageRanges::toString() const
207{
208 if (!d)
209 return QString();
210
211 QString result;
212 for (const Range &range : d->intervals) {
213 if (!result.isEmpty())
214 result += u',';
215
216 if (range.from == range.to)
217 result += QString::number(range.from);
218 else
219 result += QStringLiteral("%1-%2").arg(range.from).arg(range.to);
220 }
221
222 return result;
223}
224
225/*!
226 \fn bool QPageRanges::contains(int pageNumber) const
227
228 Returns \c true if the ranges include the page \a pageNumber;
229 otherwise returns \c false.
230*/
231bool QPageRanges::contains(int pageNumber) const
232{
233 if (!d)
234 return false;
235
236 for (const Range &range : d->intervals) {
237 if (range.from <= pageNumber && range.to >= pageNumber)
238 return true;
239 }
240 return false;
241}
242
243/*!
244 Returns \c true if the ranges are empty; otherwise returns \c false.
245*/
246bool QPageRanges::isEmpty() const
247{
248 return !d || d->intervals.isEmpty();
249}
250
251/*!
252 Returns the index of the first page covered by the page ranges,
253 or 0 if the page ranges are empty.
254*/
255int QPageRanges::firstPage() const
256{
257 if (isEmpty())
258 return 0;
259 return d->intervals.constFirst().from;
260}
261
262/*!
263 Returns the index of the last page covered by the page ranges,
264 or 0 if the page ranges are empty.
265*/
266int QPageRanges::lastPage() const
267{
268 if (isEmpty())
269 return 0;
270 return d->intervals.constLast().to;
271}
272
273/*!
274 \internal
275*/
276bool QPageRanges::isEqual(const QPageRanges &other) const noexcept
277{
278 if (d == other.d)
279 return true;
280 if (!d || !other.d)
281 return false;
282 return d->intervals == other.d->intervals;
283}
284
285/*!
286 \internal
287*/
288void QPageRanges::detach()
289{
290 if (d)
291 d.detach();
292 else
293 d.reset(new QPageRangesPrivate);
294}
295
296#if !defined(QT_NO_DATASTREAM)
297/*!
298 \fn QDataStream &operator<<(QDataStream &stream, const QPageRanges &pageRanges)
299 \relates QPageRanges
300
301 Writes \a pageRanges to \a stream as a range string.
302
303 \sa QPageRanges::toString
304*/
305
306QDataStream &operator<<(QDataStream &s, const QPageRanges &pageRanges)
307{
308 s << pageRanges.toString();
309 return s;
310}
311
312/*!
313 \fn QDataStream &operator>>(QDataStream &stream, QPageRanges &pageRanges)
314 \relates QPageRanges
315
316 Reads a page ranges string from \a stream and stores it in \a pageRanges.
317
318 \sa QPageRanges::fromString
319*/
320
321QDataStream &operator>>(QDataStream &s, QPageRanges &pageRanges)
322{
323 QString rangesString;
324 s >> rangesString;
325 pageRanges = QPageRanges::fromString(rangesString);
326 return s;
327}
328#endif // QT_NO_DATASTREAM
329
330#ifndef QT_NO_DEBUG_STREAM
331QDebug operator<<(QDebug dbg, const QPageRanges &pageRanges)
332{
333 QDebugStateSaver saver(dbg);
334 dbg.nospace();
335 dbg.noquote();
336 dbg << "QPageRanges(" << pageRanges.toString() << ")";
337
338 return dbg;
339}
340#endif
341
342/*!
343 \struct QPageRanges::Range
344 \inmodule QtGui
345 \brief The QPageRanges::Range struct holds the \c from and \c to endpoints of a range.
346
347 \sa QPageRanges::toRangeList()
348*/
349
350/*!
351 \variable QPageRanges::Range::from
352 \brief the lower endpoint of the range
353*/
354
355/*!
356 \variable QPageRanges::Range::to
357 \brief the upper endpoint of the range
358*/
359
360/*!
361 \fn bool QPageRanges::Range::contains(int pageNumber) const
362
363 Returns \c true if \a pageNumber is within the interval \c{[from, to]};
364 otherwise returns \c false.
365*/
366
367
368QT_END_NAMESPACE
Combined button and popup list for selecting options.
QDataStream & operator>>(QDataStream &s, QKeyCombination &combination)