File indexing completed on 2024-04-21 04:41:51

0001 /* This file is part of the KDE project
0002    Copyright (C) 1998 1999 Reginald Stadlbauer <reggie@kde.org>
0003    Copyright (C) 1998 1999 Torben Weis <weis@kde.org>
0004    Copyright (C) 2004 Nicolas GOUTTE <goutte@kde.org>
0005    Copyright (C) 2010 Thomas Zander <zander@kde.org>
0006    Copyright (C) 2012 Friedrich W. H. Kossebau <kossebau@kde.org>
0007    Copyright (C) 2017 Jarosław Staniek <staniek@kde.org>
0008 
0009    This library is free software; you can redistribute it and/or
0010    modify it under the terms of the GNU Library General Public
0011    License as published by the Free Software Foundation; either
0012    version 2 of the License, or (at your option) any later version.
0013 
0014    This library is distributed in the hope that it will be useful,
0015    but WITHOUT ANY WARRANTY; without even the implied warranty of
0016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0017    Library General Public License for more details.
0018 
0019    You should have received a copy of the GNU Library General Public License
0020    along with this library; see the file COPYING.LIB.  If not, write to
0021    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0022  * Boston, MA 02110-1301, USA.
0023 */
0024 
0025 #ifndef KREPORTUNIT_H
0026 #define KREPORTUNIT_H
0027 
0028 #include <math.h> // for floor
0029 
0030 #include <QCoreApplication>
0031 #include <QString>
0032 #include <QDebug>
0033 #include <QMetaType>
0034 
0035 #include "kreport_export.h"
0036 
0037 // 1 inch ^= 72 pt
0038 // 1 inch ^= 25.399956 mm (-pedantic ;p)
0039 // 1 pt = 1/12 pi
0040 // 1 pt ^= 0.0077880997 cc
0041 // 1 cc = 12 dd
0042 // Note: I don't use division but multiplication with the inverse value
0043 // because it's faster ;p (Werner)
0044 #define POINT_TO_MM(px) qreal((px)*0.352777167)
0045 #define MM_TO_POINT(mm) qreal((mm)*2.83465058)
0046 #define POINT_TO_CM(px) qreal((px)*0.0352777167)
0047 #define CM_TO_POINT(cm) qreal((cm)*28.3465058)
0048 #define POINT_TO_DM(px) qreal((px)*0.00352777167)
0049 #define DM_TO_POINT(dm) qreal((dm)*283.465058)
0050 #define POINT_TO_INCH(px) qreal((px)*0.01388888888889)
0051 #define INCH_TO_POINT(inch) qreal((inch)*72.0)
0052 #define MM_TO_INCH(mm) qreal((mm)*0.039370147)
0053 #define INCH_TO_MM(inch) qreal((inch)*25.399956)
0054 #define POINT_TO_PI(px) qreal((px)*0.083333333)
0055 #define POINT_TO_CC(px) qreal((px)*0.077880997)
0056 #define PI_TO_POINT(pi) qreal((pi)*12)
0057 #define CC_TO_POINT(cc) qreal((cc)*12.840103)
0058 
0059 /*!
0060  * @brief Converts between different units
0061  *
0062  * KReportUnit stores everything in pt (using "qreal") internally.
0063  * When displaying a value to the user, the value is converted to the user's unit
0064  * of choice, and rounded to a reasonable precision to avoid 0.999999
0065  *
0066  * For implementing the selection of a unit type in the UI use the allTypes() method.
0067  * it ensure the same order of the unit types in all places, with the order not
0068  * bound to the order in the enum so ABI-compatible extension is possible.
0069  */
0070 class KREPORT_EXPORT KReportUnit
0071 {
0072     Q_DECLARE_TR_FUNCTIONS(KReportUnit)
0073 public:
0074     /** Length units supported by %KReport. */
0075     enum class Type {
0076         Invalid,
0077         Millimeter,
0078         Centimeter,
0079         Decimeter,
0080         Inch,
0081         Pica,
0082         Cicero,
0083         Point,  ///< Postscript point, 1/72th of an Inco
0084         Pixel,
0085         Last = Pixel ///< internal
0086     };
0087 
0088     /**
0089      * @brief Constructs invalid unit
0090       *
0091       * @since 3.1
0092       */
0093     KReportUnit();
0094 
0095     /** Construct unit with given type and factor. */
0096     explicit KReportUnit(Type type, qreal factor = 1.0);
0097 
0098     KReportUnit(const KReportUnit &other);
0099 
0100     ~KReportUnit();
0101 
0102     /// Assigns specified type and factor 1.0 to the object
0103     /// @param unit Type of unit
0104     KReportUnit& operator=(Type type);
0105 
0106     KReportUnit& operator=(const KReportUnit& other);
0107 
0108     bool operator!=(const KReportUnit &other) const;
0109 
0110     bool operator==(const KReportUnit &other) const;
0111 
0112     /**
0113      * @brief Returns true if type of this unit is valid
0114      *
0115      * @since 3.1
0116      */
0117     bool isValid() const;
0118 
0119     /**
0120      * @brief Returns list of all supported types (without Invalid)
0121      *
0122      * @since 3.1
0123      */
0124     static QList<Type> allTypes();
0125 
0126     /** Returns the type of this unit */
0127     KReportUnit::Type type() const;
0128 
0129     /**
0130      * @brief Returns (translated) description string for type of this unit
0131      *
0132      * @since 3.1
0133      */
0134     QString description() const;
0135 
0136     /**
0137      * @brief Returns (translated) description string for given unit type
0138      *
0139      * @since 3.1
0140      */
0141     static QString description(KReportUnit::Type type);
0142 
0143     /**
0144      * @brief Returns the list of (translated) description strings for given list of types
0145      *
0146      * @since 3.1
0147      */
0148     static QStringList descriptions(const QList<Type> &types);
0149 
0150     void setFactor(qreal factor);
0151 
0152     qreal factor() const;
0153 
0154     /**
0155      * Prepare ptValue to be displayed in pt
0156      * This method will round to 0.001 precision
0157      */
0158     static inline qreal toPoint(qreal ptValue)
0159     {
0160         // No conversion, only rounding (to 0.001 precision)
0161         return floor(ptValue * 1000.0) / 1000.0;
0162     }
0163 
0164     /**
0165      * Prepare ptValue to be displayed in mm
0166      * This method will round to 0.0001 precision, use POINT_TO_MM() for lossless conversion.
0167      */
0168     static inline qreal toMillimeter(qreal ptValue)
0169     {
0170         // "mm" values are rounded to 0.0001 millimeters
0171         return floor(POINT_TO_MM(ptValue) * 10000.0) / 10000.0;
0172     }
0173 
0174     /**
0175      * Prepare ptValue to be displayed in cm
0176      * This method will round to 0.0001 precision, use POINT_TO_CM() for lossless conversion.
0177      */
0178     static inline qreal toCentimeter(qreal ptValue)
0179     {
0180         return floor(POINT_TO_CM(ptValue) * 10000.0) / 10000.0;
0181     }
0182 
0183     /**
0184      * Prepare ptValue to be displayed in dm
0185      * This method will round to 0.0001 precision, use POINT_TO_DM() for lossless conversion.
0186      */
0187     static inline qreal toDecimeter(qreal ptValue)
0188     {
0189         return floor(POINT_TO_DM(ptValue) * 10000.0) / 10000.0;
0190     }
0191 
0192     /**
0193      * Prepare ptValue to be displayed in inch
0194      * This method will round to 0.00001 precision, use POINT_TO_INCH() for lossless conversion.
0195      */
0196     static inline qreal toInch(qreal ptValue)
0197     {
0198         // "in" values are rounded to 0.00001 inches
0199         return floor(POINT_TO_INCH(ptValue) * 100000.0) / 100000.0;
0200     }
0201 
0202     /**
0203      * Prepare ptValue to be displayed in pica
0204      * This method will round to 0.00001 precision, use POINT_TO_PI() for lossless conversion.
0205      */
0206     static inline qreal toPica(qreal ptValue)
0207     {
0208         // "pi" values are rounded to 0.00001 inches
0209         return floor(POINT_TO_PI(ptValue) * 100000.0) / 100000.0;
0210     }
0211 
0212     /**
0213      * Prepare ptValue to be displayed in cicero
0214      * This method will round to 0.00001 precision, use POINT_TO_CC() for lossless conversion.
0215      */
0216     static inline qreal toCicero(qreal ptValue)
0217     {
0218         // "cc" values are rounded to 0.00001 inches
0219         return floor(POINT_TO_CC(ptValue) * 100000.0) / 100000.0;
0220     }
0221 
0222     /**
0223      * convert the given value directly from one unit to another with high accuracy
0224      */
0225     static qreal convertFromUnitToUnit(qreal value, const KReportUnit &fromUnit,
0226                                        const KReportUnit &toUnit, qreal factor = 1.0);
0227 
0228     /**
0229      * convert the given value directly from one unit to another with high accuracy
0230      */
0231     static QPointF convertFromUnitToUnit(const QPointF &value,
0232                                          const KReportUnit &fromUnit,
0233                                          const KReportUnit &toUnit);
0234 
0235     /**
0236      * convert the given value directly from one unit to another with high accuracy
0237      */
0238     static QSizeF convertFromUnitToUnit(const QSizeF &value, const KReportUnit &fromUnit,
0239                                         const KReportUnit &toUnit);
0240 
0241     /**
0242      * This method is the one to use to display a value in a dialog
0243      * \return the value @a ptValue converted to unit and rounded, ready to be displayed
0244      */
0245     qreal toUserValue(qreal ptValue) const;
0246 
0247     /**
0248      * Convert the value @a ptValue to a given unit @a unit
0249      * Unlike KReportUnit::ptToUnit the return value remains unrounded, so that it can be used in complex calculation
0250      * \return the converted value
0251      */
0252     static qreal ptToUnit(qreal ptValue, const KReportUnit &unit);
0253 
0254     /// This method is the one to use to display a value in a dialog
0255     /// @return the value @a ptValue converted the unit and rounded, ready to be displayed
0256     QString toUserStringValue(qreal ptValue) const;
0257 
0258     //! @return the value converted to points with high accuracy
0259     qreal convertToPoint(qreal value) const;
0260 
0261     //! @return the value converted from points to the actual unit with high accuracy
0262     qreal convertFromPoint(qreal ptValue) const;
0263 
0264     //! @return the value converted from points to the actual unit with high accuracy
0265     QPointF convertFromPoint(const QPointF &ptValue) const;
0266 
0267     //! @return the value converted from points to the actual unit with high accuracy
0268     QSizeF convertFromPoint(const QSizeF &ptValue) const;
0269 
0270     //! Equal to convertToPoint(), use convertToPoint() instead for clarity
0271     inline qreal fromUserValue(qreal value) const { return convertToPoint(value); }
0272 
0273     /// @return the value converted to points with high accuracy
0274     QPointF convertToPoint(const QPointF &value) const;
0275 
0276     /// @return the value converted to points with high accuracy
0277     QSizeF convertToPoint(const QSizeF &value) const;
0278 
0279     /// @return the value converted to points with high accuracy
0280     /// @param value value entered by the user
0281     /// @param ok if set, the pointed bool is set to true if the value could be
0282     /// converted to a qreal, and to false otherwise.
0283     /// @return the value converted to points for internal use
0284     qreal convertToPoint(const QString &value, bool *ok = nullptr) const;
0285 
0286     //! Equal to convertToPoint(), use convertToPoint() instead for clarity
0287     inline qreal fromUserValue(const QString &value, bool *ok = nullptr) const {
0288         return convertToPoint(value, ok);
0289     }
0290 
0291     //! Returns the symbol string of given unit type
0292     //! Symbol for Invalid type is empty string.
0293     static QString symbol(KReportUnit::Type type);
0294 
0295     //! Returns the symbol string of the unit
0296     //! Symbol for Invalid type is empty string.
0297     QString symbol() const;
0298 
0299     /**
0300      * Equal to symbol(): returns the symbol string of the unit.
0301      */
0302     inline QString toString() const
0303     {
0304         return symbol();
0305     }
0306 
0307     /**
0308      * @brief Returns a unit symbol string to type
0309      *
0310      * @param symbol symbol to convert, must be lowercase
0311      * @return Invalid type for unsupported symbol
0312      *
0313      * @since 3.1
0314      */
0315     static KReportUnit::Type symbolToType(const QString &symbol);
0316 
0317     /**
0318      * @brief Returns the list of unit symbols for the given types
0319      *
0320      * @since 3.1
0321      */
0322     static QStringList symbols(const QList<Type> &types);
0323 
0324     /// Parses common %KReport and ODF values, like "10cm", "5mm" to pt.
0325     /// If no unit is specified, pt is assumed.
0326     /// @a defaultVal is in Points
0327     static qreal parseValue(const QString &value, qreal defaultVal = 0.0);
0328 
0329     /// parse an angle to its value in degrees
0330     /// @a defaultVal is in degrees
0331     static qreal parseAngle(const QString &value, qreal defaultVal = 0.0);
0332 
0333 private:
0334     class Private;
0335     Private * const d;
0336 };
0337 
0338 #ifndef QT_NO_DEBUG_STREAM
0339 KREPORT_EXPORT QDebug operator<<(QDebug, const KReportUnit &);
0340 #endif
0341 
0342 Q_DECLARE_METATYPE(KReportUnit)
0343 
0344 #endif