KReport

KReportUnit.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2001 David Faure <faure@kde.org>
3 Copyright (C) 2004 Nicolas GOUTTE <goutte@kde.org>
4 Copyright (C) 2012 Friedrich W. H. Kossebau <kossebau@kde.org>
5 Copyright (C) 2017 Jarosław Staniek <staniek@kde.org>
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public License
18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21*/
22
23#include "KReportUnit.h"
24#include "kreport_debug.h"
25
26#include <cmath>
27
28#include <QTransform>
29#include <QCoreApplication>
30
31class Q_DECL_HIDDEN KReportUnit::Private
32{
33public:
35 qreal pixelConversion;
36};
37
38// unit types
39// Note: ensure the same order as in KReportUnit::Unit
40static QList<KReportUnit::Type> s_unitTypes = {
41 KReportUnit::Type::Millimeter,
42 KReportUnit::Type::Centimeter,
43 KReportUnit::Type::Decimeter,
44 KReportUnit::Type::Inch,
45 KReportUnit::Type::Pica,
46 KReportUnit::Type::Cicero,
48 KReportUnit::Type::Pixel
49};
50static int firstUnitIndex()
51{
52 return static_cast<int>(KReportUnit::Type::Invalid) + 1;
53}
54
55static int lastUnitIndex()
56{
57 return static_cast<int>(KReportUnit::Type::Last); // without Invalid
58}
59
60// unit symbols
61// Note: ensure the same order as in KReportUnit::Unit
62static const char* const s_unitSymbols[] =
63{
64 nullptr,
65 "mm",
66 "cm",
67 "dm",
68 "in",
69 "pi",
70 "cc",
71 "pt",
72 "px"
73};
74
75KReportUnit::KReportUnit() : d(new Private)
76{
77 d->type = Type::Invalid;
78 d->pixelConversion = 1.0;
79}
80
81KReportUnit::KReportUnit(Type type, qreal factor) : d(new Private)
82{
83 d->type = type;
84 d->pixelConversion = factor;
85}
86
87KReportUnit::KReportUnit(const KReportUnit& other) : d(new Private)
88{
89 d->type = other.type();
90 d->pixelConversion = other.factor();
91}
92
93KReportUnit::~KReportUnit()
94{
95 delete d;
96}
97
98bool KReportUnit::operator==(const KReportUnit& other) const
99{
100 return d->type == other.d->type &&
101 (d->type != Type::Pixel ||
102 qFuzzyCompare(d->pixelConversion, other.d->pixelConversion));
103}
104
105bool KReportUnit::operator!=(const KReportUnit& other) const
106{
107 return !operator==(other);
108}
109
110
112{
113 d->type = type;
114 d->pixelConversion = 1.0;
115 return *this;
116}
117
119{
120 d->type = other.type();
121 d->pixelConversion = other.factor();
122 return *this;
123}
124
125//static
127{
128 return s_unitTypes;
129}
130
131//static
133{
134 switch (type) {
135 case KReportUnit::Type::Invalid:
136 return tr("Invalid");
137 case KReportUnit::Type::Millimeter:
138 return tr("Millimeters (mm)");
139 case KReportUnit::Type::Centimeter:
140 return tr("Centimeters (cm)");
141 case KReportUnit::Type::Decimeter:
142 return tr("Decimeters (dm)");
143 case KReportUnit::Type::Inch:
144 return tr("Inches (in)");
145 case KReportUnit::Type::Pica:
146 return tr("Pica (pi)");
147 case KReportUnit::Type::Cicero:
148 return tr("Cicero (cc)");
150 return tr("Points (pt)");
151 case KReportUnit::Type::Pixel:
152 return tr("Pixels (px)");
153 default:
154 return tr("Unsupported unit");
155 }
156}
157
162
164{
165 QStringList result;
166 for (Type t : types) {
167 result.append(description(t));
168 }
169 return result;
170}
171
172qreal KReportUnit::toUserValue(qreal ptValue) const
173{
174 switch (d->type) {
175 case Type::Invalid:
176 kreportWarning() << "Conversion for Invalid type not supported";
177 return -1.0;
178 case Type::Millimeter:
179 return toMillimeter(ptValue);
180 case Type::Centimeter:
181 return toCentimeter(ptValue);
182 case Type::Decimeter:
183 return toDecimeter(ptValue);
184 case Type::Inch:
185 return toInch(ptValue);
186 case Type::Pica:
187 return toPica(ptValue);
188 case Type::Cicero:
189 return toCicero(ptValue);
190 case Type::Pixel:
191 return ptValue * d->pixelConversion;
192 case Type::Point:
193 default:
194 return toPoint(ptValue);
195 }
196}
197
198qreal KReportUnit::ptToUnit(qreal ptValue, const KReportUnit &unit)
199{
200 switch (unit.d->type) {
201 case Type::Invalid:
202 return -1.0;
203 case Type::Millimeter:
204 return POINT_TO_MM(ptValue);
205 case Type::Centimeter:
206 return POINT_TO_CM(ptValue);
207 case Type::Decimeter:
208 return POINT_TO_DM(ptValue);
209 case Type::Inch:
210 return POINT_TO_INCH(ptValue);
211 case Type::Pica:
212 return POINT_TO_PI(ptValue);
213 case Type::Cicero:
214 return POINT_TO_CC(ptValue);
215 case Type::Pixel:
216 return ptValue * unit.d->pixelConversion;
217 case Type::Point:
218 default:
219 return ptValue;
220 }
221}
222
224{
225 return QLocale::system().toString(toUserValue(ptValue));
226}
227
228qreal KReportUnit::convertFromPoint(qreal ptValue) const
229{
230 switch (d->type) {
231 case Type::Millimeter:
232 return POINT_TO_MM(ptValue);
233 case Type::Centimeter:
234 return POINT_TO_CM(ptValue);
235 case Type::Decimeter:
236 return POINT_TO_DM(ptValue);
237 case Type::Inch:
238 return POINT_TO_INCH(ptValue);
239 case Type::Pica:
240 return POINT_TO_PI(ptValue);
241 case Type::Cicero:
242 return POINT_TO_CC(ptValue);
243 case Type::Pixel:
244 return ptValue * d->pixelConversion;
245 case Type::Point:
246 default:
247 return ptValue;
248 }
249}
250
252{
253 return QPointF(convertFromPoint(ptValue.x()), convertFromPoint(ptValue.y()));
254}
255
257{
258 return QSizeF(convertFromPoint(ptValue.width()), convertFromPoint(ptValue.height()));
259}
260
261qreal KReportUnit::convertToPoint(qreal value) const
262{
263 switch (d->type) {
264 case Type::Invalid:
265 return -1.0;
266 case Type::Millimeter:
267 return MM_TO_POINT(value);
268 case Type::Centimeter:
269 return CM_TO_POINT(value);
270 case Type::Decimeter:
271 return DM_TO_POINT(value);
272 case Type::Inch:
273 return INCH_TO_POINT(value);
274 case Type::Pica:
275 return PI_TO_POINT(value);
276 case Type::Cicero:
277 return CC_TO_POINT(value);
278 case Type::Pixel:
279 return value / d->pixelConversion;
280 case Type::Point:
281 default:
282 return value;
283 }
284}
285
286qreal KReportUnit::convertToPoint(const QString &value, bool *ok) const
287{
288 return convertToPoint(QLocale::system().toDouble(value, ok));
289}
290
292{
293 return QPointF(KReportUnit::convertToPoint(value.x()),
295}
296
302
303qreal KReportUnit::parseValue(const QString& _value, qreal defaultVal)
304{
305 if (_value.isEmpty())
306 return defaultVal;
307
308 QString value(_value.simplified());
309 value.remove(QLatin1Char(' '));
310
311 int firstLetter = -1;
312 for (int i = 0; i < value.length(); ++i) {
313 if (value.at(i).isLetter()) {
314 if (value.at(i) == QLatin1Char('e'))
315 continue;
316 firstLetter = i;
317 break;
318 }
319 }
320
321 bool ok;
322 if (firstLetter == -1) {
323 qreal result = QVariant(value).toReal(&ok);
324 return ok ? result : defaultVal;
325 }
326
327 const QByteArray symbol = value.mid(firstLetter).toLatin1();
328 value.truncate(firstLetter);
329 const qreal val = value.toDouble();
330
331 if (symbol == "pt" || symbol.isEmpty())
332 return val;
333
335 if (u.isValid()) {
336 return u.fromUserValue(val);
337 }
338
339 if (symbol == "m")
340 return DM_TO_POINT(val * 10.0);
341 else if (symbol == "km")
342 return DM_TO_POINT(val * 10000.0);
343 kreportWarning() << "KReportUnit::parseValue: Unit" << symbol << "is not supported, please report.";
344
345 //! @todo add support for mi/ft ?
346 return defaultVal;
347}
348
349//static
351{
352 return QLatin1String(s_unitSymbols[static_cast<int>(type)]);
353}
354
355//static
357{
358 Type result = Type::Invalid;
359
360 if (symbol == QLatin1String("inch") /*compat*/) {
361 result = Type::Inch;
362 } else {
363 for (int i = firstUnitIndex(); i <= lastUnitIndex(); ++i) {
364 if (symbol == QLatin1String(s_unitSymbols[i])) {
365 result = static_cast<Type>(i);
366 break;
367 }
368 }
369 }
370 return result;
371}
372
373//static
375{
376 QStringList result;
377 for (Type t : types) {
378 result.append(symbol(t));
379 }
380 return result;
381}
382
383qreal KReportUnit::convertFromUnitToUnit(qreal value, const KReportUnit &fromUnit, const KReportUnit &toUnit, qreal factor)
384{
385 qreal pt;
386 switch (fromUnit.type()) {
387 case Type::Invalid:
388 pt = -1.0;
389 break;
390 case Type::Millimeter:
391 pt = MM_TO_POINT(value);
392 break;
393 case Type::Centimeter:
394 pt = CM_TO_POINT(value);
395 break;
396 case Type::Decimeter:
397 pt = DM_TO_POINT(value);
398 break;
399 case Type::Inch:
400 pt = INCH_TO_POINT(value);
401 break;
402 case Type::Pica:
403 pt = PI_TO_POINT(value);
404 break;
405 case Type::Cicero:
406 pt = CC_TO_POINT(value);
407 break;
408 case Type::Pixel:
409 pt = value / factor;
410 break;
411 case Type::Point:
412 default:
413 pt = value;
414 }
415
416 switch (toUnit.type()) {
417 case Type::Millimeter:
418 return POINT_TO_MM(pt);
419 case Type::Centimeter:
420 return POINT_TO_CM(pt);
421 case Type::Decimeter:
422 return POINT_TO_DM(pt);
423 case Type::Inch:
424 return POINT_TO_INCH(pt);
425 case Type::Pica:
426 return POINT_TO_PI(pt);
427 case Type::Cicero:
428 return POINT_TO_CC(pt);
429 case Type::Pixel:
430 return pt * factor;
431 case Type::Invalid:
432 default:
433 return pt;
434 }
435}
436
438 const KReportUnit &fromUnit,
439 const KReportUnit &toUnit)
440{
441 return QPointF(
442 KReportUnit::convertFromUnitToUnit(value.x(), fromUnit, toUnit),
443 KReportUnit::convertFromUnitToUnit(value.y(), fromUnit, toUnit));
444}
445
447 const KReportUnit &fromUnit,
448 const KReportUnit &toUnit)
449{
450 return QSizeF(
451 KReportUnit::convertFromUnitToUnit(value.width(), fromUnit, toUnit),
452 KReportUnit::convertFromUnitToUnit(value.height(), fromUnit, toUnit));
453}
454
456{
457 return QLatin1String(s_unitSymbols[static_cast<int>(d->type)]);
458}
459
460qreal KReportUnit::parseAngle(const QString& _value, qreal defaultVal)
461{
462 if (_value.isEmpty())
463 return defaultVal;
464
465 QString value(_value.simplified());
466 value.remove(QLatin1Char(' '));
467
468 int firstLetter = -1;
469 for (int i = 0; i < value.length(); ++i) {
470 if (value.at(i).isLetter()) {
471 if (value.at(i) == QLatin1Char('e'))
472 continue;
473 firstLetter = i;
474 break;
475 }
476 }
477
478 if (firstLetter == -1)
479 return value.toDouble();
480
481 const QString type = value.mid(firstLetter);
482 value.truncate(firstLetter);
483 const qreal val = value.toDouble();
484
485 if (type == QLatin1String("deg"))
486 return val;
487 else if (type == QLatin1String("rad"))
488 return val * 180 / M_PI;
489 else if (type == QLatin1String("grad"))
490 return val * 0.9;
491
492 return defaultVal;
493}
494
495#ifndef QT_NO_DEBUG_STREAM
496QDebug operator<<(QDebug debug, const KReportUnit &unit)
497{
498#ifndef NDEBUG
499 if (unit.isValid()) {
500 debug.nospace() << QString::fromLatin1("Unit(%1, %2)").arg(unit.symbol()).arg(unit.factor());
501 } else {
502 debug.nospace() << QString::fromLatin1("Unit(Invalid)");
503 }
504#else
505 Q_UNUSED(unit);
506#endif
507 return debug.space();
508}
509
510void KReportUnit::setFactor(qreal factor)
511{
512 d->pixelConversion = factor;
513}
514
515qreal KReportUnit::factor() const
516{
517 return d->pixelConversion;
518}
519
521{
522 return d->type;
523}
524
526{
527 return d->type != KReportUnit::Type::Invalid;
528}
529
530#endif
Converts between different units.
Definition KReportUnit.h:71
KReportUnit()
Constructs invalid unit.
static KReportUnit::Type symbolToType(const QString &symbol)
Returns a unit symbol string to type.
KReportUnit::Type type() const
Returns the type of this unit.
qreal convertFromPoint(qreal ptValue) const
QString description() const
Returns (translated) description string for type of this unit.
static qreal convertFromUnitToUnit(qreal value, const KReportUnit &fromUnit, const KReportUnit &toUnit, qreal factor=1.0)
convert the given value directly from one unit to another with high accuracy
static QList< Type > allTypes()
Returns list of all supported types (without Invalid)
KReportUnit & operator=(Type type)
Assigns specified type and factor 1.0 to the object.
static qreal toCicero(qreal ptValue)
Prepare ptValue to be displayed in cicero This method will round to 0.00001 precision,...
static qreal toPica(qreal ptValue)
Prepare ptValue to be displayed in pica This method will round to 0.00001 precision,...
Type
Length units supported by KReport.
Definition KReportUnit.h:75
@ Point
Postscript point, 1/72th of an Inco.
qreal fromUserValue(qreal value) const
Equal to convertToPoint(), use convertToPoint() instead for clarity.
static qreal toDecimeter(qreal ptValue)
Prepare ptValue to be displayed in dm This method will round to 0.0001 precision, use POINT_TO_DM() f...
static QString symbol(KReportUnit::Type type)
Returns the symbol string of given unit type Symbol for Invalid type is empty string.
static qreal toCentimeter(qreal ptValue)
Prepare ptValue to be displayed in cm This method will round to 0.0001 precision, use POINT_TO_CM() f...
bool isValid() const
Returns true if type of this unit is valid.
qreal convertToPoint(qreal value) const
static QStringList symbols(const QList< Type > &types)
Returns the list of unit symbols for the given types.
static qreal parseValue(const QString &value, qreal defaultVal=0.0)
Parses common KReport and ODF values, like "10cm", "5mm" to pt.
static qreal toPoint(qreal ptValue)
Prepare ptValue to be displayed in pt This method will round to 0.001 precision.
QString symbol() const
Returns the symbol string of the unit Symbol for Invalid type is empty string.
QString toUserStringValue(qreal ptValue) const
This method is the one to use to display a value in a dialog.
static qreal toInch(qreal ptValue)
Prepare ptValue to be displayed in inch This method will round to 0.00001 precision,...
static QStringList descriptions(const QList< Type > &types)
Returns the list of (translated) description strings for given list of types.
static qreal ptToUnit(qreal ptValue, const KReportUnit &unit)
Convert the value ptValue to a given unit unit Unlike KReportUnit::ptToUnit the return value remains ...
static qreal parseAngle(const QString &value, qreal defaultVal=0.0)
parse an angle to its value in degrees defaultVal is in degrees
qreal toUserValue(qreal ptValue) const
This method is the one to use to display a value in a dialog.
static qreal toMillimeter(qreal ptValue)
Prepare ptValue to be displayed in mm This method will round to 0.0001 precision, use POINT_TO_MM() f...
Type type(const QSqlDatabase &db)
bool isLetter(char32_t ucs4)
QDebug & nospace()
QDebug & space()
void append(QList< T > &&value)
QLocale system()
QString toString(QDate date, FormatType format) const const
qreal x() const const
qreal y() const const
qreal height() const const
qreal width() const const
QString arg(Args &&... args) const const
const QChar at(qsizetype position) const const
QString fromLatin1(QByteArrayView str)
bool isEmpty() const const
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) const const
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QString simplified() const const
double toDouble(bool *ok) const const
QByteArray toLatin1() const const
void truncate(qsizetype position)
qreal toReal(bool *ok) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:21:31 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.