File indexing completed on 2024-06-09 12:38:03

0001 /* This file is part of the KDE project
0002    Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
0003    Copyright (C) 2004 Alexander Dymo <cloudtemple@mskat.net>
0004    Copyright (C) 2004-2017 Jarosław Staniek <staniek@kde.org>
0005 
0006    This library is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU Library General Public
0008    License as published by the Free Software Foundation; either
0009    version 2 of the License, or (at your option) any later version.
0010 
0011    This library is distributed in the hope that it will be useful,
0012    but WITHOUT ANY WARRANTY; without even the implied warranty of
0013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014    Library General Public License for more details.
0015 
0016    You should have received a copy of the GNU Library General Public License
0017    along with this library; see the file COPYING.LIB.  If not, write to
0018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019  * Boston, MA 02110-1301, USA.
0020 */
0021 
0022 #ifndef KPROPERTY_PROPERTY_H
0023 #define KPROPERTY_PROPERTY_H
0024 
0025 #include <QVariant>
0026 #include <QStringList>
0027 #include <QByteArray>
0028 #include <QDebug>
0029 
0030 #include <cmath>
0031 #include <limits>
0032 
0033 #include "kpropertycore_export.h"
0034 
0035 class KComposedPropertyInterface;
0036 class KPropertyListData;
0037 class KPropertySet;
0038 class KPropertySetPrivate;
0039 
0040 /**
0041  * @brief Minimum double value working precisely.
0042  *
0043  * @since 3.1
0044  */
0045 #define KPROPERTY_MIN_PRECISE_DOUBLE (-pow(2, std::numeric_limits<double>::digits))
0046 
0047 /**
0048  * @brief Minimum double value working precisely
0049  *
0050  * Editor for double values (spin box) has localized contents and its code supports just this maximum.
0051  * For a 64-bit machine it's 2**53.
0052  * See also https://phabricator.kde.org/D5419#inline-22329
0053  *
0054  * @since 3.1
0055  */
0056 #define KPROPERTY_MAX_PRECISE_DOUBLE (pow(2, std::numeric_limits<double>::digits))
0057 
0058 /*! \brief The base class representing a single property
0059 
0060   KProperty object can hold a property of given type supported by QVariant. Properties of custom types
0061   can be also created, see using KPropertyFactory. Composed or custom properties
0062   are not created using subclassing of KProperty but using @ref KComposedPropertyInterface.
0063 
0064   Each property stores old value to allows undoing that reverts the value to the old one.
0065   Property has a non-empty name (a QByteArray), a caption that is user-visible translated string
0066   displayed in property editor. Description is a translatable string that can be specified too
0067   in order to further explain meaning of the property.
0068 
0069   Propery also supports setting arbitrary number of options using KProperty::setOption() that allow
0070   to customize look or behavior of the property in the editor.
0071 
0072   @code
0073   // Creating a simple property:
0074   KProperty *property = new KProperty(name, value, caption, description);
0075   // name is a QByteArray, value is whatever type QVariant supports
0076 
0077   // Creating a property of type ValueFromList matching keys with names:
0078   QStringList keys({"one", "two", "three"}); // possible values of the property
0079   QStringList names({tr("One"), tr("Two"), tr("Three")}); // Names (possibly translated) shown in
0080                                                           // the editor instead of the keys
0081   property = new KProperty(name, new KPropertyListData(keys, names), "two", caption);
0082 
0083   // Creating a property of type ValueFromList matching variant keys with names:
0084   KPropertyListData *listData = new KPropertyListData({1.1, tr("One")}, {2.5, tr("Two")}, {3., tr("Three")}});
0085   propertySet->addProperty(new KProperty("List", listData, "otheritem", "List"));
0086   @endcode
0087 
0088   @note Sometimes it makes sense to split property captions that have with more words to multiple lines
0089   using a newline character, e.g. "Allow Zero Size" to "Allow Zero\nSize".
0090   This is suitable especially for the needs of property editor which can offer only limited area.
0091   The text of property caption containing newline characters is available in its original form using
0092   KProperty::captionForDisplaying(). KProperty::caption() returns modified caption text in which
0093   the newline characters are substituted with spaces and any trailing and leading whitespace is removed.
0094 */
0095 class KPROPERTYCORE_EXPORT KProperty
0096 {
0097 public:
0098     /*! Defines types of properties.
0099      Properties defined by plugins should have a type number >= UserDefined .*/
0100     enum Type {
0101         //standard supported QVariant types
0102         Auto = 0x00ffffff,
0103         Invalid = QVariant::Invalid,
0104         BitArray = QVariant::BitArray,
0105         Bitmap = QVariant::Bitmap,
0106         Bool = QVariant::Bool,
0107         Brush = QVariant::Brush,
0108         ByteArray = QVariant::ByteArray,
0109         Char = QVariant::Char,
0110         Color = QVariant::Color,
0111         Cursor = QVariant::Cursor,
0112         Date = QVariant::Date,
0113         DateTime = QVariant::DateTime,
0114         Double = QVariant::Double,
0115         Font = QVariant::Font,
0116         Icon = QVariant::Icon,
0117         Image = QVariant::Image,
0118         Int = QVariant::Int,
0119         KeySequence = QVariant::KeySequence,
0120         Line = QVariant::Line,
0121         LineF = QVariant::LineF,
0122         List = QVariant::List,
0123         Locale = QVariant::Locale,
0124         LongLong = QVariant::LongLong,
0125         Map = QVariant::Map,
0126         Matrix = QVariant::Matrix,
0127         Transform = QVariant::Transform,
0128         Palette = QVariant::Palette,
0129         Pen = QVariant::Pen,
0130         Pixmap = QVariant::Pixmap,
0131         Point = QVariant::Point,
0132         PointF = QVariant::PointF,
0133         Polygon = QVariant::Polygon,
0134         Rect = QVariant::Rect,
0135         RectF = QVariant::RectF,
0136         RegExp = QVariant::RegExp,
0137         Region = QVariant::Region,
0138         Size = QVariant::Size,
0139         SizeF = QVariant::SizeF,
0140         SizePolicy = QVariant::SizePolicy,
0141         String = QVariant::String,
0142         StringList = QVariant::StringList,
0143         TextFormat = QVariant::TextFormat,
0144         TextLength = QVariant::TextLength,
0145         Time = QVariant::Time,
0146         UInt = QVariant::UInt,
0147         ULongLong = QVariant::ULongLong,
0148         Url = QVariant::Url,
0149 
0150         //predefined custom types
0151         ValueFromList = 1000,         /**<string value from a list*/
0152         Symbol,                       /**<unicode symbol code*/
0153         FontName,                     /**<font name, e.g. "times new roman"*/
0154         LineStyle,                    /**<line style*/
0155         ComposedUrl                   /**<composed URL @since 3.2 */,
0156 
0157         UserDefined = 4000            /**<plugin defined properties should start here*/
0158     };
0159 
0160     /**
0161      * Constructs a null property.
0162      * Null properties have empty names and captions and Invalid types.
0163      */
0164     KProperty();
0165 
0166     /*! Constructs property of a simple type. */
0167     explicit KProperty(const QByteArray &name, const QVariant &value = QVariant(),
0168              const QString &caption = QString(), const QString &description = QString(),
0169              int type = Auto, KProperty* parent = nullptr);
0170 
0171     /**
0172      * @brief Constructs property of ValueFromList type
0173      *
0174      * Ownership of @a listData is passed to the property object.
0175      */
0176     KProperty(const QByteArray &name, KPropertyListData *listData,
0177              const QVariant &value = QVariant(),
0178              const QString &caption = QString(), const QString &description = QString(),
0179              int type = ValueFromList, KProperty* parent = nullptr);
0180 
0181     /*! Constructs a deep copy of \a prop property. */
0182     KProperty(const KProperty &prop);
0183 
0184     ~KProperty();
0185 
0186     /**
0187      * @return name of the property
0188      * @note empty name means a null property
0189      */
0190     QByteArray name() const;
0191 
0192     /**
0193      * Sets name of the property
0194      * @note empty name means a null property
0195      */
0196     void setName(const QByteArray &name);
0197 
0198     /*! \return the caption of the property. Does not contain newline characters. Can be empty. */
0199     QString caption() const;
0200 
0201     /*! \return the caption of the property or name() if the caption is empty. */
0202     inline QString captionOrName() const
0203     {
0204         return caption().isEmpty() ? QString::fromLatin1(name()) : caption();
0205     }
0206 
0207     /*! \return the caption text of the property for displaying.
0208      It is similar to caption() but if the property caption contains newline characters,
0209      these are not substituted with spaces. */
0210     QString captionForDisplaying() const;
0211 
0212     /*! Sets the name of the property. If the caption contains newline characters,
0213      these are substituted with spaces.
0214      @see captionForDisplaying
0215     */
0216     void setCaption(const QString &caption);
0217 
0218     /*! \return the description of the property.*/
0219     QString description() const;
0220 
0221     /*! Sets the description of the property.*/
0222     void setDescription(const QString &description);
0223 
0224     /*! \return the type of the property.*/
0225     int type() const;
0226 
0227     /*! Sets the type of the property.*/
0228     void setType(int type);
0229 
0230     /*! \return the value of the property.*/
0231     QVariant value() const;
0232 
0233     /*! Returns the previous property value if it was set in setValue(). */
0234     QVariant oldValue() const;
0235 
0236     //! Options that influence how values are handled in setValue() and valueEqualsTo()
0237     //! @since 3.1
0238     enum class ValueOption {
0239         None = 0,        //!< No options, that is 1. old value is remembered before setting a new one;
0240                          //!< 2. composed properties are considered while comparing old and new value
0241         IgnoreOld = 1,   //!< Do not remember the old value before setting a new one
0242         IgnoreComposedProperty = 2 //!< Do not use composed property when comparing values
0243     };
0244     Q_DECLARE_FLAGS(ValueOptions, ValueOption)
0245 
0246     /**
0247      * @brief Sets value of the property.
0248      * @param value New value
0249      * @param options Options for the value setting.
0250      * @return @c true if the value has been changed and @c false if the @a value was the same
0251      *         as previous one so it was not changed of if this property is null.
0252      */
0253     bool setValue(const QVariant &value, ValueOptions options = ValueOptions());
0254 
0255     /**
0256      * @return true if value of this property is equal to specified value
0257      *
0258      * Takes type into account.
0259      * @param value Value to compare.
0260      * @param valueOptions Options to use when comparing.
0261      *                     Only the @c None and IgnoreComposedProperties are supported.
0262      * @since 3.1
0263      */
0264     bool valueEqualsTo(const QVariant &value, ValueOptions valueOptions = ValueOptions()) const;
0265 
0266     /*! Resets the value of the property to the old value.
0267      @see oldValue() */
0268     void resetValue();
0269 
0270     /*! \return the qstring-to-value correspondence list of the property.
0271      used to create comboboxes-like property editors.*/
0272     KPropertyListData* listData() const;
0273 
0274     /*! Sets the qstring-to-value correspondence list of the property.
0275     This is used to create comboboxes-like property editors.*/
0276     void setListData(KPropertyListData* list);
0277 
0278     /*! Sets the string-to-value correspondence list of the property.
0279      This is used to create comboboxes-like property editors.
0280      This is overload of the above ctor added for convenience. */
0281     void setListData(const QStringList &keys, const QStringList &names);
0282 
0283     /*! Sets icon name to \a name for this property. Icons are optional and are used e.g.
0284      in property editor - displayed at the left hand. */
0285     void setIconName(const QString &name);
0286 
0287     /*! \return property icon's name. Can be empty. */
0288     QString iconName() const;
0289 
0290     /*! \return a list of all children for this property, or NULL of there
0291      is no children for this property */
0292     const QList<KProperty*>*  children() const;
0293 
0294     /*! \return a child property for \a name, or NULL if there is no property with that name. */
0295     KProperty* child(const QByteArray &name);
0296 
0297     /*! \return parent property for this property, or NULL if there is no parent property. */
0298     KProperty* parent() const;
0299 
0300     /*! \return the composed property for this property, or NULL if there was
0301     no composed property defined. */
0302     KComposedPropertyInterface* composedProperty() const;
0303 
0304     /*! Sets composed property \a prop for this property. */
0305     void setComposedProperty(KComposedPropertyInterface *prop);
0306 
0307     /*! \return true if this property is null. Property is null if it has empty name. */
0308     bool isNull() const;
0309 
0310     /**
0311      * @brief Return @c true if value of this property or value of any child property is modified.
0312      *
0313      * @see clearModifiedFlag()
0314      */
0315     bool isModified() const;
0316 
0317     /**
0318      * @brief Clears the "modified" flag for this property and all its child properties.
0319      *
0320      * After calling this method isModified() returs false for the property and all child
0321      * properties.
0322      *
0323      * @see isModified()
0324      */
0325     void clearModifiedFlag();
0326 
0327     /*! \return true if the property is read-only when used in a property editor.
0328      @c false by default.
0329      The property can be read-write but still not editable for the user if the parent property set's
0330      read-only flag is set.
0331      @see KPropertySet::isReadOnly() */
0332     bool isReadOnly() const;
0333 
0334     /*! Sets this property to be read-only.
0335      @see isReadOnly() */
0336     void setReadOnly(bool readOnly);
0337 
0338     /*! \return true if the property is visible.
0339      Only visible properties are displayed by the property editor view. */
0340     bool isVisible() const;
0341 
0342     /*! Sets the visibility flag.*/
0343     void setVisible(bool visible);
0344 
0345     /*! \return true if the property can be saved to a stream, xml, etc.
0346     There is a possibility to use "GUI" properties that aren't
0347     stored but used only in a GUI.*/
0348     bool isStorable() const;
0349 
0350     /*! Sets "storable" flag for this property. @see isStorable() */
0351     void setStorable(bool storable);
0352 
0353     //! Synchronization policy for property values
0354     //! @since 3.1
0355     enum class ValueSyncPolicy {
0356         Editor,   //!< Allow to synchronize by the property editor using its valueSync setting (default)
0357         FocusOut, //!< Synchronize the value when focus is out of the editor widget for this property
0358                   //!< or when the user presses the Enter key
0359         Auto      //!< Synchronize automatically as soon as the editor widget for this property signals
0360                   //! (using commitData) that the value has been changed, e.g. when the user types
0361                   //! another letter in a text box
0362     };
0363 
0364     //! @return synchronization policy for property values of this property
0365     //! @since 3.1
0366     ValueSyncPolicy valueSyncPolicy() const;
0367 
0368     //! Sets synchronization policy for property values of this property
0369     //! See ValueSyncPolicy for details.
0370     //! @since 3.1
0371     void setValueSyncPolicy(ValueSyncPolicy policy);
0372 
0373     /*! Sets value \a val for option \a name.
0374      Options are used to override default settings of individual properties.
0375      They are most visible in property editor widgets. Option is set if it is not null.
0376      This means that empty string can be still a valid value.
0377      To unset given option, call setOption() with a null QVariant value.
0378 
0379     Currently supported options are:
0380     <ul>
0381     <li> min: value describing minimum value for properties of integer, double,
0382          date, date/time and time types. Default is 0 for double and unsigned integer types,
0383          -INT_MAX for signed integer type.
0384          Defaults for date, date/time and time types are specified in documentation
0385          of QDateEdit::minimumDate, QDateTimeEdit::minimumDateTime and QTime::minimumTime, respectively.
0386          The value specified for this option is accepted if:
0387          - it is not larger than the value of the "max" option
0388          - it is not smaller than KPROPERTY_MIN_PRECISE_DOUBLE (for double type)
0389          - it is not smaller than -INT_MAX (for integer type)
0390          - it is not smaller than 0 (for unsigned integer type).
0391          </li>
0392     <li> minValueText: user-visible translated string to be displayed in editor for integer,
0393          double, date, date/time and time types when the value is equal to the value of
0394          "min" option.
0395          The value specified for this option is accepted if min option is supported for given type
0396          and is specified.
0397          @see QAbstractSpinBox::specialValueText</li>
0398     <li> max: value describing minimum value for properties of integer type.
0399          Default is KPROPERTY_MAX_PRECISE_DOUBLE for double type (maximum precise value)
0400          and INT_MAX for integer type.
0401          Defaults for date, date/time and time types are specified in documentation
0402          of QDateEdit::maximumDate, QDateTimeEdit::maximumDateTime and QTime::maximumTime, respectively.
0403          The value is ignored if it is smaller than the value of "min" option. </li>
0404          The value specified for this option is accepted if:
0405          - it is not smaller than the value of the "min" option
0406          - it is not larger than KPROPERTY_MAX_PRECISE_DOUBLE (for double type)
0407          - it is not larger than INT_MAX (for integer and unsigned integer type).
0408          </li>
0409     <li> precision: integer value >= 0 describing the number of decimals after the decimal
0410          point for double type. Default value is 2.
0411          @see QDoubleSpinBox::decimals</li>
0412     <li> step: double value > 0.0 describing the size of the step that is taken when
0413          the user hits the up or down button of editor for double type. Default value is 0.01.
0414          @see QDoubleSpinBox::singleStep</li>
0415     <li> 3State: boolean value used for boolean type; if @c true, the editor becomes a combobox
0416          (instead of checkable button) and accepts the third "null" state. Otherwise the boolean
0417          type only accepts @c true and @c false values, anything other, including invalid and null
0418          values, is converted to @c false.</li>
0419     <li> yesName: user-visible translated string used for boolean type (both 2- and 3-state)
0420          to visually represent the "true" value. If not present, tr("Yes") is used.</li>
0421     <li> noName: user-visible translated string used for boolean type (both 2- and 3-state)
0422          to visually represent the "false" value. If not present, tr("No") is used.</li>
0423     <li> 3rdStateName: user-visible translated string used for boolean type (both 2- and 3-state)
0424          to visually represent the third "null" value. If not present, tr("None") is used.</li>
0425     <li> nullName: user-visible translated string used for boolean type to display the "null"
0426          value, if and only if the property accepts two states (i.e. when "3State" option
0427          is @c false). If the "nullName" option is not set, null values are displayed as
0428          @c false.</li>
0429     <li> extraValueAllowed: boolean value, if @c true the user is able to manually add extra
0430          values to a combobox.</li>
0431     <li> fileMode: string value that describes types of objects that can be selected by the url
0432          editor:
0433          <ul>
0434          <li>"dirsOnly": only display and allow to select existing directories;
0435              @see QFileDialog::getExistingDirectoryUrl()</li>
0436          <li>"existingFile": only allow to select one existing file for opening, i.e. confirmation
0437              of overwriting is not performed;
0438              @see QFileDialog::getOpenFileUrl()</li>
0439          <li>Any other value: any file is supported, whether it exists or not; if the file exists,
0440              "confirmOverwrites" option is honored; this mode is the only one supporting non-file
0441              protocols such as ftp or http; to use them user has to enter them explicitly,
0442              file protocol is still the default
0443              @see QFileDialog::getSaveFileUrl()</li>
0444          </ul>
0445          @note Empty URLs are always allowed.
0446          </li>
0447     <li> confirmOverwrites: boolean value supported by the url editor; if @c true and the "fileMode"
0448          option is not equal to "existingFile" nor "dirsOnly" user will be asked for confirmation
0449          of file overwriting if selected file exists. @c false by default.
0450          @note The line edit does not validate the content.</li>
0451     <li> multiLine: boolean value used for string type. If @c true, a multi-line
0452          QPlainTextEdit-based widget is used for editor; otherwise a single-line QLineEdit
0453          widget is used. @c false by default. Added in version 3.1.</li>
0454     <li>prefix: string to display before the value, e.g. '$'. Supported for double and integer
0455         types and composed types based on double and integer types (Point*, Size*, Rect*).
0456         @see QDoubleSpinBox::prefix QSpinBox::prefix</li>
0457     <li>suffix: string to display after the value, e.g. unit such as 'mm'.
0458         Supported for double and integer types and composed types based on double and
0459         integer types (Point*, Size*, Rect*). Note that only display is affected, value
0460         is not converted to any unit.
0461         @see QDoubleSpinBox::suffix QSpinBox::suffix</li>
0462     </ul>*/
0463     void setOption(const char* name, const QVariant& val);
0464 
0465     /*! @brief Returns value of given option
0466      * Option is set if returned value is not null.
0467      * If there is no option for @a name in given property and parent property is present (see parent()),
0468      * parent property is checked. If the parent property offers the option, the value
0469      * is returned. If it is not present there, @a defaultValue value is returned.
0470      * Looking at parent property is available since 3.1.
0471      * @note The lookup is performed recursively, first in parent, then grand parent, etc.
0472      * @see setOption
0473      */
0474     QVariant option(const char* name, const QVariant& defaultValue = QVariant()) const;
0475 
0476     /*! @brief Returns @c true if at least one option is specified for this property
0477      * If there are no options defined @c true can be still returned if parent property
0478      * is present and it has at least one option specified.
0479      * Looking at parent property is available since 3.1.
0480      * @note The lookup is performed recursively, first in parent, then grand parent, etc.
0481      */
0482     bool hasOptions() const;
0483 
0484     /*! Equivalent to setValue(const QVariant &) */
0485     KProperty& operator= (const QVariant& val);
0486 
0487     /*! Assigns a deep copy of all attributes of \a property to this property. */
0488     KProperty& operator= (const KProperty &property);
0489 
0490     /**
0491      * @return @c true if the property is equal to @a prop; otherwise returns @c false.
0492      * Two properties are equal if they have the same name and type.
0493      * @note All null properties are equal
0494      * @todo Compare properties deeper?
0495      */
0496     bool operator==(const KProperty &prop) const;
0497 
0498     /**
0499      * @return @c true if the property is different from @a prop; otherwise returns @c false.
0500      * Two properties are different if they have different names or types.
0501      * @since 3.1
0502      */
0503     bool operator!=(const KProperty &prop) const;
0504 
0505 #if 0
0506     /*! \return a key used for sorting.
0507      Usually its set by KPropertySet::addProperty() and KProperty::addChild() to a unique value,
0508      so that this property can be sorted in a property editor in original order.
0509      \see EditorItem::compare() */
0510     int sortingKey() const;
0511 #endif
0512 
0513 private:
0514     //! Added only to help porting old code. Use public setValue() methods.
0515     void setValue(const QVariant &value, bool a1, bool a2 = true);
0516 
0517     class Private;
0518     Private * const d;
0519 
0520     friend class KPropertySet;
0521     friend class KPropertySetPrivate;
0522     friend class KPropertySetBuffer;
0523     friend KPROPERTYCORE_EXPORT QDebug operator<<(QDebug dbg, const KProperty &p);
0524 };
0525 
0526 //! qDebug() stream operator. Writes property @a p to the debug output in a nicely formatted way.
0527 KPROPERTYCORE_EXPORT QDebug operator<<(QDebug dbg, const KProperty &p);
0528 
0529 Q_DECLARE_OPERATORS_FOR_FLAGS(KProperty::ValueOptions)
0530 
0531 #endif