1 /* This file is part of the KDE project 2 Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr> 3 Copyright (C) 2004 Alexander Dymo <cloudtemple@mskat.net> 4 Copyright (C) 2004-2017 Jarosław Staniek <staniek@kde.org> 5 6 This library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Library General Public 8 License as published by the Free Software Foundation; either 9 version 2 of the License, or (at your option) any later version. 10 11 This library is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Library General Public License for more details. 15 16 You should have received a copy of the GNU Library General Public License 17 along with this library; see the file COPYING.LIB. If not, write to 18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA. 20 */ 21 22 #ifndef KPROPERTY_PROPERTY_H 23 #define KPROPERTY_PROPERTY_H 24 25 #include <QVariant> 26 #include <QStringList> 27 #include <QByteArray> 28 #include <QDebug> 29 30 #include <cmath> 31 #include <limits> 32 33 #include "kpropertycore_export.h" 34 35 class KComposedPropertyInterface; 36 class KPropertyListData; 37 class KPropertySet; 38 class KPropertySetPrivate; 39 40 /** 41 * @brief Minimum double value working precisely. 42 * 43 * @since 3.1 44 */ 45 #define KPROPERTY_MIN_PRECISE_DOUBLE (-pow(2, std::numeric_limits<double>::digits)) 46 47 /** 48 * @brief Minimum double value working precisely 49 * 50 * Editor for double values (spin box) has localized contents and its code supports just this maximum. 51 * For a 64-bit machine it's 2**53. 52 * See also https://phabricator.kde.org/D5419#inline-22329 53 * 54 * @since 3.1 55 */ 56 #define KPROPERTY_MAX_PRECISE_DOUBLE (pow(2, std::numeric_limits<double>::digits)) 57 58 /*! \brief The base class representing a single property 59 60 KProperty object can hold a property of given type supported by QVariant. Properties of custom types 61 can be also created, see using KPropertyFactory. Composed or custom properties 62 are not created using subclassing of KProperty but using @ref KComposedPropertyInterface. 63 64 Each property stores old value to allows undoing that reverts the value to the old one. 65 Property has a non-empty name (a QByteArray), a caption that is user-visible translated string 66 displayed in property editor. Description is a translatable string that can be specified too 67 in order to further explain meaning of the property. 68 69 Propery also supports setting arbitrary number of options using KProperty::setOption() that allow 70 to customize look or behavior of the property in the editor. 71 72 @code 73 // Creating a simple property: 74 KProperty *property = new KProperty(name, value, caption, description); 75 // name is a QByteArray, value is whatever type QVariant supports 76 77 // Creating a property of type ValueFromList matching keys with names: 78 QStringList keys({"one", "two", "three"}); // possible values of the property 79 QStringList names({tr("One"), tr("Two"), tr("Three")}); // Names (possibly translated) shown in 80 // the editor instead of the keys 81 property = new KProperty(name, new KPropertyListData(keys, names), "two", caption); 82 83 // Creating a property of type ValueFromList matching variant keys with names: 84 KPropertyListData *listData = new KPropertyListData({1.1, tr("One")}, {2.5, tr("Two")}, {3., tr("Three")}}); 85 propertySet->addProperty(new KProperty("List", listData, "otheritem", "List")); 86 @endcode 87 88 @note Sometimes it makes sense to split property captions that have with more words to multiple lines 89 using a newline character, e.g. "Allow Zero Size" to "Allow Zero\nSize". 90 This is suitable especially for the needs of property editor which can offer only limited area. 91 The text of property caption containing newline characters is available in its original form using 92 KProperty::captionForDisplaying(). KProperty::caption() returns modified caption text in which 93 the newline characters are substituted with spaces and any trailing and leading whitespace is removed. 94 */ 95 class KPROPERTYCORE_EXPORT KProperty 96 { 97 public: 98 /*! Defines types of properties. 99 Properties defined by plugins should have a type number >= UserDefined .*/ 100 enum Type { 101 //standard supported QVariant types 102 Auto = 0x00ffffff, 103 Invalid = QVariant::Invalid, 104 BitArray = QVariant::BitArray, 105 Bitmap = QVariant::Bitmap, 106 Bool = QVariant::Bool, 107 Brush = QVariant::Brush, 108 ByteArray = QVariant::ByteArray, 109 Char = QVariant::Char, 110 Color = QVariant::Color, 111 Cursor = QVariant::Cursor, 112 Date = QVariant::Date, 113 DateTime = QVariant::DateTime, 114 Double = QVariant::Double, 115 Font = QVariant::Font, 116 Icon = QVariant::Icon, 117 Image = QVariant::Image, 118 Int = QVariant::Int, 119 KeySequence = QVariant::KeySequence, 120 Line = QVariant::Line, 121 LineF = QVariant::LineF, 122 List = QVariant::List, 123 Locale = QVariant::Locale, 124 LongLong = QVariant::LongLong, 125 Map = QVariant::Map, 126 Matrix = QVariant::Matrix, 127 Transform = QVariant::Transform, 128 Palette = QVariant::Palette, 129 Pen = QVariant::Pen, 130 Pixmap = QVariant::Pixmap, 131 Point = QVariant::Point, 132 PointF = QVariant::PointF, 133 Polygon = QVariant::Polygon, 134 Rect = QVariant::Rect, 135 RectF = QVariant::RectF, 136 RegExp = QVariant::RegExp, 137 Region = QVariant::Region, 138 Size = QVariant::Size, 139 SizeF = QVariant::SizeF, 140 SizePolicy = QVariant::SizePolicy, 141 String = QVariant::String, 142 StringList = QVariant::StringList, 143 TextFormat = QVariant::TextFormat, 144 TextLength = QVariant::TextLength, 145 Time = QVariant::Time, 146 UInt = QVariant::UInt, 147 ULongLong = QVariant::ULongLong, 148 Url = QVariant::Url, 149 150 //predefined custom types 151 ValueFromList = 1000, /**<string value from a list*/ 152 Symbol, /**<unicode symbol code*/ 153 FontName, /**<font name, e.g. "times new roman"*/ 154 LineStyle, /**<line style*/ 155 ComposedUrl /**<composed URL @since 3.2 */, 156 157 UserDefined = 4000 /**<plugin defined properties should start here*/ 158 }; 159 160 /** 161 * Constructs a null property. 162 * Null properties have empty names and captions and Invalid types. 163 */ 164 KProperty(); 165 166 /*! Constructs property of a simple type. */ 167 explicit KProperty(const QByteArray &name, const QVariant &value = QVariant(), 168 const QString &caption = QString(), const QString &description = QString(), 169 int type = Auto, KProperty* parent = nullptr); 170 171 /** 172 * @brief Constructs property of ValueFromList type 173 * 174 * Ownership of @a listData is passed to the property object. 175 */ 176 KProperty(const QByteArray &name, KPropertyListData *listData, 177 const QVariant &value = QVariant(), 178 const QString &caption = QString(), const QString &description = QString(), 179 int type = ValueFromList, KProperty* parent = nullptr); 180 181 /*! Constructs a deep copy of \a prop property. */ 182 KProperty(const KProperty &prop); 183 184 ~KProperty(); 185 186 /** 187 * @return name of the property 188 * @note empty name means a null property 189 */ 190 QByteArray name() const; 191 192 /** 193 * Sets name of the property 194 * @note empty name means a null property 195 */ 196 void setName(const QByteArray &name); 197 198 /*! \return the caption of the property. Does not contain newline characters. Can be empty. */ 199 QString caption() const; 200 201 /*! \return the caption of the property or name() if the caption is empty. */ captionOrName()202 inline QString captionOrName() const 203 { 204 return caption().isEmpty() ? QString::fromLatin1(name()) : caption(); 205 } 206 207 /*! \return the caption text of the property for displaying. 208 It is similar to caption() but if the property caption contains newline characters, 209 these are not substituted with spaces. */ 210 QString captionForDisplaying() const; 211 212 /*! Sets the name of the property. If the caption contains newline characters, 213 these are substituted with spaces. 214 @see captionForDisplaying 215 */ 216 void setCaption(const QString &caption); 217 218 /*! \return the description of the property.*/ 219 QString description() const; 220 221 /*! Sets the description of the property.*/ 222 void setDescription(const QString &description); 223 224 /*! \return the type of the property.*/ 225 int type() const; 226 227 /*! Sets the type of the property.*/ 228 void setType(int type); 229 230 /*! \return the value of the property.*/ 231 QVariant value() const; 232 233 /*! Returns the previous property value if it was set in setValue(). */ 234 QVariant oldValue() const; 235 236 //! Options that influence how values are handled in setValue() and valueEqualsTo() 237 //! @since 3.1 238 enum class ValueOption { 239 None = 0, //!< No options, that is 1. old value is remembered before setting a new one; 240 //!< 2. composed properties are considered while comparing old and new value 241 IgnoreOld = 1, //!< Do not remember the old value before setting a new one 242 IgnoreComposedProperty = 2 //!< Do not use composed property when comparing values 243 }; 244 Q_DECLARE_FLAGS(ValueOptions, ValueOption) 245 246 /** 247 * @brief Sets value of the property. 248 * @param value New value 249 * @param options Options for the value setting. 250 * @return @c true if the value has been changed and @c false if the @a value was the same 251 * as previous one so it was not changed of if this property is null. 252 */ 253 bool setValue(const QVariant &value, ValueOptions options = ValueOptions()); 254 255 /** 256 * @return true if value of this property is equal to specified value 257 * 258 * Takes type into account. 259 * @param value Value to compare. 260 * @param valueOptions Options to use when comparing. 261 * Only the @c None and IgnoreComposedProperties are supported. 262 * @since 3.1 263 */ 264 bool valueEqualsTo(const QVariant &value, ValueOptions valueOptions = ValueOptions()) const; 265 266 /*! Resets the value of the property to the old value. 267 @see oldValue() */ 268 void resetValue(); 269 270 /*! \return the qstring-to-value correspondence list of the property. 271 used to create comboboxes-like property editors.*/ 272 KPropertyListData* listData() const; 273 274 /*! Sets the qstring-to-value correspondence list of the property. 275 This is used to create comboboxes-like property editors.*/ 276 void setListData(KPropertyListData* list); 277 278 /*! Sets the string-to-value correspondence list of the property. 279 This is used to create comboboxes-like property editors. 280 This is overload of the above ctor added for convenience. */ 281 void setListData(const QStringList &keys, const QStringList &names); 282 283 /*! Sets icon name to \a name for this property. Icons are optional and are used e.g. 284 in property editor - displayed at the left hand. */ 285 void setIconName(const QString &name); 286 287 /*! \return property icon's name. Can be empty. */ 288 QString iconName() const; 289 290 /*! \return a list of all children for this property, or NULL of there 291 is no children for this property */ 292 const QList<KProperty*>* children() const; 293 294 /*! \return a child property for \a name, or NULL if there is no property with that name. */ 295 KProperty* child(const QByteArray &name); 296 297 /*! \return parent property for this property, or NULL if there is no parent property. */ 298 KProperty* parent() const; 299 300 /*! \return the composed property for this property, or NULL if there was 301 no composed property defined. */ 302 KComposedPropertyInterface* composedProperty() const; 303 304 /*! Sets composed property \a prop for this property. */ 305 void setComposedProperty(KComposedPropertyInterface *prop); 306 307 /*! \return true if this property is null. Property is null if it has empty name. */ 308 bool isNull() const; 309 310 /** 311 * @brief Return @c true if value of this property or value of any child property is modified. 312 * 313 * @see clearModifiedFlag() 314 */ 315 bool isModified() const; 316 317 /** 318 * @brief Clears the "modified" flag for this property and all its child properties. 319 * 320 * After calling this method isModified() returs false for the property and all child 321 * properties. 322 * 323 * @see isModified() 324 */ 325 void clearModifiedFlag(); 326 327 /*! \return true if the property is read-only when used in a property editor. 328 @c false by default. 329 The property can be read-write but still not editable for the user if the parent property set's 330 read-only flag is set. 331 @see KPropertySet::isReadOnly() */ 332 bool isReadOnly() const; 333 334 /*! Sets this property to be read-only. 335 @see isReadOnly() */ 336 void setReadOnly(bool readOnly); 337 338 /*! \return true if the property is visible. 339 Only visible properties are displayed by the property editor view. */ 340 bool isVisible() const; 341 342 /*! Sets the visibility flag.*/ 343 void setVisible(bool visible); 344 345 /*! \return true if the property can be saved to a stream, xml, etc. 346 There is a possibility to use "GUI" properties that aren't 347 stored but used only in a GUI.*/ 348 bool isStorable() const; 349 350 /*! Sets "storable" flag for this property. @see isStorable() */ 351 void setStorable(bool storable); 352 353 //! Synchronization policy for property values 354 //! @since 3.1 355 enum class ValueSyncPolicy { 356 Editor, //!< Allow to synchronize by the property editor using its valueSync setting (default) 357 FocusOut, //!< Synchronize the value when focus is out of the editor widget for this property 358 //!< or when the user presses the Enter key 359 Auto //!< Synchronize automatically as soon as the editor widget for this property signals 360 //! (using commitData) that the value has been changed, e.g. when the user types 361 //! another letter in a text box 362 }; 363 364 //! @return synchronization policy for property values of this property 365 //! @since 3.1 366 ValueSyncPolicy valueSyncPolicy() const; 367 368 //! Sets synchronization policy for property values of this property 369 //! See ValueSyncPolicy for details. 370 //! @since 3.1 371 void setValueSyncPolicy(ValueSyncPolicy policy); 372 373 /*! Sets value \a val for option \a name. 374 Options are used to override default settings of individual properties. 375 They are most visible in property editor widgets. Option is set if it is not null. 376 This means that empty string can be still a valid value. 377 To unset given option, call setOption() with a null QVariant value. 378 379 Currently supported options are: 380 <ul> 381 <li> min: value describing minimum value for properties of integer, double, 382 date, date/time and time types. Default is 0 for double and unsigned integer types, 383 -INT_MAX for signed integer type. 384 Defaults for date, date/time and time types are specified in documentation 385 of QDateEdit::minimumDate, QDateTimeEdit::minimumDateTime and QTime::minimumTime, respectively. 386 The value specified for this option is accepted if: 387 - it is not larger than the value of the "max" option 388 - it is not smaller than KPROPERTY_MIN_PRECISE_DOUBLE (for double type) 389 - it is not smaller than -INT_MAX (for integer type) 390 - it is not smaller than 0 (for unsigned integer type). 391 </li> 392 <li> minValueText: user-visible translated string to be displayed in editor for integer, 393 double, date, date/time and time types when the value is equal to the value of 394 "min" option. 395 The value specified for this option is accepted if min option is supported for given type 396 and is specified. 397 @see QAbstractSpinBox::specialValueText</li> 398 <li> max: value describing minimum value for properties of integer type. 399 Default is KPROPERTY_MAX_PRECISE_DOUBLE for double type (maximum precise value) 400 and INT_MAX for integer type. 401 Defaults for date, date/time and time types are specified in documentation 402 of QDateEdit::maximumDate, QDateTimeEdit::maximumDateTime and QTime::maximumTime, respectively. 403 The value is ignored if it is smaller than the value of "min" option. </li> 404 The value specified for this option is accepted if: 405 - it is not smaller than the value of the "min" option 406 - it is not larger than KPROPERTY_MAX_PRECISE_DOUBLE (for double type) 407 - it is not larger than INT_MAX (for integer and unsigned integer type). 408 </li> 409 <li> precision: integer value >= 0 describing the number of decimals after the decimal 410 point for double type. Default value is 2. 411 @see QDoubleSpinBox::decimals</li> 412 <li> step: double value > 0.0 describing the size of the step that is taken when 413 the user hits the up or down button of editor for double type. Default value is 0.01. 414 @see QDoubleSpinBox::singleStep</li> 415 <li> 3State: boolean value used for boolean type; if @c true, the editor becomes a combobox 416 (instead of checkable button) and accepts the third "null" state. Otherwise the boolean 417 type only accepts @c true and @c false values, anything other, including invalid and null 418 values, is converted to @c false.</li> 419 <li> yesName: user-visible translated string used for boolean type (both 2- and 3-state) 420 to visually represent the "true" value. If not present, tr("Yes") is used.</li> 421 <li> noName: user-visible translated string used for boolean type (both 2- and 3-state) 422 to visually represent the "false" value. If not present, tr("No") is used.</li> 423 <li> 3rdStateName: user-visible translated string used for boolean type (both 2- and 3-state) 424 to visually represent the third "null" value. If not present, tr("None") is used.</li> 425 <li> nullName: user-visible translated string used for boolean type to display the "null" 426 value, if and only if the property accepts two states (i.e. when "3State" option 427 is @c false). If the "nullName" option is not set, null values are displayed as 428 @c false.</li> 429 <li> extraValueAllowed: boolean value, if @c true the user is able to manually add extra 430 values to a combobox.</li> 431 <li> fileMode: string value that describes types of objects that can be selected by the url 432 editor: 433 <ul> 434 <li>"dirsOnly": only display and allow to select existing directories; 435 @see QFileDialog::getExistingDirectoryUrl()</li> 436 <li>"existingFile": only allow to select one existing file for opening, i.e. confirmation 437 of overwriting is not performed; 438 @see QFileDialog::getOpenFileUrl()</li> 439 <li>Any other value: any file is supported, whether it exists or not; if the file exists, 440 "confirmOverwrites" option is honored; this mode is the only one supporting non-file 441 protocols such as ftp or http; to use them user has to enter them explicitly, 442 file protocol is still the default 443 @see QFileDialog::getSaveFileUrl()</li> 444 </ul> 445 @note Empty URLs are always allowed. 446 </li> 447 <li> confirmOverwrites: boolean value supported by the url editor; if @c true and the "fileMode" 448 option is not equal to "existingFile" nor "dirsOnly" user will be asked for confirmation 449 of file overwriting if selected file exists. @c false by default. 450 @note The line edit does not validate the content.</li> 451 <li> multiLine: boolean value used for string type. If @c true, a multi-line 452 QPlainTextEdit-based widget is used for editor; otherwise a single-line QLineEdit 453 widget is used. @c false by default. Added in version 3.1.</li> 454 <li>prefix: string to display before the value, e.g. '$'. Supported for double and integer 455 types and composed types based on double and integer types (Point*, Size*, Rect*). 456 @see QDoubleSpinBox::prefix QSpinBox::prefix</li> 457 <li>suffix: string to display after the value, e.g. unit such as 'mm'. 458 Supported for double and integer types and composed types based on double and 459 integer types (Point*, Size*, Rect*). Note that only display is affected, value 460 is not converted to any unit. 461 @see QDoubleSpinBox::suffix QSpinBox::suffix</li> 462 </ul>*/ 463 void setOption(const char* name, const QVariant& val); 464 465 /*! @brief Returns value of given option 466 * Option is set if returned value is not null. 467 * If there is no option for @a name in given property and parent property is present (see parent()), 468 * parent property is checked. If the parent property offers the option, the value 469 * is returned. If it is not present there, @a defaultValue value is returned. 470 * Looking at parent property is available since 3.1. 471 * @note The lookup is performed recursively, first in parent, then grand parent, etc. 472 * @see setOption 473 */ 474 QVariant option(const char* name, const QVariant& defaultValue = QVariant()) const; 475 476 /*! @brief Returns @c true if at least one option is specified for this property 477 * If there are no options defined @c true can be still returned if parent property 478 * is present and it has at least one option specified. 479 * Looking at parent property is available since 3.1. 480 * @note The lookup is performed recursively, first in parent, then grand parent, etc. 481 */ 482 bool hasOptions() const; 483 484 /*! Equivalent to setValue(const QVariant &) */ 485 KProperty& operator= (const QVariant& val); 486 487 /*! Assigns a deep copy of all attributes of \a property to this property. */ 488 KProperty& operator= (const KProperty &property); 489 490 /** 491 * @return @c true if the property is equal to @a prop; otherwise returns @c false. 492 * Two properties are equal if they have the same name and type. 493 * @note All null properties are equal 494 * @todo Compare properties deeper? 495 */ 496 bool operator==(const KProperty &prop) const; 497 498 /** 499 * @return @c true if the property is different from @a prop; otherwise returns @c false. 500 * Two properties are different if they have different names or types. 501 * @since 3.1 502 */ 503 bool operator!=(const KProperty &prop) const; 504 505 #if 0 506 /*! \return a key used for sorting. 507 Usually its set by KPropertySet::addProperty() and KProperty::addChild() to a unique value, 508 so that this property can be sorted in a property editor in original order. 509 \see EditorItem::compare() */ 510 int sortingKey() const; 511 #endif 512 513 private: 514 //! Added only to help porting old code. Use public setValue() methods. 515 void setValue(const QVariant &value, bool a1, bool a2 = true); 516 517 class Private; 518 Private * const d; 519 520 friend class KPropertySet; 521 friend class KPropertySetPrivate; 522 friend class KPropertySetBuffer; 523 friend KPROPERTYCORE_EXPORT QDebug operator<<(QDebug dbg, const KProperty &p); 524 }; 525 526 //! qDebug() stream operator. Writes property @a p to the debug output in a nicely formatted way. 527 KPROPERTYCORE_EXPORT QDebug operator<<(QDebug dbg, const KProperty &p); 528 529 Q_DECLARE_OPERATORS_FOR_FLAGS(KProperty::ValueOptions) 530 531 #endif 532