KReport

KReportUnit.cpp
1 /* This file is part of the KDE project
2  Copyright (C) 2001 David Faure <[email protected]>
3  Copyright (C) 2004 Nicolas GOUTTE <[email protected]>
4  Copyright (C) 2012 Friedrich W. H. Kossebau <[email protected]>
5  Copyright (C) 2017 JarosÅ‚aw Staniek <[email protected]>
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 
31 class Q_DECL_HIDDEN KReportUnit::Private
32 {
33 public:
35  qreal pixelConversion;
36 };
37 
38 // unit types
39 // Note: ensure the same order as in KReportUnit::Unit
40 static 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 };
50 static int firstUnitIndex()
51 {
52  return static_cast<int>(KReportUnit::Type::Invalid) + 1;
53 }
54 
55 static 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
62 static 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 
75 KReportUnit::KReportUnit() : d(new Private)
76 {
77  d->type = Type::Invalid;
78  d->pixelConversion = 1.0;
79 }
80 
81 KReportUnit::KReportUnit(Type type, qreal factor) : d(new Private)
82 {
83  d->type = type;
84  d->pixelConversion = factor;
85 }
86 
87 KReportUnit::KReportUnit(const KReportUnit& other) : d(new Private)
88 {
89  d->type = other.type();
90  d->pixelConversion = other.factor();
91 }
92 
93 KReportUnit::~KReportUnit()
94 {
95  delete d;
96 }
97 
98 bool 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 
105 bool 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 
159 {
160  return KReportUnit::description(type());
161 }
162 
164 {
165  QStringList result;
166  for (Type t : types) {
167  result.append(description(t));
168  }
169  return result;
170 }
171 
172 qreal 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 
198 qreal 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 
228 qreal 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 
261 qreal 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 
286 qreal 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()),
294  KReportUnit::convertToPoint(value.y()));
295 }
296 
298 {
299  return QSizeF(KReportUnit::convertToPoint(value.width()),
301 }
302 
303 qreal 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 
383 qreal 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 
460 qreal 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
496 QDebug 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 
510 void KReportUnit::setFactor(qreal factor)
511 {
512  d->pixelConversion = factor;
513 }
514 
515 qreal 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
static qreal toCicero(qreal ptValue)
Prepare ptValue to be displayed in cicero This method will round to 0.00001 precision,...
Definition: KReportUnit.h:216
qreal toReal(bool *ok) const const
void append(const T &value)
void truncate(int position)
qreal height() const const
bool isValid() const
Returns true if type of this unit is valid.
Converts between different units.
Definition: KReportUnit.h:70
qreal convertToPoint(qreal value) const
Type type(const QSqlDatabase &db)
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 KReportUnit::Type symbolToType(const QString &symbol)
Returns a unit symbol string to type.
QDebug & nospace()
QDebug & space()
QDataStream & operator<<(QDataStream &out, const KDateTime &dateTime)
QByteArray toLatin1() const const
KReportUnit()
Constructs invalid unit.
Definition: KReportUnit.cpp:75
bool isLetter() const const
QString simplified() const const
QString symbol() const
Returns the symbol string of the unit 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...
Definition: KReportUnit.h:178
QLocale system()
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...
Definition: KReportUnit.h:187
static QStringList descriptions(const QList< Type > &types)
Returns the list of (translated) description strings for given list of types.
Type
Length units supported by KReport.
Definition: KReportUnit.h:75
qreal toUserValue(qreal ptValue) const
This method is the one to use to display a value in a dialog.
static qreal toPoint(qreal ptValue)
Prepare ptValue to be displayed in pt This method will round to 0.001 precision.
Definition: KReportUnit.h:158
@ Point
Postscript point, 1/72th of an Inco.
qreal fromUserValue(qreal value) const
Equal to convertToPoint(), use convertToPoint() instead for clarity.
Definition: KReportUnit.h:271
bool isEmpty() const const
int length() const const
QString toUserStringValue(qreal ptValue) const
This method is the one to use to display a value in a dialog.
QString toString(qlonglong i) const const
qreal convertFromPoint(qreal ptValue) const
static qreal parseValue(const QString &value, qreal defaultVal=0.0)
Parses common KReport and ODF values, like "10cm", "5mm" to pt.
static QString symbol(KReportUnit::Type type)
Returns the symbol string of given unit type Symbol for Invalid type is empty string.
double toDouble(bool *ok) const const
QString & remove(int position, int n)
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...
Definition: KReportUnit.h:168
qreal x() const const
qreal y() const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
static QStringList symbols(const QList< Type > &types)
Returns the list of unit symbols for the given types.
QString fromLatin1(const char *str, int size)
const QChar at(int position) const const
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
KReportUnit::Type type() const
Returns the type of this unit.
static qreal toPica(qreal ptValue)
Prepare ptValue to be displayed in pica This method will round to 0.00001 precision,...
Definition: KReportUnit.h:206
QString mid(int position, int n) const const
KReportUnit & operator=(Type type)
Assigns specified type and factor 1.0 to the object.
QString description() const
Returns (translated) description string for type of this unit.
static QList< Type > allTypes()
Returns list of all supported types (without Invalid)
static qreal toInch(qreal ptValue)
Prepare ptValue to be displayed in inch This method will round to 0.00001 precision,...
Definition: KReportUnit.h:196
qreal width() const const
static qreal parseAngle(const QString &value, qreal defaultVal=0.0)
parse an angle to its value in degrees defaultVal is in degrees
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Mon Jun 27 2022 04:26:40 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.