File indexing completed on 2024-05-12 16:02:28

0001 /*
0002  *  SPDX-FileCopyrightText: 2017 Laurent Valentin Jospin <laurent.valentin@famillejospin.ch>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef KISSPINBOXUNITMANAGER_H
0008 #define KISSPINBOXUNITMANAGER_H
0009 
0010 #include <QObject>
0011 #include <QStringList>
0012 #include <QAbstractListModel>
0013 
0014 #include "kritawidgetutils_export.h"
0015 
0016 class KisSpinBoxUnitManager;
0017 class KisSpinBoxUnitManagerBuilder;
0018 class KisSpinBoxUnitManagerFactory;
0019 
0020 /*!
0021  * \brief The KisSpinBoxUnitManagerFactory class is a factory that is used to build a default KisSpinBoxUnitManager.
0022  * \see KisSpinBoxUnitManagerBuilder
0023  */
0024 class KRITAWIDGETUTILS_EXPORT KisSpinBoxUnitManagerFactory
0025 {
0026 public:
0027 
0028     static KisSpinBoxUnitManager* buildDefaultUnitManager(QObject* parent);
0029     //! \brief set a builder the factory can use. The factory should take on the lifecycle of the builder, so to delete it call clearUnitManagerBuilder();
0030     static void setDefaultUnitManagerBuilder(KisSpinBoxUnitManagerBuilder* pBuilder);
0031     static void clearUnitManagerBuilder();
0032 
0033 private:
0034 
0035     static KisSpinBoxUnitManagerBuilder* builder;
0036 
0037 };
0038 
0039 /*!
0040  * \brief The KisSpinBoxUnitManagerBuilder class is the base class, used in the strategy pattern of KisSpinBoxUnitManagerFactory.
0041  * \see KisSpinBoxUnitManagerFactory.
0042  */
0043 class KRITAWIDGETUTILS_EXPORT KisSpinBoxUnitManagerBuilder
0044 {
0045 
0046 public:
0047 
0048     virtual ~KisSpinBoxUnitManagerBuilder() {}
0049 
0050     virtual KisSpinBoxUnitManager* buildUnitManager(QObject* parent) = 0; //this pure virtual function is used to build a unitmanager, it will be used by the unitManagerFactory.
0051 };
0052 
0053 /**
0054  * @brief The KisSpinBoxUnitManager class is an abstract interface for the unitspinboxes classes to manage different type of units.
0055  *
0056  * The class differentiates between unit dimension (distance, angle, time).
0057  *
0058  * The class allows to convert values between reference unit and apparent unit, but also to get other information like possible units symbols.
0059  *
0060  * This class doesn't allow to use relative units (units whose conversion factor is dependent of the context), even if it's private data is prepared to manage it.
0061  * The reason for this is that from the library of this class it is very hard to easily access the information needed. So all will be managed by subclasses in other libs.
0062  *
0063  * The class is a subclass of QAbstractListModel, so that available list of units is easily accessed by other Qt standard components, like QComboBoxes.
0064  *
0065  */
0066 class KRITAWIDGETUTILS_EXPORT KisSpinBoxUnitManager : public  QAbstractListModel
0067 {
0068     Q_OBJECT
0069 
0070 public:
0071 
0072     enum UnitDimension{
0073         LENGTH = 0, //length, print size, reference is point
0074         IMLENGTH = 1, //length, image size, reference is pixel. This dimension is used when the printing units must be avoided
0075         ANGLE = 2,
0076         TIME = 3
0077     };
0078 
0079     static inline bool isUnitId(int code) { return (code == LENGTH || code == ANGLE || code == TIME); }
0080 
0081     //! \brief this list holds the symbols of the reference unit per dimension. The index is equal to the value in UnitDimension so that the dimension name can be used to index the list.
0082     static const QStringList referenceUnitSymbols;
0083 
0084     enum Constrain{
0085         NOCONSTR = 0,
0086         REFISINT = 1,
0087         VALISINT = 2
0088 
0089     };
0090 
0091     Q_DECLARE_FLAGS(Constrains, Constrain)
0092 
0093     explicit KisSpinBoxUnitManager(QObject *parent = 0);
0094     ~KisSpinBoxUnitManager() override;
0095 
0096     int getUnitDimensionType() const;
0097     QString getReferenceUnitSymbol() const;
0098     QString getApparentUnitSymbol() const;
0099 
0100     //! \brief get the position of the apparent unit in the list of units. It is useful if we want to build a model for combo-box based unit management.
0101     int getApparentUnitId() const;
0102 
0103     //! \brief get a hint of how many decimals the spinbox needs to display.
0104     int getApparentUnitRecommandedDecimals() const;
0105 
0106     virtual QStringList getsUnitSymbolList(bool withName = false) const;
0107 
0108     qreal getReferenceValue(double apparentValue) const;
0109     qreal getApparentValue(double refValue) const;
0110 
0111     //! \brief gets the conversion factor of a managed unit, or -1 in case of error. This method is the one that needs to be overridden to extend the ability of the KisSpinBoxUnitManager.
0112     virtual qreal getConversionFactor(int dim, QString symbol) const;
0113     //! \brief some units conversions are done via an affine transform, not just a linear transform. This function gives the constant of this affine transform (usually 0).
0114     virtual qreal getConversionConstant(int dim, QString symbol) const;
0115 
0116     int rowCount(const QModelIndex &parent = QModelIndex()) const override;
0117     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
0118 
0119 Q_SIGNALS:
0120 
0121     void unitDimensionChanged(int dimCode);
0122     void unitAboutToChange();
0123     void unitChanged(QString symbol);
0124     void unitChanged(int index);
0125     void conversionFactorChanged(qreal newConversionFactor, qreal oldConversionFactor) const;
0126     void conversionConstantChanged(qreal newConversionFactor, qreal oldConversionFactor) const;
0127     void unitListChanged();
0128 
0129 public Q_SLOTS:
0130 
0131     void setUnitDimension(UnitDimension dimension);
0132     void setApparentUnitFromSymbol(QString pSymbol);
0133     void selectApparentUnitFromIndex(int index);
0134 
0135     void syncWithOtherUnitManager(KisSpinBoxUnitManager* other);
0136     void clearSyncWithOtherUnitManager(KisSpinBoxUnitManager* other);
0137 
0138 protected:
0139 
0140     class Private;
0141     Private * d;
0142 
0143     //! \brief convert a unitChanged signal with a QString to one with an index.
0144     void newUnitSymbolToUnitIndex(QString symbol);
0145 
0146     //! \brief indicate if the unit manager has some kind of way of using a percent unit, used by the main class to add percent when necessary.
0147     virtual bool hasPercent(int unitDim) const;
0148 
0149     //unit's that may be used only if access to the document information exists.
0150     static const QStringList documentRelativeLengthUnitSymbols;
0151     static const QStringList documentRelativeTimeUnitSymbols;
0152 
0153     void recomputeConversionFactor() const;
0154     void recomputeConvesrionConstant() const;
0155 
0156     //! \brief calling this method gives access to document relative units. Only subclasses that manage those units should call it.
0157     void grantDocumentRelativeUnits();
0158 
0159 };
0160 
0161 #endif // KISSPINBOXUNITMANAGER_H