diff --git a/AUTHORS b/AUTHORS index 9d7b5369b6..6ff7cbddb7 100644 --- a/AUTHORS +++ b/AUTHORS @@ -362,6 +362,12 @@ Icons from the Elementary icon theme (GPLv3) * src/tiled/images/32/dialog-error.png * src/tiled/images/32/dialog-warning.png +Icons from the GNOME project (CC0 1.0 Universal) +* src/tiled/resources/images/scalable/text-bold-symbolic.svg +* src/tiled/resources/images/scalable/text-italic-symbolic.svg +* src/tiled/resources/images/scalable/text-underline-symbolic.svg +* src/tiled/resources/images/scalable/text-strikethrough-symbolic.svg + Tilesets: diff --git a/src/libtiled/imagelayer.cpp b/src/libtiled/imagelayer.cpp index 9086d87c8a..ab1169115c 100644 --- a/src/libtiled/imagelayer.cpp +++ b/src/libtiled/imagelayer.cpp @@ -104,8 +104,7 @@ ImageLayer *ImageLayer::initializeClone(ImageLayer *clone) const clone->mImageSource = mImageSource; clone->mTransparentColor = mTransparentColor; clone->mImage = mImage; - clone->mRepeatX = mRepeatX; - clone->mRepeatY = mRepeatY; + clone->mRepetition = mRepetition; return clone; } diff --git a/src/libtiled/imagelayer.h b/src/libtiled/imagelayer.h index 2a63df2071..faf00a4c6b 100644 --- a/src/libtiled/imagelayer.h +++ b/src/libtiled/imagelayer.h @@ -46,6 +46,19 @@ namespace Tiled { class TILEDSHARED_EXPORT ImageLayer : public Layer { public: + enum Repetition { + /** + * Makes the image repeat along the X axis. + */ + RepeatX = 0x1, + + /** + * Makes the image repeat along the Y axis. + */ + RepeatY = 0x2, + }; + Q_DECLARE_FLAGS(RepetitionFlags, Repetition) + ImageLayer(const QString &name, int x, int y); ~ImageLayer() override; @@ -114,25 +127,13 @@ class TILEDSHARED_EXPORT ImageLayer : public Layer */ bool isEmpty() const override; - /** - * Returns true if the image of this layer repeats along the X axis. - */ - bool repeatX() const { return mRepeatX; } - - /** - * Returns true if the image of this layer repeats along the Y axis. - */ - bool repeatY() const { return mRepeatY; } - - /** - * Sets whether the image of this layer repeats along the X axis. - */ - void setRepeatX(bool repeatX) { mRepeatX = repeatX; } + bool repeatX() const { return mRepetition & RepeatX; } + bool repeatY() const { return mRepetition & RepeatY; } + RepetitionFlags repetition() const { return mRepetition; } - /** - * Sets whether the image of this layer repeats along the Y axis. - */ - void setRepeatY(bool repeatY) { mRepeatY = repeatY; } + void setRepeatX(bool repeatX) { mRepetition.setFlag(RepeatX, repeatX); } + void setRepeatY(bool repeatY) { mRepetition.setFlag(RepeatY, repeatY); } + void setRepetition(RepetitionFlags repetition) { mRepetition = repetition; } ImageLayer *clone() const override; @@ -143,8 +144,10 @@ class TILEDSHARED_EXPORT ImageLayer : public Layer QUrl mImageSource; QColor mTransparentColor; QPixmap mImage; - bool mRepeatX = false; - bool mRepeatY = false; + RepetitionFlags mRepetition; }; } // namespace Tiled + +Q_DECLARE_METATYPE(Tiled::ImageLayer::RepetitionFlags) +Q_DECLARE_OPERATORS_FOR_FLAGS(Tiled::ImageLayer::RepetitionFlags) diff --git a/src/libtiled/map.h b/src/libtiled/map.h index 0abee3233e..f353ad72f8 100644 --- a/src/libtiled/map.h +++ b/src/libtiled/map.h @@ -78,8 +78,7 @@ class TILEDSHARED_EXPORT Map : public Object QString exportFormat; enum Property { - TileWidthProperty, - TileHeightProperty, + TileSizeProperty, InfiniteProperty, HexSideLengthProperty, StaggerAxisProperty, @@ -212,6 +211,7 @@ class TILEDSHARED_EXPORT Map : public Object void setTileHeight(int height); QSize tileSize() const; + void setTileSize(QSize size); bool infinite() const; void setInfinite(bool infinite); @@ -455,6 +455,12 @@ inline QSize Map::tileSize() const return QSize(mParameters.tileWidth, mParameters.tileHeight); } +inline void Map::setTileSize(QSize size) +{ + mParameters.tileWidth = size.width(); + mParameters.tileHeight = size.height(); +} + inline bool Map::infinite() const { return mParameters.infinite; @@ -791,3 +797,5 @@ Q_DECLARE_METATYPE(Tiled::Map*) Q_DECLARE_METATYPE(Tiled::Map::Orientation) Q_DECLARE_METATYPE(Tiled::Map::LayerDataFormat) Q_DECLARE_METATYPE(Tiled::Map::RenderOrder) +Q_DECLARE_METATYPE(Tiled::Map::StaggerAxis) +Q_DECLARE_METATYPE(Tiled::Map::StaggerIndex) diff --git a/src/libtiled/object.cpp b/src/libtiled/object.cpp index e8d1acc9f2..357ed62d06 100644 --- a/src/libtiled/object.cpp +++ b/src/libtiled/object.cpp @@ -40,6 +40,17 @@ Object::~Object() delete mEditable; } +const ClassPropertyType *Object::classType() const +{ + QString objectClassName = className(); + if (objectClassName.isEmpty() && typeId() == Object::MapObjectType) { + auto mapObject = static_cast(this); + objectClassName = mapObject->effectiveClassName(); + } + + return propertyTypes().findClassFor(objectClassName, *this); +} + /** * Returns the value of the property \a name, taking into account that it may * be inherited from another object or from the class. @@ -78,32 +89,36 @@ QVariant Object::resolvedProperty(const QString &name) const QVariantMap Object::resolvedProperties() const { QVariantMap allProperties; + Tiled::mergeProperties(allProperties, inheritedProperties()); + return allProperties; +} + +/** + * Computes the inherited properties for this object. This excludes the + * properties that are directly set on the object. + */ +QVariantMap Object::inheritedProperties() const +{ + QVariantMap inheritedProperties; + // Insert properties into allProperties in the reverse order that // Object::resolvedProperty searches them, to make sure that the // same precedence is maintained. - QString objectClassName = className(); - if (objectClassName.isEmpty() && typeId() == Object::MapObjectType) { - auto mapObject = static_cast(this); - objectClassName = mapObject->effectiveClassName(); - } - - if (auto type = propertyTypes().findClassFor(objectClassName, *this)) - Tiled::mergeProperties(allProperties, type->members); + if (auto type = classType()) + Tiled::mergeProperties(inheritedProperties, type->members); if (typeId() == Object::MapObjectType) { auto mapObject = static_cast(this); if (const Tile *tile = mapObject->cell().tile()) - Tiled::mergeProperties(allProperties, tile->properties()); + Tiled::mergeProperties(inheritedProperties, tile->properties()); if (const MapObject *templateObject = mapObject->templateObject()) - Tiled::mergeProperties(allProperties, templateObject->properties()); + Tiled::mergeProperties(inheritedProperties, templateObject->properties()); } - Tiled::mergeProperties(allProperties, properties()); - - return allProperties; + return inheritedProperties; } bool Object::setProperty(const QStringList &path, const QVariant &value) diff --git a/src/libtiled/object.h b/src/libtiled/object.h index 589fcbcd47..52b8592657 100644 --- a/src/libtiled/object.h +++ b/src/libtiled/object.h @@ -72,6 +72,8 @@ class TILEDSHARED_EXPORT Object const QString &className() const; void setClassName(const QString &className); + const ClassPropertyType *classType() const; + /** * Returns the properties of this object. */ @@ -111,6 +113,7 @@ class TILEDSHARED_EXPORT Object QVariant resolvedProperty(const QString &name) const; QVariantMap resolvedProperties() const; + QVariantMap inheritedProperties() const; /** * Returns the value of the object's \a name property, as a string. diff --git a/src/libtiled/objectgroup.h b/src/libtiled/objectgroup.h index 07765ebdbd..3abacd4a7e 100644 --- a/src/libtiled/objectgroup.h +++ b/src/libtiled/objectgroup.h @@ -238,3 +238,4 @@ TILEDSHARED_EXPORT ObjectGroup::DrawOrder drawOrderFromString(const QString &); } // namespace Tiled Q_DECLARE_METATYPE(Tiled::ObjectGroup*) +Q_DECLARE_METATYPE(Tiled::ObjectGroup::DrawOrder) diff --git a/src/libtiled/tileset.h b/src/libtiled/tileset.h index c7b5b01156..934adfdbfe 100644 --- a/src/libtiled/tileset.h +++ b/src/libtiled/tileset.h @@ -739,5 +739,9 @@ inline void Tileset::setTransformationFlags(TransformationFlags flags) Q_DECLARE_METATYPE(Tiled::Tileset*) Q_DECLARE_METATYPE(Tiled::SharedTileset) +Q_DECLARE_METATYPE(Tiled::Tileset::Orientation) +Q_DECLARE_METATYPE(Tiled::Tileset::TileRenderSize) +Q_DECLARE_METATYPE(Tiled::Tileset::FillMode) +Q_DECLARE_METATYPE(Tiled::Tileset::TransformationFlags) Q_DECLARE_OPERATORS_FOR_FLAGS(Tiled::Tileset::TransformationFlags) diff --git a/src/libtiled/wangset.h b/src/libtiled/wangset.h index 2955762c0a..c2df394b53 100644 --- a/src/libtiled/wangset.h +++ b/src/libtiled/wangset.h @@ -424,5 +424,6 @@ TILEDSHARED_EXPORT WangSet::Type wangSetTypeFromString(const QString &); } // namespace Tiled -Q_DECLARE_METATYPE(Tiled::WangSet*) Q_DECLARE_METATYPE(Tiled::WangId) +Q_DECLARE_METATYPE(Tiled::WangSet*) +Q_DECLARE_METATYPE(Tiled::WangSet::Type) diff --git a/src/qtpropertybrowser/README.TXT b/src/qtpropertybrowser/README.TXT deleted file mode 100644 index 148c47b4ba..0000000000 --- a/src/qtpropertybrowser/README.TXT +++ /dev/null @@ -1,93 +0,0 @@ -Qt Solutions Component: Property Browser - -A property browser framework enabling the user to edit a set of -properties. - -The framework provides a browser widget that displays the given -properties with labels and corresponding editing widgets (e.g. -line edits or comboboxes). The various types of editing widgets -are provided by the framework's editor factories: For each -property type, the framework provides a property manager (e.g. -QtIntPropertyManager and QtStringPropertyManager) which can be -associated with the preferred editor factory (e.g. -QtSpinBoxFactory and QtLineEditFactory). The framework also -provides a variant based property type with corresponding variant -manager and factory. Finally, the framework provides three -ready-made implementations of the browser widget: -QtTreePropertyBrowser, QtButtonPropertyBrowser and -QtGroupBoxPropertyBrowser. - -Version history: - -2.1: - QtTreePropertyBrowser - tooltip of property applied to - first column, while second column shows the value text of property - in its tooltip - - QtAbstractPropertyManager - initializeProperty() and - uninitializeProperty() without const modifier now - - QtTreePropertyBrowser and QtGroupBoxPropertyBrowser - internal - margin set to 0 - - QtProperty - setEnabled() and isEnabled() methods added - - QtTreePropertyBrowser - "rootIsDecorated", "indentation" and - "headerVisible" properties added - - QtProperty - hasValue() method added, useful for group - properties - -2.2: - FocusOut event now filtered out in case of - Qt::ActiveWindowFocusReason reason. In that case editor is not - closed when its sub dialog is executed - - Removed bug in color icon generation - - Decimals attribute added to "double" property type - - PointF, SizeF and RectF types supported - - Proper translation calls for tree property browser - - QtProperty - ensure inserted subproperty is different from - "this" property - - QtBrowserItem class introduced, useful for identifying browser's - gui elements - - Possibility to control expanded state of QtTreePropertyBrowser's - items from code - - QtTreePropertyBrowser - "resizeMode" and "splitterPosition" - properties added - - QtGroupBoxPropertyBrowser - fixed crash in case of deleting the - editor factory and then deleting the manager - - "Decoration" example added - it shows how to add new - responsibilities to the existing managers and editor factories - -2.3: - Various bugfixes and improvements - - QtProperty - setModified() and isModified() methods added - - QtTreePropertyBrowser - disabling an item closes its editor - - KeySequence, Char, Locale and Cursor types supported - - Support for icons in enum type added - - Kerning subproperty exposed in Font type - - New property browser class added - QtButtonPropertyBrowser with - drop down button as a grouping element - -2.4: - Fixed memory leak of QtProperty - - QtTreePropertyBrowser - group items are rendered better - - QtTreePropertyBrowser - propertiesWithoutValueMarked and - alternatingRowColors features added - - QtTreePropertyBrowser - possibility of coloring properties added - - QtTreePropertyBrowser - keyboard navigation improved - - New factories providing popup dialogs added: - QtColorEditorFactory and QtFontEditorFactory - - Single step attribute added to: QtIntPropertyManager and - QtDoublePropertyManager - -2.5: - "Object Controller" example added. It implements a similar - widget to the property editor in QDesigner - - Compile with QT_NO_CURSOR - - Expand root item with single click on the '+' icon - - QtRectPropertyManager and QtRectFPropertyManager - by default - constraint is null rect meaning no constraint is applied - -2.6: - QtGroupPropertyBrowser - don't force the layout to show the - whole labels' contents for read only properties, show tooltips for - them in addition. - - QtTreePropertyBrowser - fixed painting of the editor for color - property type when style sheet is used (QTSOLBUG-64). - - Make it possible to change the style of the checkboxes with a - stylesheet (QTSOLBUG-61). - - Change the minimum size of a combobox so that it can show at - least one character and an icon. - - Make it possible to properly style custom embedded editors (e.g. - the color editor provided with the solution). - diff --git a/src/qtpropertybrowser/common.pri b/src/qtpropertybrowser/common.pri deleted file mode 100644 index d6178c6645..0000000000 --- a/src/qtpropertybrowser/common.pri +++ /dev/null @@ -1,5 +0,0 @@ -TEMPLATE += fakelib -QTPROPERTYBROWSER_LIBNAME = $$qtLibraryTarget(QtSolutions_PropertyBrowser-head) -TEMPLATE -= fakelib -QTPROPERTYBROWSER_LIBDIR = $$PWD/lib -unix:qtpropertybrowser-uselib:!qtpropertybrowser-buildlib:QMAKE_RPATHDIR += $$QTPROPERTYBROWSER_LIBDIR diff --git a/src/qtpropertybrowser/qtpropertybrowser.qbs b/src/qtpropertybrowser/qtpropertybrowser.qbs deleted file mode 100644 index 53bad9bab8..0000000000 --- a/src/qtpropertybrowser/qtpropertybrowser.qbs +++ /dev/null @@ -1,46 +0,0 @@ -StaticLibrary { - name: "qtpropertybrowser" - - Depends { name: "cpp" } - Depends { name: "Qt"; submodules: ["widgets"] } - - cpp.includePaths: ["src"] - cpp.cxxLanguageVersion: "c++17" - cpp.cxxFlags: { - var flags = base; - if (qbs.toolchain.contains("msvc")) { - if (Qt.core.versionMajor >= 6 && Qt.core.versionMinor >= 3) - flags.push("/permissive-"); - } else if (qbs.toolchain.contains("mingw")) { - // needed to work around "too many sections" issue in qteditorfactory.cpp - if (Qt.core.versionMajor >= 6 && Qt.core.versionMinor >= 2) - flags.push("-Wa,-mbig-obj"); - } - return flags; - } - cpp.visibility: "minimal" - - files: [ - "src/qtbuttonpropertybrowser.cpp", - "src/qtbuttonpropertybrowser.h", - "src/qteditorfactory.cpp", - "src/qteditorfactory.h", - "src/qtgroupboxpropertybrowser.cpp", - "src/qtgroupboxpropertybrowser.h", - "src/qtpropertybrowser.cpp", - "src/qtpropertybrowser.h", - "src/qtpropertybrowserutils.cpp", - "src/qtpropertybrowserutils_p.h", - "src/qtpropertymanager.cpp", - "src/qtpropertymanager.h", - "src/qttreepropertybrowser.cpp", - "src/qttreepropertybrowser.h", - "src/qtvariantproperty.cpp", - "src/qtvariantproperty.h", - ] - - Export { - Depends { name: "cpp" } - cpp.includePaths: "src" - } -} diff --git a/src/qtpropertybrowser/src/QtAbstractEditorFactoryBase b/src/qtpropertybrowser/src/QtAbstractEditorFactoryBase deleted file mode 100644 index ab4e7104a4..0000000000 --- a/src/qtpropertybrowser/src/QtAbstractEditorFactoryBase +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertybrowser.h" diff --git a/src/qtpropertybrowser/src/QtAbstractPropertyBrowser b/src/qtpropertybrowser/src/QtAbstractPropertyBrowser deleted file mode 100644 index ab4e7104a4..0000000000 --- a/src/qtpropertybrowser/src/QtAbstractPropertyBrowser +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertybrowser.h" diff --git a/src/qtpropertybrowser/src/QtAbstractPropertyManager b/src/qtpropertybrowser/src/QtAbstractPropertyManager deleted file mode 100644 index ab4e7104a4..0000000000 --- a/src/qtpropertybrowser/src/QtAbstractPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertybrowser.h" diff --git a/src/qtpropertybrowser/src/QtBoolPropertyManager b/src/qtpropertybrowser/src/QtBoolPropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtBoolPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtBrowserItem b/src/qtpropertybrowser/src/QtBrowserItem deleted file mode 100644 index ab4e7104a4..0000000000 --- a/src/qtpropertybrowser/src/QtBrowserItem +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertybrowser.h" diff --git a/src/qtpropertybrowser/src/QtButtonPropertyBrowser b/src/qtpropertybrowser/src/QtButtonPropertyBrowser deleted file mode 100644 index 56e089704a..0000000000 --- a/src/qtpropertybrowser/src/QtButtonPropertyBrowser +++ /dev/null @@ -1 +0,0 @@ -#include "qtbuttonpropertybrowser.h" diff --git a/src/qtpropertybrowser/src/QtCharEditorFactory b/src/qtpropertybrowser/src/QtCharEditorFactory deleted file mode 100644 index 75f35adabc..0000000000 --- a/src/qtpropertybrowser/src/QtCharEditorFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qtpropertybrowser/src/QtCharPropertyManager b/src/qtpropertybrowser/src/QtCharPropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtCharPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtCheckBoxFactory b/src/qtpropertybrowser/src/QtCheckBoxFactory deleted file mode 100644 index 75f35adabc..0000000000 --- a/src/qtpropertybrowser/src/QtCheckBoxFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qtpropertybrowser/src/QtColorEditorFactory b/src/qtpropertybrowser/src/QtColorEditorFactory deleted file mode 100644 index 75f35adabc..0000000000 --- a/src/qtpropertybrowser/src/QtColorEditorFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qtpropertybrowser/src/QtColorPropertyManager b/src/qtpropertybrowser/src/QtColorPropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtColorPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtCursorEditorFactory b/src/qtpropertybrowser/src/QtCursorEditorFactory deleted file mode 100644 index 75f35adabc..0000000000 --- a/src/qtpropertybrowser/src/QtCursorEditorFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qtpropertybrowser/src/QtCursorPropertyManager b/src/qtpropertybrowser/src/QtCursorPropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtCursorPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtDateEditFactory b/src/qtpropertybrowser/src/QtDateEditFactory deleted file mode 100644 index 75f35adabc..0000000000 --- a/src/qtpropertybrowser/src/QtDateEditFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qtpropertybrowser/src/QtDatePropertyManager b/src/qtpropertybrowser/src/QtDatePropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtDatePropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtDateTimeEditFactory b/src/qtpropertybrowser/src/QtDateTimeEditFactory deleted file mode 100644 index 75f35adabc..0000000000 --- a/src/qtpropertybrowser/src/QtDateTimeEditFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qtpropertybrowser/src/QtDateTimePropertyManager b/src/qtpropertybrowser/src/QtDateTimePropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtDateTimePropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtDoublePropertyManager b/src/qtpropertybrowser/src/QtDoublePropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtDoublePropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtDoubleSpinBoxFactory b/src/qtpropertybrowser/src/QtDoubleSpinBoxFactory deleted file mode 100644 index 75f35adabc..0000000000 --- a/src/qtpropertybrowser/src/QtDoubleSpinBoxFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qtpropertybrowser/src/QtEnumEditorFactory b/src/qtpropertybrowser/src/QtEnumEditorFactory deleted file mode 100644 index 75f35adabc..0000000000 --- a/src/qtpropertybrowser/src/QtEnumEditorFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qtpropertybrowser/src/QtEnumPropertyManager b/src/qtpropertybrowser/src/QtEnumPropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtEnumPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtFlagPropertyManager b/src/qtpropertybrowser/src/QtFlagPropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtFlagPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtFontEditorFactory b/src/qtpropertybrowser/src/QtFontEditorFactory deleted file mode 100644 index 75f35adabc..0000000000 --- a/src/qtpropertybrowser/src/QtFontEditorFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qtpropertybrowser/src/QtFontPropertyManager b/src/qtpropertybrowser/src/QtFontPropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtFontPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtGroupBoxPropertyBrowser b/src/qtpropertybrowser/src/QtGroupBoxPropertyBrowser deleted file mode 100644 index 27964c0803..0000000000 --- a/src/qtpropertybrowser/src/QtGroupBoxPropertyBrowser +++ /dev/null @@ -1 +0,0 @@ -#include "qtgroupboxpropertybrowser.h" diff --git a/src/qtpropertybrowser/src/QtGroupPropertyManager b/src/qtpropertybrowser/src/QtGroupPropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtGroupPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtIntPropertyManager b/src/qtpropertybrowser/src/QtIntPropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtIntPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtKeySequenceEditorFactory b/src/qtpropertybrowser/src/QtKeySequenceEditorFactory deleted file mode 100644 index 75f35adabc..0000000000 --- a/src/qtpropertybrowser/src/QtKeySequenceEditorFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qtpropertybrowser/src/QtKeySequencePropertyManager b/src/qtpropertybrowser/src/QtKeySequencePropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtKeySequencePropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtLineEditFactory b/src/qtpropertybrowser/src/QtLineEditFactory deleted file mode 100644 index 75f35adabc..0000000000 --- a/src/qtpropertybrowser/src/QtLineEditFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qtpropertybrowser/src/QtLocalePropertyManager b/src/qtpropertybrowser/src/QtLocalePropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtLocalePropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtPointFPropertyManager b/src/qtpropertybrowser/src/QtPointFPropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtPointFPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtPointPropertyManager b/src/qtpropertybrowser/src/QtPointPropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtPointPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtProperty b/src/qtpropertybrowser/src/QtProperty deleted file mode 100644 index ab4e7104a4..0000000000 --- a/src/qtpropertybrowser/src/QtProperty +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertybrowser.h" diff --git a/src/qtpropertybrowser/src/QtRectFPropertyManager b/src/qtpropertybrowser/src/QtRectFPropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtRectFPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtRectPropertyManager b/src/qtpropertybrowser/src/QtRectPropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtRectPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtScrollBarFactory b/src/qtpropertybrowser/src/QtScrollBarFactory deleted file mode 100644 index 75f35adabc..0000000000 --- a/src/qtpropertybrowser/src/QtScrollBarFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qtpropertybrowser/src/QtSizeFPropertyManager b/src/qtpropertybrowser/src/QtSizeFPropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtSizeFPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtSizePolicyPropertyManager b/src/qtpropertybrowser/src/QtSizePolicyPropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtSizePolicyPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtSizePropertyManager b/src/qtpropertybrowser/src/QtSizePropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtSizePropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtSliderFactory b/src/qtpropertybrowser/src/QtSliderFactory deleted file mode 100644 index 75f35adabc..0000000000 --- a/src/qtpropertybrowser/src/QtSliderFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qtpropertybrowser/src/QtSpinBoxFactory b/src/qtpropertybrowser/src/QtSpinBoxFactory deleted file mode 100644 index 75f35adabc..0000000000 --- a/src/qtpropertybrowser/src/QtSpinBoxFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qtpropertybrowser/src/QtStringPropertyManager b/src/qtpropertybrowser/src/QtStringPropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtStringPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtTimeEditFactory b/src/qtpropertybrowser/src/QtTimeEditFactory deleted file mode 100644 index 75f35adabc..0000000000 --- a/src/qtpropertybrowser/src/QtTimeEditFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qteditorfactory.h" diff --git a/src/qtpropertybrowser/src/QtTimePropertyManager b/src/qtpropertybrowser/src/QtTimePropertyManager deleted file mode 100644 index 1842e431d3..0000000000 --- a/src/qtpropertybrowser/src/QtTimePropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtpropertymanager.h" diff --git a/src/qtpropertybrowser/src/QtTreePropertyBrowser b/src/qtpropertybrowser/src/QtTreePropertyBrowser deleted file mode 100644 index aab106c753..0000000000 --- a/src/qtpropertybrowser/src/QtTreePropertyBrowser +++ /dev/null @@ -1 +0,0 @@ -#include "qttreepropertybrowser.h" diff --git a/src/qtpropertybrowser/src/QtVariantEditorFactory b/src/qtpropertybrowser/src/QtVariantEditorFactory deleted file mode 100644 index 8118190d50..0000000000 --- a/src/qtpropertybrowser/src/QtVariantEditorFactory +++ /dev/null @@ -1 +0,0 @@ -#include "qtvariantproperty.h" diff --git a/src/qtpropertybrowser/src/QtVariantProperty b/src/qtpropertybrowser/src/QtVariantProperty deleted file mode 100644 index 8118190d50..0000000000 --- a/src/qtpropertybrowser/src/QtVariantProperty +++ /dev/null @@ -1 +0,0 @@ -#include "qtvariantproperty.h" diff --git a/src/qtpropertybrowser/src/QtVariantPropertyManager b/src/qtpropertybrowser/src/QtVariantPropertyManager deleted file mode 100644 index 8118190d50..0000000000 --- a/src/qtpropertybrowser/src/QtVariantPropertyManager +++ /dev/null @@ -1 +0,0 @@ -#include "qtvariantproperty.h" diff --git a/src/qtpropertybrowser/src/images/cursor-arrow.png b/src/qtpropertybrowser/src/images/cursor-arrow.png deleted file mode 100644 index a69ef4eb61..0000000000 Binary files a/src/qtpropertybrowser/src/images/cursor-arrow.png and /dev/null differ diff --git a/src/qtpropertybrowser/src/images/cursor-busy.png b/src/qtpropertybrowser/src/images/cursor-busy.png deleted file mode 100644 index 53717e4992..0000000000 Binary files a/src/qtpropertybrowser/src/images/cursor-busy.png and /dev/null differ diff --git a/src/qtpropertybrowser/src/images/cursor-closedhand.png b/src/qtpropertybrowser/src/images/cursor-closedhand.png deleted file mode 100644 index b78dd1dac5..0000000000 Binary files a/src/qtpropertybrowser/src/images/cursor-closedhand.png and /dev/null differ diff --git a/src/qtpropertybrowser/src/images/cursor-cross.png b/src/qtpropertybrowser/src/images/cursor-cross.png deleted file mode 100644 index fe38e74480..0000000000 Binary files a/src/qtpropertybrowser/src/images/cursor-cross.png and /dev/null differ diff --git a/src/qtpropertybrowser/src/images/cursor-forbidden.png b/src/qtpropertybrowser/src/images/cursor-forbidden.png deleted file mode 100644 index 2b08c4e2a3..0000000000 Binary files a/src/qtpropertybrowser/src/images/cursor-forbidden.png and /dev/null differ diff --git a/src/qtpropertybrowser/src/images/cursor-hand.png b/src/qtpropertybrowser/src/images/cursor-hand.png deleted file mode 100644 index d2004aefa7..0000000000 Binary files a/src/qtpropertybrowser/src/images/cursor-hand.png and /dev/null differ diff --git a/src/qtpropertybrowser/src/images/cursor-hsplit.png b/src/qtpropertybrowser/src/images/cursor-hsplit.png deleted file mode 100644 index a5667e3ffb..0000000000 Binary files a/src/qtpropertybrowser/src/images/cursor-hsplit.png and /dev/null differ diff --git a/src/qtpropertybrowser/src/images/cursor-ibeam.png b/src/qtpropertybrowser/src/images/cursor-ibeam.png deleted file mode 100644 index 097fc5fa72..0000000000 Binary files a/src/qtpropertybrowser/src/images/cursor-ibeam.png and /dev/null differ diff --git a/src/qtpropertybrowser/src/images/cursor-openhand.png b/src/qtpropertybrowser/src/images/cursor-openhand.png deleted file mode 100644 index 9181c859ed..0000000000 Binary files a/src/qtpropertybrowser/src/images/cursor-openhand.png and /dev/null differ diff --git a/src/qtpropertybrowser/src/images/cursor-sizeall.png b/src/qtpropertybrowser/src/images/cursor-sizeall.png deleted file mode 100644 index 69f13eb347..0000000000 Binary files a/src/qtpropertybrowser/src/images/cursor-sizeall.png and /dev/null differ diff --git a/src/qtpropertybrowser/src/images/cursor-sizeb.png b/src/qtpropertybrowser/src/images/cursor-sizeb.png deleted file mode 100644 index f37d7b91e8..0000000000 Binary files a/src/qtpropertybrowser/src/images/cursor-sizeb.png and /dev/null differ diff --git a/src/qtpropertybrowser/src/images/cursor-sizef.png b/src/qtpropertybrowser/src/images/cursor-sizef.png deleted file mode 100644 index 3b127a05d3..0000000000 Binary files a/src/qtpropertybrowser/src/images/cursor-sizef.png and /dev/null differ diff --git a/src/qtpropertybrowser/src/images/cursor-sizeh.png b/src/qtpropertybrowser/src/images/cursor-sizeh.png deleted file mode 100644 index a9f40cbc3d..0000000000 Binary files a/src/qtpropertybrowser/src/images/cursor-sizeh.png and /dev/null differ diff --git a/src/qtpropertybrowser/src/images/cursor-sizev.png b/src/qtpropertybrowser/src/images/cursor-sizev.png deleted file mode 100644 index 1edbab27a5..0000000000 Binary files a/src/qtpropertybrowser/src/images/cursor-sizev.png and /dev/null differ diff --git a/src/qtpropertybrowser/src/images/cursor-uparrow.png b/src/qtpropertybrowser/src/images/cursor-uparrow.png deleted file mode 100644 index d3e70ef4c2..0000000000 Binary files a/src/qtpropertybrowser/src/images/cursor-uparrow.png and /dev/null differ diff --git a/src/qtpropertybrowser/src/images/cursor-vsplit.png b/src/qtpropertybrowser/src/images/cursor-vsplit.png deleted file mode 100644 index 1beda2570e..0000000000 Binary files a/src/qtpropertybrowser/src/images/cursor-vsplit.png and /dev/null differ diff --git a/src/qtpropertybrowser/src/images/cursor-wait.png b/src/qtpropertybrowser/src/images/cursor-wait.png deleted file mode 100644 index 69056c479e..0000000000 Binary files a/src/qtpropertybrowser/src/images/cursor-wait.png and /dev/null differ diff --git a/src/qtpropertybrowser/src/images/cursor-whatsthis.png b/src/qtpropertybrowser/src/images/cursor-whatsthis.png deleted file mode 100644 index b47601c378..0000000000 Binary files a/src/qtpropertybrowser/src/images/cursor-whatsthis.png and /dev/null differ diff --git a/src/qtpropertybrowser/src/qtbuttonpropertybrowser.cpp b/src/qtpropertybrowser/src/qtbuttonpropertybrowser.cpp deleted file mode 100644 index 293fbf6bfd..0000000000 --- a/src/qtpropertybrowser/src/qtbuttonpropertybrowser.cpp +++ /dev/null @@ -1,627 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qtbuttonpropertybrowser.h" -#include -#include -#include -#include -#include -#include -#include - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QtButtonPropertyBrowserPrivate -{ - QtButtonPropertyBrowser *q_ptr; - Q_DECLARE_PUBLIC(QtButtonPropertyBrowser) -public: - - void init(QWidget *parent); - - void propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex); - void propertyRemoved(QtBrowserItem *index); - void propertyChanged(QtBrowserItem *index); - QWidget *createEditor(QtProperty *property, QWidget *parent) const - { return q_ptr->createEditor(property, parent); } - - void slotEditorDestroyed(); - void slotUpdate(); - void slotToggled(bool checked); - - struct WidgetItem - { - WidgetItem() : widget(0), label(0), widgetLabel(0), - button(0), container(0), layout(0), /*line(0), */parent(0), expanded(false) { } - QWidget *widget; // can be null - QLabel *label; // main label with property name - QLabel *widgetLabel; // label substitute showing the current value if there is no widget - QToolButton *button; // expandable button for items with children - QWidget *container; // container which is expanded when the button is clicked - QGridLayout *layout; // layout in container - WidgetItem *parent; - QList children; - bool expanded; - }; -private: - void updateLater(); - void updateItem(WidgetItem *item); - void insertRow(QGridLayout *layout, int row) const; - void removeRow(QGridLayout *layout, int row) const; - int gridRow(WidgetItem *item) const; - int gridSpan(WidgetItem *item) const; - void setExpanded(WidgetItem *item, bool expanded); - QToolButton *createButton(QWidget *panret = 0) const; - - QMap m_indexToItem; - QMap m_itemToIndex; - QMap m_widgetToItem; - QMap m_buttonToItem; - QGridLayout *m_mainLayout; - QList m_children; - QList m_recreateQueue; -}; - -QToolButton *QtButtonPropertyBrowserPrivate::createButton(QWidget *parent) const -{ - QToolButton *button = new QToolButton(parent); - button->setCheckable(true); - button->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed)); - button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - button->setArrowType(Qt::DownArrow); - button->setIconSize(QSize(3, 16)); - /* - QIcon icon; - icon.addPixmap(q_ptr->style()->standardPixmap(QStyle::SP_ArrowDown), QIcon::Normal, QIcon::Off); - icon.addPixmap(q_ptr->style()->standardPixmap(QStyle::SP_ArrowUp), QIcon::Normal, QIcon::On); - button->setIcon(icon); - */ - return button; -} - -int QtButtonPropertyBrowserPrivate::gridRow(WidgetItem *item) const -{ - QList siblings; - if (item->parent) - siblings = item->parent->children; - else - siblings = m_children; - - int row = 0; - QListIterator it(siblings); - while (it.hasNext()) { - WidgetItem *sibling = it.next(); - if (sibling == item) - return row; - row += gridSpan(sibling); - } - return -1; -} - -int QtButtonPropertyBrowserPrivate::gridSpan(WidgetItem *item) const -{ - if (item->container && item->expanded) - return 2; - return 1; -} - -void QtButtonPropertyBrowserPrivate::init(QWidget *parent) -{ - m_mainLayout = new QGridLayout(); - parent->setLayout(m_mainLayout); - QLayoutItem *item = new QSpacerItem(0, 0, - QSizePolicy::Fixed, QSizePolicy::Expanding); - m_mainLayout->addItem(item, 0, 0); -} - -void QtButtonPropertyBrowserPrivate::slotEditorDestroyed() -{ - QWidget *editor = qobject_cast(q_ptr->sender()); - if (!editor) - return; - if (!m_widgetToItem.contains(editor)) - return; - m_widgetToItem[editor]->widget = 0; - m_widgetToItem.remove(editor); -} - -void QtButtonPropertyBrowserPrivate::slotUpdate() -{ - QListIterator itItem(m_recreateQueue); - while (itItem.hasNext()) { - WidgetItem *item = itItem.next(); - - WidgetItem *parent = item->parent; - QWidget *w = 0; - QGridLayout *l = 0; - const int oldRow = gridRow(item); - if (parent) { - w = parent->container; - l = parent->layout; - } else { - w = q_ptr; - l = m_mainLayout; - } - - int span = 1; - if (!item->widget && !item->widgetLabel) - span = 2; - item->label = new QLabel(w); - item->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); - l->addWidget(item->label, oldRow, 0, 1, span); - - updateItem(item); - } - m_recreateQueue.clear(); -} - -void QtButtonPropertyBrowserPrivate::setExpanded(WidgetItem *item, bool expanded) -{ - if (item->expanded == expanded) - return; - - if (!item->container) - return; - - item->expanded = expanded; - const int row = gridRow(item); - WidgetItem *parent = item->parent; - QGridLayout *l = 0; - if (parent) - l = parent->layout; - else - l = m_mainLayout; - - if (expanded) { - insertRow(l, row + 1); - l->addWidget(item->container, row + 1, 0, 1, 2); - item->container->show(); - } else { - l->removeWidget(item->container); - item->container->hide(); - removeRow(l, row + 1); - } - - item->button->setChecked(expanded); - item->button->setArrowType(expanded ? Qt::UpArrow : Qt::DownArrow); -} - -void QtButtonPropertyBrowserPrivate::slotToggled(bool checked) -{ - WidgetItem *item = m_buttonToItem.value(q_ptr->sender()); - if (!item) - return; - - setExpanded(item, checked); - - if (checked) - emit q_ptr->expanded(m_itemToIndex.value(item)); - else - emit q_ptr->collapsed(m_itemToIndex.value(item)); -} - -void QtButtonPropertyBrowserPrivate::updateLater() -{ - QTimer::singleShot(0, q_ptr, SLOT(slotUpdate())); -} - -void QtButtonPropertyBrowserPrivate::propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex) -{ - WidgetItem *afterItem = m_indexToItem.value(afterIndex); - WidgetItem *parentItem = m_indexToItem.value(index->parent()); - - WidgetItem *newItem = new WidgetItem(); - newItem->parent = parentItem; - - QGridLayout *layout = 0; - QWidget *parentWidget = 0; - int row = -1; - if (!afterItem) { - row = 0; - if (parentItem) - parentItem->children.insert(0, newItem); - else - m_children.insert(0, newItem); - } else { - row = gridRow(afterItem) + gridSpan(afterItem); - if (parentItem) - parentItem->children.insert(parentItem->children.indexOf(afterItem) + 1, newItem); - else - m_children.insert(m_children.indexOf(afterItem) + 1, newItem); - } - - if (!parentItem) { - layout = m_mainLayout; - parentWidget = q_ptr; - } else { - if (!parentItem->container) { - m_recreateQueue.removeAll(parentItem); - WidgetItem *grandParent = parentItem->parent; - QGridLayout *l = 0; - const int oldRow = gridRow(parentItem); - if (grandParent) { - l = grandParent->layout; - } else { - l = m_mainLayout; - } - QFrame *container = new QFrame(); - container->setFrameShape(QFrame::Panel); - container->setFrameShadow(QFrame::Raised); - parentItem->container = container; - parentItem->button = createButton(); - m_buttonToItem[parentItem->button] = parentItem; - q_ptr->connect(parentItem->button, SIGNAL(toggled(bool)), q_ptr, SLOT(slotToggled(bool))); - parentItem->layout = new QGridLayout(); - container->setLayout(parentItem->layout); - if (parentItem->label) { - l->removeWidget(parentItem->label); - delete parentItem->label; - parentItem->label = 0; - } - int span = 1; - if (!parentItem->widget && !parentItem->widgetLabel) - span = 2; - l->addWidget(parentItem->button, oldRow, 0, 1, span); - updateItem(parentItem); - } - layout = parentItem->layout; - parentWidget = parentItem->container; - } - - newItem->label = new QLabel(parentWidget); - newItem->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); - newItem->widget = createEditor(index->property(), parentWidget); - if (newItem->widget) { - QObject::connect(newItem->widget, SIGNAL(destroyed()), q_ptr, SLOT(slotEditorDestroyed())); - m_widgetToItem[newItem->widget] = newItem; - } else if (index->property()->hasValue()) { - newItem->widgetLabel = new QLabel(parentWidget); - newItem->widgetLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed)); - } - - insertRow(layout, row); - int span = 1; - if (newItem->widget) - layout->addWidget(newItem->widget, row, 1); - else if (newItem->widgetLabel) - layout->addWidget(newItem->widgetLabel, row, 1); - else - span = 2; - layout->addWidget(newItem->label, row, 0, span, 1); - - m_itemToIndex[newItem] = index; - m_indexToItem[index] = newItem; - - updateItem(newItem); -} - -void QtButtonPropertyBrowserPrivate::propertyRemoved(QtBrowserItem *index) -{ - WidgetItem *item = m_indexToItem.value(index); - - m_indexToItem.remove(index); - m_itemToIndex.remove(item); - - WidgetItem *parentItem = item->parent; - - const int row = gridRow(item); - - if (parentItem) - parentItem->children.removeAt(parentItem->children.indexOf(item)); - else - m_children.removeAt(m_children.indexOf(item)); - - const int colSpan = gridSpan(item); - - m_buttonToItem.remove(item->button); - - if (item->widget) - delete item->widget; - if (item->label) - delete item->label; - if (item->widgetLabel) - delete item->widgetLabel; - if (item->button) - delete item->button; - if (item->container) - delete item->container; - - if (!parentItem) { - removeRow(m_mainLayout, row); - if (colSpan > 1) - removeRow(m_mainLayout, row); - } else if (parentItem->children.count() != 0) { - removeRow(parentItem->layout, row); - if (colSpan > 1) - removeRow(parentItem->layout, row); - } else { - const WidgetItem *grandParent = parentItem->parent; - QGridLayout *l = 0; - if (grandParent) { - l = grandParent->layout; - } else { - l = m_mainLayout; - } - - const int parentRow = gridRow(parentItem); - const int parentSpan = gridSpan(parentItem); - - l->removeWidget(parentItem->button); - l->removeWidget(parentItem->container); - delete parentItem->button; - delete parentItem->container; - parentItem->button = 0; - parentItem->container = 0; - parentItem->layout = 0; - if (!m_recreateQueue.contains(parentItem)) - m_recreateQueue.append(parentItem); - if (parentSpan > 1) - removeRow(l, parentRow + 1); - - updateLater(); - } - m_recreateQueue.removeAll(item); - - delete item; -} - -void QtButtonPropertyBrowserPrivate::insertRow(QGridLayout *layout, int row) const -{ - QMap itemToPos; - int idx = 0; - while (idx < layout->count()) { - int r, c, rs, cs; - layout->getItemPosition(idx, &r, &c, &rs, &cs); - if (r >= row) { - itemToPos[layout->takeAt(idx)] = QRect(r + 1, c, rs, cs); - } else { - idx++; - } - } - - const QMap::ConstIterator icend = itemToPos.constEnd(); - for(QMap::ConstIterator it = itemToPos.constBegin(); it != icend; ++it) { - const QRect r = it.value(); - layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height()); - } -} - -void QtButtonPropertyBrowserPrivate::removeRow(QGridLayout *layout, int row) const -{ - QMap itemToPos; - int idx = 0; - while (idx < layout->count()) { - int r, c, rs, cs; - layout->getItemPosition(idx, &r, &c, &rs, &cs); - if (r > row) { - itemToPos[layout->takeAt(idx)] = QRect(r - 1, c, rs, cs); - } else { - idx++; - } - } - - const QMap::ConstIterator icend = itemToPos.constEnd(); - for(QMap::ConstIterator it = itemToPos.constBegin(); it != icend; ++it) { - const QRect r = it.value(); - layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height()); - } -} - -void QtButtonPropertyBrowserPrivate::propertyChanged(QtBrowserItem *index) -{ - WidgetItem *item = m_indexToItem.value(index); - - updateItem(item); -} - -void QtButtonPropertyBrowserPrivate::updateItem(WidgetItem *item) -{ - QtProperty *property = m_itemToIndex[item]->property(); - if (item->button) { - QFont font = item->button->font(); - font.setUnderline(property->isModified()); - item->button->setFont(font); - item->button->setText(property->propertyName()); - item->button->setToolTip(property->toolTip()); - item->button->setStatusTip(property->statusTip()); - item->button->setWhatsThis(property->whatsThis()); - item->button->setEnabled(property->isEnabled()); - } - if (item->label) { - QFont font = item->label->font(); - font.setUnderline(property->isModified()); - item->label->setFont(font); - item->label->setText(property->propertyName()); - item->label->setToolTip(property->toolTip()); - item->label->setStatusTip(property->statusTip()); - item->label->setWhatsThis(property->whatsThis()); - item->label->setEnabled(property->isEnabled()); - } - if (item->widgetLabel) { - QFont font = item->widgetLabel->font(); - font.setUnderline(false); - item->widgetLabel->setFont(font); - item->widgetLabel->setText(property->valueText()); - item->widgetLabel->setToolTip(property->valueText()); - item->widgetLabel->setEnabled(property->isEnabled()); - } - if (item->widget) { - QFont font = item->widget->font(); - font.setUnderline(false); - item->widget->setFont(font); - item->widget->setEnabled(property->isEnabled()); - item->widget->setToolTip(property->valueText()); - } -} - - - -/*! - \class QtButtonPropertyBrowser - - \brief The QtButtonPropertyBrowser class provides a drop down QToolButton - based property browser. - - A property browser is a widget that enables the user to edit a - given set of properties. Each property is represented by a label - specifying the property's name, and an editing widget (e.g. a line - edit or a combobox) holding its value. A property can have zero or - more subproperties. - - QtButtonPropertyBrowser provides drop down button for all nested - properties, i.e. subproperties are enclosed by a container associated with - the drop down button. The parent property's name is displayed as button text. For example: - - \image qtbuttonpropertybrowser.png - - Use the QtAbstractPropertyBrowser API to add, insert and remove - properties from an instance of the QtButtonPropertyBrowser - class. The properties themselves are created and managed by - implementations of the QtAbstractPropertyManager class. - - \sa QtTreePropertyBrowser, QtAbstractPropertyBrowser -*/ - -/*! - \fn void QtButtonPropertyBrowser::collapsed(QtBrowserItem *item) - - This signal is emitted when the \a item is collapsed. - - \sa expanded(), setExpanded() -*/ - -/*! - \fn void QtButtonPropertyBrowser::expanded(QtBrowserItem *item) - - This signal is emitted when the \a item is expanded. - - \sa collapsed(), setExpanded() -*/ - -/*! - Creates a property browser with the given \a parent. -*/ -QtButtonPropertyBrowser::QtButtonPropertyBrowser(QWidget *parent) - : QtAbstractPropertyBrowser(parent) -{ - d_ptr = new QtButtonPropertyBrowserPrivate; - d_ptr->q_ptr = this; - - d_ptr->init(this); -} - -/*! - Destroys this property browser. - - Note that the properties that were inserted into this browser are - \e not destroyed since they may still be used in other - browsers. The properties are owned by the manager that created - them. - - \sa QtProperty, QtAbstractPropertyManager -*/ -QtButtonPropertyBrowser::~QtButtonPropertyBrowser() -{ - const QMap::ConstIterator icend = d_ptr->m_itemToIndex.constEnd(); - for (QMap::ConstIterator it = d_ptr->m_itemToIndex.constBegin(); it != icend; ++it) - delete it.key(); - delete d_ptr; -} - -/*! - \reimp -*/ -void QtButtonPropertyBrowser::itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem) -{ - d_ptr->propertyInserted(item, afterItem); -} - -/*! - \reimp -*/ -void QtButtonPropertyBrowser::itemRemoved(QtBrowserItem *item) -{ - d_ptr->propertyRemoved(item); -} - -/*! - \reimp -*/ -void QtButtonPropertyBrowser::itemChanged(QtBrowserItem *item) -{ - d_ptr->propertyChanged(item); -} - -/*! - Sets the \a item to either collapse or expanded, depending on the value of \a expanded. - - \sa isExpanded(), expanded(), collapsed() -*/ - -void QtButtonPropertyBrowser::setExpanded(QtBrowserItem *item, bool expanded) -{ - QtButtonPropertyBrowserPrivate::WidgetItem *itm = d_ptr->m_indexToItem.value(item); - if (itm) - d_ptr->setExpanded(itm, expanded); -} - -/*! - Returns true if the \a item is expanded; otherwise returns false. - - \sa setExpanded() -*/ - -bool QtButtonPropertyBrowser::isExpanded(QtBrowserItem *item) const -{ - QtButtonPropertyBrowserPrivate::WidgetItem *itm = d_ptr->m_indexToItem.value(item); - if (itm) - return itm->expanded; - return false; -} - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#include "moc_qtbuttonpropertybrowser.cpp" diff --git a/src/qtpropertybrowser/src/qtbuttonpropertybrowser.h b/src/qtpropertybrowser/src/qtbuttonpropertybrowser.h deleted file mode 100644 index bdab1485ca..0000000000 --- a/src/qtpropertybrowser/src/qtbuttonpropertybrowser.h +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QTBUTTONPROPERTYBROWSER_H -#define QTBUTTONPROPERTYBROWSER_H - -#include "qtpropertybrowser.h" - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QtButtonPropertyBrowserPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtButtonPropertyBrowser : public QtAbstractPropertyBrowser -{ - Q_OBJECT -public: - - QtButtonPropertyBrowser(QWidget *parent = 0); - ~QtButtonPropertyBrowser(); - - void setExpanded(QtBrowserItem *item, bool expanded); - bool isExpanded(QtBrowserItem *item) const; - -Q_SIGNALS: - - void collapsed(QtBrowserItem *item); - void expanded(QtBrowserItem *item); - -protected: - virtual void itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem); - virtual void itemRemoved(QtBrowserItem *item); - virtual void itemChanged(QtBrowserItem *item); - -private: - - QtButtonPropertyBrowserPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtButtonPropertyBrowser) - Q_DISABLE_COPY(QtButtonPropertyBrowser) - Q_PRIVATE_SLOT(d_func(), void slotUpdate()) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed()) - Q_PRIVATE_SLOT(d_func(), void slotToggled(bool)) - -}; - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#endif diff --git a/src/qtpropertybrowser/src/qteditorfactory.cpp b/src/qtpropertybrowser/src/qteditorfactory.cpp deleted file mode 100644 index 284a38dde4..0000000000 --- a/src/qtpropertybrowser/src/qteditorfactory.cpp +++ /dev/null @@ -1,2734 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qteditorfactory.h" -#include "qtpropertybrowserutils_p.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(Q_CC_MSVC) -# pragma warning(disable: 4786) /* MS VS 6: truncating debug info after 255 characters */ -#endif - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -// Set a hard coded left margin to account for the indentation -// of the tree view icon when switching to an editor - -static inline void setupTreeViewEditorMargin(QLayout *lt) -{ - enum { DecorationMargin = 4 }; - if (QApplication::layoutDirection() == Qt::LeftToRight) - lt->setContentsMargins(DecorationMargin, 0, 0, 0); - else - lt->setContentsMargins(0, 0, DecorationMargin, 0); -} - -// ---------- EditorFactoryPrivate : -// Base class for editor factory private classes. Manages mapping of properties to editors and vice versa. - -template -class EditorFactoryPrivate -{ -public: - - typedef QList EditorList; - typedef QMap PropertyToEditorListMap; - typedef QMap EditorToPropertyMap; - - Editor *createEditor(QtProperty *property, QWidget *parent); - void initializeEditor(QtProperty *property, Editor *e); - void slotEditorDestroyed(QObject *object); - - PropertyToEditorListMap m_createdEditors; - EditorToPropertyMap m_editorToProperty; -}; - -template -Editor *EditorFactoryPrivate::createEditor(QtProperty *property, QWidget *parent) -{ - Editor *editor = new Editor(parent); - initializeEditor(property, editor); - return editor; -} - -template -void EditorFactoryPrivate::initializeEditor(QtProperty *property, Editor *editor) -{ - typename PropertyToEditorListMap::iterator it = m_createdEditors.find(property); - if (it == m_createdEditors.end()) - it = m_createdEditors.insert(property, EditorList()); - it.value().append(editor); - m_editorToProperty.insert(editor, property); -} - -template -void EditorFactoryPrivate::slotEditorDestroyed(QObject *object) -{ - const typename EditorToPropertyMap::iterator ecend = m_editorToProperty.end(); - for (typename EditorToPropertyMap::iterator itEditor = m_editorToProperty.begin(); itEditor != ecend; ++itEditor) { - if (itEditor.key() == object) { - Editor *editor = itEditor.key(); - QtProperty *property = itEditor.value(); - const typename PropertyToEditorListMap::iterator pit = m_createdEditors.find(property); - if (pit != m_createdEditors.end()) { - pit.value().removeAll(editor); - if (pit.value().empty()) - m_createdEditors.erase(pit); - } - m_editorToProperty.erase(itEditor); - return; - } - } -} - -// ------------ QtSpinBoxFactory - -class QtSpinBoxFactoryPrivate : public EditorFactoryPrivate -{ - QtSpinBoxFactory *q_ptr; - Q_DECLARE_PUBLIC(QtSpinBoxFactory) -public: - - void slotPropertyChanged(QtProperty *property, int value); - void slotRangeChanged(QtProperty *property, int min, int max); - void slotSingleStepChanged(QtProperty *property, int step); - void slotReadOnlyChanged(QtProperty *property, bool readOnly); - void slotSetValue(int value); -}; - -void QtSpinBoxFactoryPrivate::slotPropertyChanged(QtProperty *property, int value) -{ - if (!m_createdEditors.contains(property)) - return; - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QSpinBox *editor = itEditor.next(); - if (editor->value() != value) { - editor->blockSignals(true); - editor->setValue(value); - editor->blockSignals(false); - } - } -} - -void QtSpinBoxFactoryPrivate::slotRangeChanged(QtProperty *property, int min, int max) -{ - if (!m_createdEditors.contains(property)) - return; - - QtIntPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QSpinBox *editor = itEditor.next(); - editor->blockSignals(true); - editor->setRange(min, max); - editor->setValue(manager->value(property)); - editor->blockSignals(false); - } -} - -void QtSpinBoxFactoryPrivate::slotSingleStepChanged(QtProperty *property, int step) -{ - if (!m_createdEditors.contains(property)) - return; - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QSpinBox *editor = itEditor.next(); - editor->blockSignals(true); - editor->setSingleStep(step); - editor->blockSignals(false); - } -} - -void QtSpinBoxFactoryPrivate::slotReadOnlyChanged( QtProperty *property, bool readOnly) -{ - if (!m_createdEditors.contains(property)) - return; - - QtIntPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QSpinBox *editor = itEditor.next(); - editor->blockSignals(true); - editor->setReadOnly(readOnly); - editor->blockSignals(false); - } -} - -void QtSpinBoxFactoryPrivate::slotSetValue(int value) -{ - QObject *object = q_ptr->sender(); - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) { - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtIntPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } - } -} - -/*! - \class QtSpinBoxFactory - - \brief The QtSpinBoxFactory class provides QSpinBox widgets for - properties created by QtIntPropertyManager objects. - - \sa QtAbstractEditorFactory, QtIntPropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtSpinBoxFactory::QtSpinBoxFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtSpinBoxFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtSpinBoxFactory::~QtSpinBoxFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtSpinBoxFactory::connectPropertyManager(QtIntPropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotPropertyChanged(QtProperty *, int))); - connect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)), - this, SLOT(slotRangeChanged(QtProperty *, int, int))); - connect(manager, SIGNAL(singleStepChanged(QtProperty *, int)), - this, SLOT(slotSingleStepChanged(QtProperty *, int))); - connect(manager, SIGNAL(readOnlyChanged(QtProperty *, bool)), - this, SLOT(slotReadOnlyChanged(QtProperty *, bool))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtSpinBoxFactory::createEditor(QtIntPropertyManager *manager, QtProperty *property, - QWidget *parent) -{ - QSpinBox *editor = d_ptr->createEditor(property, parent); - editor->setSingleStep(manager->singleStep(property)); - editor->setRange(manager->minimum(property), manager->maximum(property)); - editor->setValue(manager->value(property)); - editor->setKeyboardTracking(false); - editor->setReadOnly(manager->isReadOnly(property)); - - connect(editor, SIGNAL(valueChanged(int)), this, SLOT(slotSetValue(int))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtSpinBoxFactory::disconnectPropertyManager(QtIntPropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotPropertyChanged(QtProperty *, int))); - disconnect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)), - this, SLOT(slotRangeChanged(QtProperty *, int, int))); - disconnect(manager, SIGNAL(singleStepChanged(QtProperty *, int)), - this, SLOT(slotSingleStepChanged(QtProperty *, int))); - disconnect(manager, SIGNAL(readOnlyChanged(QtProperty *, bool)), - this, SLOT(slotReadOnlyChanged(QtProperty *, bool))); -} - -// QtSliderFactory - -class QtSliderFactoryPrivate : public EditorFactoryPrivate -{ - QtSliderFactory *q_ptr; - Q_DECLARE_PUBLIC(QtSliderFactory) -public: - void slotPropertyChanged(QtProperty *property, int value); - void slotRangeChanged(QtProperty *property, int min, int max); - void slotSingleStepChanged(QtProperty *property, int step); - void slotSetValue(int value); -}; - -void QtSliderFactoryPrivate::slotPropertyChanged(QtProperty *property, int value) -{ - if (!m_createdEditors.contains(property)) - return; - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QSlider *editor = itEditor.next(); - editor->blockSignals(true); - editor->setValue(value); - editor->blockSignals(false); - } -} - -void QtSliderFactoryPrivate::slotRangeChanged(QtProperty *property, int min, int max) -{ - if (!m_createdEditors.contains(property)) - return; - - QtIntPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QSlider *editor = itEditor.next(); - editor->blockSignals(true); - editor->setRange(min, max); - editor->setValue(manager->value(property)); - editor->blockSignals(false); - } -} - -void QtSliderFactoryPrivate::slotSingleStepChanged(QtProperty *property, int step) -{ - if (!m_createdEditors.contains(property)) - return; - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QSlider *editor = itEditor.next(); - editor->blockSignals(true); - editor->setSingleStep(step); - editor->blockSignals(false); - } -} - -void QtSliderFactoryPrivate::slotSetValue(int value) -{ - QObject *object = q_ptr->sender(); - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor ) { - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtIntPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } - } -} - -/*! - \class QtSliderFactory - - \brief The QtSliderFactory class provides QSlider widgets for - properties created by QtIntPropertyManager objects. - - \sa QtAbstractEditorFactory, QtIntPropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtSliderFactory::QtSliderFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtSliderFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtSliderFactory::~QtSliderFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtSliderFactory::connectPropertyManager(QtIntPropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotPropertyChanged(QtProperty *, int))); - connect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)), - this, SLOT(slotRangeChanged(QtProperty *, int, int))); - connect(manager, SIGNAL(singleStepChanged(QtProperty *, int)), - this, SLOT(slotSingleStepChanged(QtProperty *, int))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtSliderFactory::createEditor(QtIntPropertyManager *manager, QtProperty *property, - QWidget *parent) -{ - QSlider *editor = new QSlider(Qt::Horizontal, parent); - d_ptr->initializeEditor(property, editor); - editor->setSingleStep(manager->singleStep(property)); - editor->setRange(manager->minimum(property), manager->maximum(property)); - editor->setValue(manager->value(property)); - - connect(editor, SIGNAL(valueChanged(int)), this, SLOT(slotSetValue(int))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtSliderFactory::disconnectPropertyManager(QtIntPropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotPropertyChanged(QtProperty *, int))); - disconnect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)), - this, SLOT(slotRangeChanged(QtProperty *, int, int))); - disconnect(manager, SIGNAL(singleStepChanged(QtProperty *, int)), - this, SLOT(slotSingleStepChanged(QtProperty *, int))); -} - -// QtSliderFactory - -class QtScrollBarFactoryPrivate : public EditorFactoryPrivate -{ - QtScrollBarFactory *q_ptr; - Q_DECLARE_PUBLIC(QtScrollBarFactory) -public: - void slotPropertyChanged(QtProperty *property, int value); - void slotRangeChanged(QtProperty *property, int min, int max); - void slotSingleStepChanged(QtProperty *property, int step); - void slotSetValue(int value); -}; - -void QtScrollBarFactoryPrivate::slotPropertyChanged(QtProperty *property, int value) -{ - if (!m_createdEditors.contains(property)) - return; - - QListIterator itEditor( m_createdEditors[property]); - while (itEditor.hasNext()) { - QScrollBar *editor = itEditor.next(); - editor->blockSignals(true); - editor->setValue(value); - editor->blockSignals(false); - } -} - -void QtScrollBarFactoryPrivate::slotRangeChanged(QtProperty *property, int min, int max) -{ - if (!m_createdEditors.contains(property)) - return; - - QtIntPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QListIterator itEditor( m_createdEditors[property]); - while (itEditor.hasNext()) { - QScrollBar *editor = itEditor.next(); - editor->blockSignals(true); - editor->setRange(min, max); - editor->setValue(manager->value(property)); - editor->blockSignals(false); - } -} - -void QtScrollBarFactoryPrivate::slotSingleStepChanged(QtProperty *property, int step) -{ - if (!m_createdEditors.contains(property)) - return; - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QScrollBar *editor = itEditor.next(); - editor->blockSignals(true); - editor->setSingleStep(step); - editor->blockSignals(false); - } -} - -void QtScrollBarFactoryPrivate::slotSetValue(int value) -{ - QObject *object = q_ptr->sender(); - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtIntPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - -/*! - \class QtScrollBarFactory - - \brief The QtScrollBarFactory class provides QScrollBar widgets for - properties created by QtIntPropertyManager objects. - - \sa QtAbstractEditorFactory, QtIntPropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtScrollBarFactory::QtScrollBarFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtScrollBarFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtScrollBarFactory::~QtScrollBarFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtScrollBarFactory::connectPropertyManager(QtIntPropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotPropertyChanged(QtProperty *, int))); - connect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)), - this, SLOT(slotRangeChanged(QtProperty *, int, int))); - connect(manager, SIGNAL(singleStepChanged(QtProperty *, int)), - this, SLOT(slotSingleStepChanged(QtProperty *, int))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtScrollBarFactory::createEditor(QtIntPropertyManager *manager, QtProperty *property, - QWidget *parent) -{ - QScrollBar *editor = new QScrollBar(Qt::Horizontal, parent); - d_ptr->initializeEditor(property, editor); - editor->setSingleStep(manager->singleStep(property)); - editor->setRange(manager->minimum(property), manager->maximum(property)); - editor->setValue(manager->value(property)); - connect(editor, SIGNAL(valueChanged(int)), this, SLOT(slotSetValue(int))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtScrollBarFactory::disconnectPropertyManager(QtIntPropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotPropertyChanged(QtProperty *, int))); - disconnect(manager, SIGNAL(rangeChanged(QtProperty *, int, int)), - this, SLOT(slotRangeChanged(QtProperty *, int, int))); - disconnect(manager, SIGNAL(singleStepChanged(QtProperty *, int)), - this, SLOT(slotSingleStepChanged(QtProperty *, int))); -} - -// QtCheckBoxFactory - -class QtCheckBoxFactoryPrivate : public EditorFactoryPrivate -{ - QtCheckBoxFactory *q_ptr; - Q_DECLARE_PUBLIC(QtCheckBoxFactory) -public: - void slotPropertyChanged(QtProperty *property, bool value); - void slotTextVisibleChanged(QtProperty *property, bool textVisible); - void slotSetValue(bool value); -}; - -void QtCheckBoxFactoryPrivate::slotPropertyChanged(QtProperty *property, bool value) -{ - if (!m_createdEditors.contains(property)) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QtBoolEdit *editor = itEditor.next(); - editor->blockCheckBoxSignals(true); - editor->setChecked(value); - editor->blockCheckBoxSignals(false); - } -} - -void QtCheckBoxFactoryPrivate::slotTextVisibleChanged(QtProperty *property, bool textVisible) -{ - if (!m_createdEditors.contains(property)) - return; - - QtBoolPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QtBoolEdit *editor = itEditor.next(); - editor->setTextVisible(textVisible); - } -} - -void QtCheckBoxFactoryPrivate::slotSetValue(bool value) -{ - QObject *object = q_ptr->sender(); - - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtBoolPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - -/*! - \class QtCheckBoxFactory - - \brief The QtCheckBoxFactory class provides QCheckBox widgets for - properties created by QtBoolPropertyManager objects. - - \sa QtAbstractEditorFactory, QtBoolPropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtCheckBoxFactory::QtCheckBoxFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtCheckBoxFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtCheckBoxFactory::~QtCheckBoxFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtCheckBoxFactory::connectPropertyManager(QtBoolPropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, bool)), - this, SLOT(slotPropertyChanged(QtProperty *, bool))); - connect(manager, SIGNAL(textVisibleChanged(QtProperty *, bool)), - this, SLOT(slotTextVisibleChanged(QtProperty *, bool))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtCheckBoxFactory::createEditor(QtBoolPropertyManager *manager, QtProperty *property, - QWidget *parent) -{ - QtBoolEdit *editor = d_ptr->createEditor(property, parent); - editor->setChecked(manager->value(property)); - editor->setTextVisible(manager->textVisible(property)); - - connect(editor, SIGNAL(toggled(bool)), this, SLOT(slotSetValue(bool))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtCheckBoxFactory::disconnectPropertyManager(QtBoolPropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, bool)), - this, SLOT(slotPropertyChanged(QtProperty *, bool))); - disconnect(manager, SIGNAL(textVisibleChanged(QtProperty *, bool)), - this, SLOT(slotTextVisibleChanged(QtProperty *, bool))); -} - -// QtDoubleSpinBoxFactory - -class DoubleSpinBoxAnyPrecision : public QDoubleSpinBox -{ - Q_OBJECT - -public: - explicit DoubleSpinBoxAnyPrecision(QWidget *parent = nullptr) - : QDoubleSpinBox(parent) - {} - - QString textFromValue(double val) const override - { - QString text = QDoubleSpinBox::textFromValue(val); - - // remove redundant trailing 0's in case of high precision - if (decimals() > 3) - return removeRedundantTrialingZeros(text); - - return text; - } -}; - -class QtDoubleSpinBoxFactoryPrivate : public EditorFactoryPrivate -{ - QtDoubleSpinBoxFactory *q_ptr; - Q_DECLARE_PUBLIC(QtDoubleSpinBoxFactory) -public: - - void slotPropertyChanged(QtProperty *property, double value); - void slotRangeChanged(QtProperty *property, double min, double max); - void slotSingleStepChanged(QtProperty *property, double step); - void slotDecimalsChanged(QtProperty *property, int prec); - void slotReadOnlyChanged(QtProperty *property, bool readOnly); - void slotSetValue(double value); -}; - -void QtDoubleSpinBoxFactoryPrivate::slotPropertyChanged(QtProperty *property, double value) -{ - const auto editors = m_createdEditors[property]; - for (auto editor : editors) { - if (editor->value() != value) { - editor->blockSignals(true); - editor->setValue(value); - editor->blockSignals(false); - } - } -} - -void QtDoubleSpinBoxFactoryPrivate::slotRangeChanged(QtProperty *property, - double min, double max) -{ - if (!m_createdEditors.contains(property)) - return; - - QtDoublePropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - const auto editors = m_createdEditors[property]; - for (auto editor : editors) { - editor->blockSignals(true); - editor->setRange(min, max); - editor->setValue(manager->value(property)); - editor->blockSignals(false); - } -} - -void QtDoubleSpinBoxFactoryPrivate::slotSingleStepChanged(QtProperty *property, double step) -{ - if (!m_createdEditors.contains(property)) - return; - - QtDoublePropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - const auto editors = m_createdEditors[property]; - for (auto editor : editors) { - editor->blockSignals(true); - editor->setSingleStep(step); - editor->blockSignals(false); - } -} - -void QtDoubleSpinBoxFactoryPrivate::slotReadOnlyChanged( QtProperty *property, bool readOnly) -{ - if (!m_createdEditors.contains(property)) - return; - - QtDoublePropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - const auto editors = m_createdEditors[property]; - for (auto editor : editors) { - editor->blockSignals(true); - editor->setReadOnly(readOnly); - editor->blockSignals(false); - } -} - -void QtDoubleSpinBoxFactoryPrivate::slotDecimalsChanged(QtProperty *property, int prec) -{ - if (!m_createdEditors.contains(property)) - return; - - QtDoublePropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - const auto editors = m_createdEditors[property]; - for (auto editor : editors) { - editor->blockSignals(true); - editor->setDecimals(prec); - editor->setValue(manager->value(property)); - editor->blockSignals(false); - } -} - -void QtDoubleSpinBoxFactoryPrivate::slotSetValue(double value) -{ - QObject *object = q_ptr->sender(); - const auto itcend = m_editorToProperty.constEnd(); - for (auto itEditor = m_editorToProperty.constBegin(); itEditor != itcend; ++itEditor) { - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtDoublePropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } - } -} - -/*! \class QtDoubleSpinBoxFactory - - \brief The QtDoubleSpinBoxFactory class provides QDoubleSpinBox - widgets for properties created by QtDoublePropertyManager objects. - - \sa QtAbstractEditorFactory, QtDoublePropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtDoubleSpinBoxFactory::QtDoubleSpinBoxFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtDoubleSpinBoxFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtDoubleSpinBoxFactory::~QtDoubleSpinBoxFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtDoubleSpinBoxFactory::connectPropertyManager(QtDoublePropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, double)), - this, SLOT(slotPropertyChanged(QtProperty *, double))); - connect(manager, SIGNAL(rangeChanged(QtProperty *, double, double)), - this, SLOT(slotRangeChanged(QtProperty *, double, double))); - connect(manager, SIGNAL(singleStepChanged(QtProperty *, double)), - this, SLOT(slotSingleStepChanged(QtProperty *, double))); - connect(manager, SIGNAL(decimalsChanged(QtProperty *, int)), - this, SLOT(slotDecimalsChanged(QtProperty *, int))); - connect(manager, SIGNAL(readOnlyChanged(QtProperty *, bool)), - this, SLOT(slotReadOnlyChanged(QtProperty *, bool))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtDoubleSpinBoxFactory::createEditor(QtDoublePropertyManager *manager, - QtProperty *property, QWidget *parent) -{ - QDoubleSpinBox *editor = d_ptr->createEditor(property, parent); - editor->setSingleStep(manager->singleStep(property)); - editor->setDecimals(manager->decimals(property)); - editor->setRange(manager->minimum(property), manager->maximum(property)); - editor->setValue(manager->value(property)); - editor->setKeyboardTracking(false); - editor->setReadOnly(manager->isReadOnly(property)); - - connect(editor, SIGNAL(valueChanged(double)), this, SLOT(slotSetValue(double))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtDoubleSpinBoxFactory::disconnectPropertyManager(QtDoublePropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, double)), - this, SLOT(slotPropertyChanged(QtProperty *, double))); - disconnect(manager, SIGNAL(rangeChanged(QtProperty *, double, double)), - this, SLOT(slotRangeChanged(QtProperty *, double, double))); - disconnect(manager, SIGNAL(singleStepChanged(QtProperty *, double)), - this, SLOT(slotSingleStepChanged(QtProperty *, double))); - disconnect(manager, SIGNAL(decimalsChanged(QtProperty *, int)), - this, SLOT(slotDecimalsChanged(QtProperty *, int))); - disconnect(manager, SIGNAL(readOnlyChanged(QtProperty *, bool)), - this, SLOT(slotReadOnlyChanged(QtProperty *, bool))); -} - -// QtLineEditFactory - -class QtLineEditFactoryPrivate : public EditorFactoryPrivate -{ - QtLineEditFactory *q_ptr; - Q_DECLARE_PUBLIC(QtLineEditFactory) -public: - - void slotPropertyChanged(QtProperty *property, const QString &value); - void slotRegExpChanged(QtProperty *property, const QRegularExpression ®Exp); - void slotSetValue(const QString &value); - void slotEchoModeChanged(QtProperty *, int); - void slotReadOnlyChanged(QtProperty *, bool); -}; - -void QtLineEditFactoryPrivate::slotPropertyChanged(QtProperty *property, - const QString &value) -{ - if (!m_createdEditors.contains(property)) - return; - - QListIterator itEditor( m_createdEditors[property]); - while (itEditor.hasNext()) { - QLineEdit *editor = itEditor.next(); - if (editor->text() != value) { - editor->blockSignals(true); - editor->setText(value); - editor->blockSignals(false); - } - } -} - -void QtLineEditFactoryPrivate::slotRegExpChanged(QtProperty *property, - const QRegularExpression ®Exp) -{ - if (!m_createdEditors.contains(property)) - return; - - QtStringPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QLineEdit *editor = itEditor.next(); - editor->blockSignals(true); - const QValidator *oldValidator = editor->validator(); - QValidator *newValidator = 0; - if (regExp.isValid()) { - newValidator = new QRegularExpressionValidator(regExp, editor); - } - editor->setValidator(newValidator); - if (oldValidator) - delete oldValidator; - editor->blockSignals(false); - } -} - -void QtLineEditFactoryPrivate::slotEchoModeChanged(QtProperty *property, int echoMode) -{ - if (!m_createdEditors.contains(property)) - return; - - QtStringPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QLineEdit *editor = itEditor.next(); - editor->blockSignals(true); - editor->setEchoMode((EchoMode)echoMode); - editor->blockSignals(false); - } -} - -void QtLineEditFactoryPrivate::slotReadOnlyChanged( QtProperty *property, bool readOnly) -{ - if (!m_createdEditors.contains(property)) - return; - - QtStringPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QLineEdit *editor = itEditor.next(); - editor->blockSignals(true); - editor->setReadOnly(readOnly); - editor->blockSignals(false); - } -} - -void QtLineEditFactoryPrivate::slotSetValue(const QString &value) -{ - QObject *object = q_ptr->sender(); - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtStringPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - - - -/*! - \class QtLineEditFactory - - \brief The QtLineEditFactory class provides QLineEdit widgets for - properties created by QtStringPropertyManager objects. - - \sa QtAbstractEditorFactory, QtStringPropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtLineEditFactory::QtLineEditFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtLineEditFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtLineEditFactory::~QtLineEditFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtLineEditFactory::connectPropertyManager(QtStringPropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, const QString &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QString &))); - connect(manager, SIGNAL(regExpChanged(QtProperty *, const QRegularExpression &)), - this, SLOT(slotRegExpChanged(QtProperty *, const QRegularExpression &))); - connect(manager, SIGNAL(echoModeChanged(QtProperty*, int)), - this, SLOT(slotEchoModeChanged(QtProperty *, int))); - connect(manager, SIGNAL(readOnlyChanged(QtProperty*, bool)), - this, SLOT(slotReadOnlyChanged(QtProperty *, bool))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtLineEditFactory::createEditor(QtStringPropertyManager *manager, - QtProperty *property, QWidget *parent) -{ - - QLineEdit *editor = d_ptr->createEditor(property, parent); - editor->setEchoMode((EchoMode)manager->echoMode(property)); - editor->setReadOnly(manager->isReadOnly(property)); - QRegularExpression regExp = manager->regExp(property); - if (regExp.isValid()) { - QValidator *validator = new QRegularExpressionValidator(regExp, editor); - editor->setValidator(validator); - } - editor->setText(manager->value(property)); - - connect(editor, SIGNAL(textChanged(const QString &)), - this, SLOT(slotSetValue(const QString &))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtLineEditFactory::disconnectPropertyManager(QtStringPropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QString &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QString &))); - disconnect(manager, SIGNAL(regExpChanged(QtProperty *, const QRegularExpression &)), - this, SLOT(slotRegExpChanged(QtProperty *, const QRegularExpression &))); - disconnect(manager, SIGNAL(echoModeChanged(QtProperty*,int)), - this, SLOT(slotEchoModeChanged(QtProperty *, int))); - disconnect(manager, SIGNAL(readOnlyChanged(QtProperty*, bool)), - this, SLOT(slotReadOnlyChanged(QtProperty *, bool))); - -} - -// QtDateEditFactory - -class QtDateEditFactoryPrivate : public EditorFactoryPrivate -{ - QtDateEditFactory *q_ptr; - Q_DECLARE_PUBLIC(QtDateEditFactory) -public: - - void slotPropertyChanged(QtProperty *property, const QDate &value); - void slotRangeChanged(QtProperty *property, const QDate &min, const QDate &max); - void slotSetValue(const QDate &value); -}; - -void QtDateEditFactoryPrivate::slotPropertyChanged(QtProperty *property, const QDate &value) -{ - if (!m_createdEditors.contains(property)) - return; - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QDateEdit *editor = itEditor.next(); - editor->blockSignals(true); - editor->setDate(value); - editor->blockSignals(false); - } -} - -void QtDateEditFactoryPrivate::slotRangeChanged(QtProperty *property, - const QDate &min, const QDate &max) -{ - if (!m_createdEditors.contains(property)) - return; - - QtDatePropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QDateEdit *editor = itEditor.next(); - editor->blockSignals(true); - editor->setDateRange(min, max); - editor->setDate(manager->value(property)); - editor->blockSignals(false); - } -} - -void QtDateEditFactoryPrivate::slotSetValue(const QDate &value) -{ - QObject *object = q_ptr->sender(); - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtDatePropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - -/*! - \class QtDateEditFactory - - \brief The QtDateEditFactory class provides QDateEdit widgets for - properties created by QtDatePropertyManager objects. - - \sa QtAbstractEditorFactory, QtDatePropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtDateEditFactory::QtDateEditFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtDateEditFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtDateEditFactory::~QtDateEditFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtDateEditFactory::connectPropertyManager(QtDatePropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, const QDate &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QDate &))); - connect(manager, SIGNAL(rangeChanged(QtProperty *, const QDate &, const QDate &)), - this, SLOT(slotRangeChanged(QtProperty *, const QDate &, const QDate &))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtDateEditFactory::createEditor(QtDatePropertyManager *manager, QtProperty *property, - QWidget *parent) -{ - QDateEdit *editor = d_ptr->createEditor(property, parent); - editor->setCalendarPopup(true); - editor->setDateRange(manager->minimum(property), manager->maximum(property)); - editor->setDate(manager->value(property)); - - connect(editor, SIGNAL(dateChanged(const QDate &)), - this, SLOT(slotSetValue(const QDate &))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtDateEditFactory::disconnectPropertyManager(QtDatePropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QDate &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QDate &))); - disconnect(manager, SIGNAL(rangeChanged(QtProperty *, const QDate &, const QDate &)), - this, SLOT(slotRangeChanged(QtProperty *, const QDate &, const QDate &))); -} - -// QtTimeEditFactory - -class QtTimeEditFactoryPrivate : public EditorFactoryPrivate -{ - QtTimeEditFactory *q_ptr; - Q_DECLARE_PUBLIC(QtTimeEditFactory) -public: - - void slotPropertyChanged(QtProperty *property, const QTime &value); - void slotSetValue(const QTime &value); -}; - -void QtTimeEditFactoryPrivate::slotPropertyChanged(QtProperty *property, const QTime &value) -{ - if (!m_createdEditors.contains(property)) - return; - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QTimeEdit *editor = itEditor.next(); - editor->blockSignals(true); - editor->setTime(value); - editor->blockSignals(false); - } -} - -void QtTimeEditFactoryPrivate::slotSetValue(const QTime &value) -{ - QObject *object = q_ptr->sender(); - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtTimePropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - -/*! - \class QtTimeEditFactory - - \brief The QtTimeEditFactory class provides QTimeEdit widgets for - properties created by QtTimePropertyManager objects. - - \sa QtAbstractEditorFactory, QtTimePropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtTimeEditFactory::QtTimeEditFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtTimeEditFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtTimeEditFactory::~QtTimeEditFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtTimeEditFactory::connectPropertyManager(QtTimePropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, const QTime &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QTime &))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtTimeEditFactory::createEditor(QtTimePropertyManager *manager, QtProperty *property, - QWidget *parent) -{ - QTimeEdit *editor = d_ptr->createEditor(property, parent); - editor->setTime(manager->value(property)); - - connect(editor, SIGNAL(timeChanged(const QTime &)), - this, SLOT(slotSetValue(const QTime &))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtTimeEditFactory::disconnectPropertyManager(QtTimePropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QTime &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QTime &))); -} - -// QtDateTimeEditFactory - -class QtDateTimeEditFactoryPrivate : public EditorFactoryPrivate -{ - QtDateTimeEditFactory *q_ptr; - Q_DECLARE_PUBLIC(QtDateTimeEditFactory) -public: - - void slotPropertyChanged(QtProperty *property, const QDateTime &value); - void slotSetValue(const QDateTime &value); - -}; - -void QtDateTimeEditFactoryPrivate::slotPropertyChanged(QtProperty *property, - const QDateTime &value) -{ - if (!m_createdEditors.contains(property)) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QDateTimeEdit *editor = itEditor.next(); - editor->blockSignals(true); - editor->setDateTime(value); - editor->blockSignals(false); - } -} - -void QtDateTimeEditFactoryPrivate::slotSetValue(const QDateTime &value) -{ - QObject *object = q_ptr->sender(); - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtDateTimePropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - -/*! - \class QtDateTimeEditFactory - - \brief The QtDateTimeEditFactory class provides QDateTimeEdit - widgets for properties created by QtDateTimePropertyManager objects. - - \sa QtAbstractEditorFactory, QtDateTimePropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtDateTimeEditFactory::QtDateTimeEditFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtDateTimeEditFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtDateTimeEditFactory::~QtDateTimeEditFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtDateTimeEditFactory::connectPropertyManager(QtDateTimePropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, const QDateTime &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QDateTime &))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtDateTimeEditFactory::createEditor(QtDateTimePropertyManager *manager, - QtProperty *property, QWidget *parent) -{ - QDateTimeEdit *editor = d_ptr->createEditor(property, parent); - editor->setDateTime(manager->value(property)); - - connect(editor, SIGNAL(dateTimeChanged(const QDateTime &)), - this, SLOT(slotSetValue(const QDateTime &))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtDateTimeEditFactory::disconnectPropertyManager(QtDateTimePropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QDateTime &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QDateTime &))); -} - -// QtKeySequenceEditorFactory - -class QtKeySequenceEditorFactoryPrivate : public EditorFactoryPrivate -{ - QtKeySequenceEditorFactory *q_ptr; - Q_DECLARE_PUBLIC(QtKeySequenceEditorFactory) -public: - - void slotPropertyChanged(QtProperty *property, const QKeySequence &value); - void slotSetValue(const QKeySequence &value); -}; - -void QtKeySequenceEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, - const QKeySequence &value) -{ - if (!m_createdEditors.contains(property)) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QKeySequenceEdit *editor = itEditor.next(); - editor->blockSignals(true); - editor->setKeySequence(value); - editor->blockSignals(false); - } -} - -void QtKeySequenceEditorFactoryPrivate::slotSetValue(const QKeySequence &value) -{ - QObject *object = q_ptr->sender(); - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtKeySequencePropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - -/*! - \class QtKeySequenceEditorFactory - - \brief The QtKeySequenceEditorFactory class provides editor - widgets for properties created by QtKeySequencePropertyManager objects. - - \sa QtAbstractEditorFactory -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtKeySequenceEditorFactory::QtKeySequenceEditorFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtKeySequenceEditorFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtKeySequenceEditorFactory::~QtKeySequenceEditorFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtKeySequenceEditorFactory::connectPropertyManager(QtKeySequencePropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, const QKeySequence &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QKeySequence &))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtKeySequenceEditorFactory::createEditor(QtKeySequencePropertyManager *manager, - QtProperty *property, QWidget *parent) -{ - QKeySequenceEdit *editor = d_ptr->createEditor(property, parent); - editor->setKeySequence(manager->value(property)); - - connect(editor, SIGNAL(keySequenceChanged(const QKeySequence &)), - this, SLOT(slotSetValue(const QKeySequence &))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtKeySequenceEditorFactory::disconnectPropertyManager(QtKeySequencePropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QKeySequence &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QKeySequence &))); -} - -// QtCharEdit - -class QtCharEdit : public QWidget -{ - Q_OBJECT -public: - explicit QtCharEdit(QWidget *parent = 0); - - QChar value() const; - bool eventFilter(QObject *o, QEvent *e); -public Q_SLOTS: - void setValue(const QChar &value); -Q_SIGNALS: - void valueChanged(const QChar &value); -protected: - void focusInEvent(QFocusEvent *e); - void focusOutEvent(QFocusEvent *e); - void keyPressEvent(QKeyEvent *e); - void keyReleaseEvent(QKeyEvent *e); - void paintEvent(QPaintEvent *); - bool event(QEvent *e); -private slots: - void slotClearChar(); -private: - void handleKeyEvent(QKeyEvent *e); - - QChar m_value; - QLineEdit *m_lineEdit; -}; - -QtCharEdit::QtCharEdit(QWidget *parent) - : QWidget(parent), m_lineEdit(new QLineEdit(this)) -{ - QHBoxLayout *layout = new QHBoxLayout(this); - layout->addWidget(m_lineEdit); - layout->setContentsMargins(0, 0, 0, 0); - m_lineEdit->installEventFilter(this); - m_lineEdit->setReadOnly(true); - m_lineEdit->setFocusProxy(this); - setFocusPolicy(m_lineEdit->focusPolicy()); - setAttribute(Qt::WA_InputMethodEnabled); -} - -bool QtCharEdit::eventFilter(QObject *o, QEvent *e) -{ - if (o == m_lineEdit && e->type() == QEvent::ContextMenu) { - QContextMenuEvent *c = static_cast(e); - QMenu *menu = m_lineEdit->createStandardContextMenu(); - QList actions = menu->actions(); - QListIterator itAction(actions); - while (itAction.hasNext()) { - QAction *action = itAction.next(); - action->setShortcut(QKeySequence()); - QString actionString = action->text(); - const int pos = actionString.lastIndexOf(QLatin1Char('\t')); - if (pos > 0) - actionString = actionString.remove(pos, actionString.length() - pos); - action->setText(actionString); - } - QAction *actionBefore = 0; - if (actions.count() > 0) - actionBefore = actions[0]; - QAction *clearAction = new QAction(tr("Clear Char"), menu); - menu->insertAction(actionBefore, clearAction); - menu->insertSeparator(actionBefore); - clearAction->setEnabled(!m_value.isNull()); - connect(clearAction, SIGNAL(triggered()), this, SLOT(slotClearChar())); - menu->exec(c->globalPos()); - delete menu; - e->accept(); - return true; - } - - return QWidget::eventFilter(o, e); -} - -void QtCharEdit::slotClearChar() -{ - if (m_value.isNull()) - return; - setValue(QChar()); - emit valueChanged(m_value); -} - -void QtCharEdit::handleKeyEvent(QKeyEvent *e) -{ - const int key = e->key(); - switch (key) { - case Qt::Key_Control: - case Qt::Key_Shift: - case Qt::Key_Meta: - case Qt::Key_Alt: - case Qt::Key_Super_L: - case Qt::Key_Return: - return; - default: - break; - } - - const QString text = e->text(); - if (text.size() != 1) - return; - - const QChar c = text.at(0); - if (!c.isPrint()) - return; - - if (m_value == c) - return; - - m_value = c; - const QString str = m_value.isNull() ? QString() : QString(m_value); - m_lineEdit->setText(str); - e->accept(); - emit valueChanged(m_value); -} - -void QtCharEdit::setValue(const QChar &value) -{ - if (value == m_value) - return; - - m_value = value; - QString str = value.isNull() ? QString() : QString(value); - m_lineEdit->setText(str); -} - -QChar QtCharEdit::value() const -{ - return m_value; -} - -void QtCharEdit::focusInEvent(QFocusEvent *e) -{ - m_lineEdit->event(e); - m_lineEdit->selectAll(); - QWidget::focusInEvent(e); -} - -void QtCharEdit::focusOutEvent(QFocusEvent *e) -{ - m_lineEdit->event(e); - QWidget::focusOutEvent(e); -} - -void QtCharEdit::keyPressEvent(QKeyEvent *e) -{ - handleKeyEvent(e); - e->accept(); -} - -void QtCharEdit::keyReleaseEvent(QKeyEvent *e) -{ - m_lineEdit->event(e); -} - -void QtCharEdit::paintEvent(QPaintEvent *) -{ - QStyleOption opt; - opt.initFrom(this); - QPainter p(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); -} - -bool QtCharEdit::event(QEvent *e) -{ - switch(e->type()) { - case QEvent::Shortcut: - case QEvent::ShortcutOverride: - case QEvent::KeyRelease: - e->accept(); - return true; - default: - break; - } - return QWidget::event(e); -} - -// QtCharEditorFactory - -class QtCharEditorFactoryPrivate : public EditorFactoryPrivate -{ - QtCharEditorFactory *q_ptr; - Q_DECLARE_PUBLIC(QtCharEditorFactory) -public: - - void slotPropertyChanged(QtProperty *property, const QChar &value); - void slotSetValue(const QChar &value); - -}; - -void QtCharEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, - const QChar &value) -{ - if (!m_createdEditors.contains(property)) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QtCharEdit *editor = itEditor.next(); - editor->blockSignals(true); - editor->setValue(value); - editor->blockSignals(false); - } -} - -void QtCharEditorFactoryPrivate::slotSetValue(const QChar &value) -{ - QObject *object = q_ptr->sender(); - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtCharPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - -/*! - \class QtCharEditorFactory - - \brief The QtCharEditorFactory class provides editor - widgets for properties created by QtCharPropertyManager objects. - - \sa QtAbstractEditorFactory -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtCharEditorFactory::QtCharEditorFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtCharEditorFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtCharEditorFactory::~QtCharEditorFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtCharEditorFactory::connectPropertyManager(QtCharPropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, const QChar &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QChar &))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtCharEditorFactory::createEditor(QtCharPropertyManager *manager, - QtProperty *property, QWidget *parent) -{ - QtCharEdit *editor = d_ptr->createEditor(property, parent); - editor->setValue(manager->value(property)); - - connect(editor, SIGNAL(valueChanged(const QChar &)), - this, SLOT(slotSetValue(const QChar &))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtCharEditorFactory::disconnectPropertyManager(QtCharPropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QChar &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QChar &))); -} - -// QtEnumEditorFactory - -class QtEnumEditorFactoryPrivate : public EditorFactoryPrivate -{ - QtEnumEditorFactory *q_ptr; - Q_DECLARE_PUBLIC(QtEnumEditorFactory) -public: - - void slotPropertyChanged(QtProperty *property, int value); - void slotEnumNamesChanged(QtProperty *property, const QStringList &); - void slotEnumIconsChanged(QtProperty *property, const QMap &); - void slotSetValue(int value); -}; - -void QtEnumEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, int value) -{ - if (!m_createdEditors.contains(property)) - return; - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QComboBox *editor = itEditor.next(); - editor->blockSignals(true); - editor->setCurrentIndex(value); - editor->blockSignals(false); - } -} - -void QtEnumEditorFactoryPrivate::slotEnumNamesChanged(QtProperty *property, - const QStringList &enumNames) -{ - if (!m_createdEditors.contains(property)) - return; - - QtEnumPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - QMap enumIcons = manager->enumIcons(property); - - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QComboBox *editor = itEditor.next(); - editor->blockSignals(true); - editor->clear(); - editor->addItems(enumNames); - const int nameCount = enumNames.count(); - for (int i = 0; i < nameCount; i++) - editor->setItemIcon(i, enumIcons.value(i)); - editor->setCurrentIndex(manager->value(property)); - editor->blockSignals(false); - } -} - -void QtEnumEditorFactoryPrivate::slotEnumIconsChanged(QtProperty *property, - const QMap &enumIcons) -{ - if (!m_createdEditors.contains(property)) - return; - - QtEnumPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - - const QStringList enumNames = manager->enumNames(property); - QListIterator itEditor(m_createdEditors[property]); - while (itEditor.hasNext()) { - QComboBox *editor = itEditor.next(); - editor->blockSignals(true); - const int nameCount = enumNames.count(); - for (int i = 0; i < nameCount; i++) - editor->setItemIcon(i, enumIcons.value(i)); - editor->setCurrentIndex(manager->value(property)); - editor->blockSignals(false); - } -} - -void QtEnumEditorFactoryPrivate::slotSetValue(int value) -{ - QObject *object = q_ptr->sender(); - const QMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtEnumPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - -/*! - \class QtEnumEditorFactory - - \brief The QtEnumEditorFactory class provides QComboBox widgets for - properties created by QtEnumPropertyManager objects. - - \sa QtAbstractEditorFactory, QtEnumPropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtEnumEditorFactory::QtEnumEditorFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtEnumEditorFactoryPrivate(); - d_ptr->q_ptr = this; - -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtEnumEditorFactory::~QtEnumEditorFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtEnumEditorFactory::connectPropertyManager(QtEnumPropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotPropertyChanged(QtProperty *, int))); - connect(manager, SIGNAL(enumNamesChanged(QtProperty *, const QStringList &)), - this, SLOT(slotEnumNamesChanged(QtProperty *, const QStringList &))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtEnumEditorFactory::createEditor(QtEnumPropertyManager *manager, QtProperty *property, - QWidget *parent) -{ - QComboBox *editor = d_ptr->createEditor(property, parent); - editor->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); - editor->setMinimumContentsLength(1); - editor->view()->setTextElideMode(Qt::ElideRight); - QStringList enumNames = manager->enumNames(property); - editor->addItems(enumNames); - QMap enumIcons = manager->enumIcons(property); - const int enumNamesCount = enumNames.count(); - for (int i = 0; i < enumNamesCount; i++) - editor->setItemIcon(i, enumIcons.value(i)); - editor->setCurrentIndex(manager->value(property)); - - connect(editor, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSetValue(int))); - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtEnumEditorFactory::disconnectPropertyManager(QtEnumPropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotPropertyChanged(QtProperty *, int))); - disconnect(manager, SIGNAL(enumNamesChanged(QtProperty *, const QStringList &)), - this, SLOT(slotEnumNamesChanged(QtProperty *, const QStringList &))); -} - -// QtCursorEditorFactory - -Q_GLOBAL_STATIC(QtCursorDatabase, cursorDatabase) - -class QtCursorEditorFactoryPrivate -{ - QtCursorEditorFactory *q_ptr; - Q_DECLARE_PUBLIC(QtCursorEditorFactory) -public: - QtCursorEditorFactoryPrivate(); - - void slotPropertyChanged(QtProperty *property, const QCursor &cursor); - void slotEnumChanged(QtProperty *property, int value); - void slotEditorDestroyed(QObject *object); - - QtEnumEditorFactory *m_enumEditorFactory; - QtEnumPropertyManager *m_enumPropertyManager; - - QMap m_propertyToEnum; - QMap m_enumToProperty; - QMap > m_enumToEditors; - QMap m_editorToEnum; - bool m_updatingEnum; -}; - -QtCursorEditorFactoryPrivate::QtCursorEditorFactoryPrivate() - : m_updatingEnum(false) -{ - -} - -void QtCursorEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, const QCursor &cursor) -{ - // update enum property - QtProperty *enumProp = m_propertyToEnum.value(property); - if (!enumProp) - return; - - m_updatingEnum = true; - m_enumPropertyManager->setValue(enumProp, cursorDatabase()->cursorToValue(cursor)); - m_updatingEnum = false; -} - -void QtCursorEditorFactoryPrivate::slotEnumChanged(QtProperty *property, int value) -{ - if (m_updatingEnum) - return; - // update cursor property - QtProperty *prop = m_enumToProperty.value(property); - if (!prop) - return; - QtCursorPropertyManager *cursorManager = q_ptr->propertyManager(prop); - if (!cursorManager) - return; -#ifndef QT_NO_CURSOR - cursorManager->setValue(prop, QCursor(cursorDatabase()->valueToCursor(value))); -#endif -} - -void QtCursorEditorFactoryPrivate::slotEditorDestroyed(QObject *object) -{ - // remove from m_editorToEnum map; - // remove from m_enumToEditors map; - // if m_enumToEditors doesn't contains more editors delete enum property; - const QMap::ConstIterator ecend = m_editorToEnum.constEnd(); - for (QMap::ConstIterator itEditor = m_editorToEnum.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QWidget *editor = itEditor.key(); - QtProperty *enumProp = itEditor.value(); - m_editorToEnum.remove(editor); - m_enumToEditors[enumProp].removeAll(editor); - if (m_enumToEditors[enumProp].isEmpty()) { - m_enumToEditors.remove(enumProp); - QtProperty *property = m_enumToProperty.value(enumProp); - m_enumToProperty.remove(enumProp); - m_propertyToEnum.remove(property); - delete enumProp; - } - return; - } -} - -/*! - \class QtCursorEditorFactory - - \brief The QtCursorEditorFactory class provides QComboBox widgets for - properties created by QtCursorPropertyManager objects. - - \sa QtAbstractEditorFactory, QtCursorPropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtCursorEditorFactory::QtCursorEditorFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtCursorEditorFactoryPrivate(); - d_ptr->q_ptr = this; - - d_ptr->m_enumEditorFactory = new QtEnumEditorFactory(this); - d_ptr->m_enumPropertyManager = new QtEnumPropertyManager(this); - connect(d_ptr->m_enumPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotEnumChanged(QtProperty *, int))); - d_ptr->m_enumEditorFactory->addPropertyManager(d_ptr->m_enumPropertyManager); -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtCursorEditorFactory::~QtCursorEditorFactory() -{ - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtCursorEditorFactory::connectPropertyManager(QtCursorPropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty *, const QCursor &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QCursor &))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtCursorEditorFactory::createEditor(QtCursorPropertyManager *manager, QtProperty *property, - QWidget *parent) -{ - QtProperty *enumProp = 0; - if (d_ptr->m_propertyToEnum.contains(property)) { - enumProp = d_ptr->m_propertyToEnum[property]; - } else { - enumProp = d_ptr->m_enumPropertyManager->addProperty(property->propertyName()); - d_ptr->m_enumPropertyManager->setEnumNames(enumProp, cursorDatabase()->cursorShapeNames()); - d_ptr->m_enumPropertyManager->setEnumIcons(enumProp, cursorDatabase()->cursorShapeIcons()); -#ifndef QT_NO_CURSOR - d_ptr->m_enumPropertyManager->setValue(enumProp, cursorDatabase()->cursorToValue(manager->value(property))); -#endif - d_ptr->m_propertyToEnum[property] = enumProp; - d_ptr->m_enumToProperty[enumProp] = property; - } - QtAbstractEditorFactoryBase *af = d_ptr->m_enumEditorFactory; - QWidget *editor = af->createEditor(enumProp, parent); - d_ptr->m_enumToEditors[enumProp].append(editor); - d_ptr->m_editorToEnum[editor] = enumProp; - connect(editor, SIGNAL(destroyed(QObject *)), - this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtCursorEditorFactory::disconnectPropertyManager(QtCursorPropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty *, const QCursor &)), - this, SLOT(slotPropertyChanged(QtProperty *, const QCursor &))); -} - -// QtColorEditWidget - -class QtColorEditWidget : public QWidget { - Q_OBJECT - -public: - explicit QtColorEditWidget(QWidget *parent); - - bool eventFilter(QObject *obj, QEvent *ev); - -public Q_SLOTS: - void setValue(const QColor &value); - -Q_SIGNALS: - void valueChanged(const QColor &value); - -protected: - void paintEvent(QPaintEvent *); - -private Q_SLOTS: - void buttonClicked(); - -private: - QColor m_color; - QLabel *m_pixmapLabel; - QLabel *m_label; - QToolButton *m_button; -}; - -QtColorEditWidget::QtColorEditWidget(QWidget *parent) : - QWidget(parent), - m_pixmapLabel(new QLabel), - m_label(new QLabel), - m_button(new QToolButton) -{ - QHBoxLayout *lt = new QHBoxLayout(this); - setupTreeViewEditorMargin(lt); - lt->setSpacing(0); - lt->addWidget(m_pixmapLabel); - lt->addWidget(m_label); - lt->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored)); - - m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored); - m_button->setFixedWidth(20); - setFocusProxy(m_button); - setFocusPolicy(m_button->focusPolicy()); - m_button->setText(tr("...")); - m_button->installEventFilter(this); - connect(m_button, SIGNAL(clicked()), this, SLOT(buttonClicked())); - lt->addWidget(m_button); - m_pixmapLabel->setPixmap(QtPropertyBrowserUtils::brushValuePixmap(QBrush(m_color))); - m_pixmapLabel->setVisible(m_color.isValid()); - m_label->setText(QtPropertyBrowserUtils::colorValueText(m_color)); -} - -void QtColorEditWidget::setValue(const QColor &c) -{ - if (m_color != c) { - m_color = c; - m_pixmapLabel->setPixmap(QtPropertyBrowserUtils::brushValuePixmap(QBrush(c))); - m_pixmapLabel->setVisible(c.isValid()); - m_label->setText(QtPropertyBrowserUtils::colorValueText(c)); - } -} - -void QtColorEditWidget::buttonClicked() -{ - QColor newColor = QColorDialog::getColor(m_color, this, QString(), QColorDialog::ShowAlphaChannel); - if (newColor.isValid() && newColor != m_color) { - setValue(newColor); - emit valueChanged(m_color); - } -} - -bool QtColorEditWidget::eventFilter(QObject *obj, QEvent *ev) -{ - if (obj == m_button) { - switch (ev->type()) { - case QEvent::KeyPress: - case QEvent::KeyRelease: { // Prevent the QToolButton from handling Enter/Escape meant control the delegate - switch (static_cast(ev)->key()) { - case Qt::Key_Escape: - case Qt::Key_Enter: - case Qt::Key_Return: - ev->ignore(); - return true; - default: - break; - } - } - break; - default: - break; - } - } - return QWidget::eventFilter(obj, ev); -} - -void QtColorEditWidget::paintEvent(QPaintEvent *) -{ - QStyleOption opt; - opt.initFrom(this); - QPainter p(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); -} - -// QtColorEditorFactoryPrivate - -class QtColorEditorFactoryPrivate : public EditorFactoryPrivate -{ - QtColorEditorFactory *q_ptr; - Q_DECLARE_PUBLIC(QtColorEditorFactory) -public: - - void slotPropertyChanged(QtProperty *property, const QColor &value); - void slotSetValue(const QColor &value); -}; - -void QtColorEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, - const QColor &value) -{ - const PropertyToEditorListMap::iterator it = m_createdEditors.find(property); - if (it == m_createdEditors.end()) - return; - QListIterator itEditor(it.value()); - - while (itEditor.hasNext()) - itEditor.next()->setValue(value); -} - -void QtColorEditorFactoryPrivate::slotSetValue(const QColor &value) -{ - QObject *object = q_ptr->sender(); - const EditorToPropertyMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (EditorToPropertyMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtColorPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - -/*! - \class QtColorEditorFactory - - \brief The QtColorEditorFactory class provides color editing for - properties created by QtColorPropertyManager objects. - - \sa QtAbstractEditorFactory, QtColorPropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtColorEditorFactory::QtColorEditorFactory(QObject *parent) : - QtAbstractEditorFactory(parent), - d_ptr(new QtColorEditorFactoryPrivate()) -{ - d_ptr->q_ptr = this; -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtColorEditorFactory::~QtColorEditorFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtColorEditorFactory::connectPropertyManager(QtColorPropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty*,QColor)), - this, SLOT(slotPropertyChanged(QtProperty*,QColor))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtColorEditorFactory::createEditor(QtColorPropertyManager *manager, - QtProperty *property, QWidget *parent) -{ - QtColorEditWidget *editor = d_ptr->createEditor(property, parent); - editor->setValue(manager->value(property)); - connect(editor, SIGNAL(valueChanged(QColor)), this, SLOT(slotSetValue(QColor))); - connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtColorEditorFactory::disconnectPropertyManager(QtColorPropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty*,QColor)), this, SLOT(slotPropertyChanged(QtProperty*,QColor))); -} - -// QtFontEditWidget - -class QtFontEditWidget : public QWidget { - Q_OBJECT - -public: - explicit QtFontEditWidget(QWidget *parent); - - bool eventFilter(QObject *obj, QEvent *ev); - -public Q_SLOTS: - void setValue(const QFont &value); - -Q_SIGNALS: - void valueChanged(const QFont &value); - -protected: - void paintEvent(QPaintEvent *); - -private Q_SLOTS: - void buttonClicked(); - -private: - QFont m_font; - QLabel *m_pixmapLabel; - QLabel *m_label; - QToolButton *m_button; -}; - -QtFontEditWidget::QtFontEditWidget(QWidget *parent) : - QWidget(parent), - m_pixmapLabel(new QLabel), - m_label(new QLabel), - m_button(new QToolButton) -{ - QHBoxLayout *lt = new QHBoxLayout(this); - setupTreeViewEditorMargin(lt); - lt->setSpacing(0); - lt->addWidget(m_pixmapLabel); - lt->addWidget(m_label); - lt->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored)); - - m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored); - m_button->setFixedWidth(20); - setFocusProxy(m_button); - setFocusPolicy(m_button->focusPolicy()); - m_button->setText(tr("...")); - m_button->installEventFilter(this); - connect(m_button, SIGNAL(clicked()), this, SLOT(buttonClicked())); - lt->addWidget(m_button); - m_pixmapLabel->setPixmap(QtPropertyBrowserUtils::fontValuePixmap(m_font)); - m_label->setText(QtPropertyBrowserUtils::fontValueText(m_font)); -} - -void QtFontEditWidget::setValue(const QFont &f) -{ - if (m_font != f) { - m_font = f; - m_pixmapLabel->setPixmap(QtPropertyBrowserUtils::fontValuePixmap(f)); - m_label->setText(QtPropertyBrowserUtils::fontValueText(f)); - } -} - -void QtFontEditWidget::buttonClicked() -{ - bool ok = false; - - QFont oldFont = m_font; - - // Font dialogs generally deal with point sizes. When the font size is set - // in pixels, convert to points. - if (m_font.pixelSize() != -1) - oldFont.setPointSizeF(oldFont.pixelSize() / logicalDpiX() * 72.0); - - QFont newFont = QFontDialog::getFont(&ok, oldFont, this, tr("Select Font")); - if (ok && newFont != oldFont) { - QFont f = m_font; - - // Convert back to pixels when the current font size is set in pixels - if (m_font.pixelSize() != -1 && newFont.pointSize() != -1) { - int pixelSize = qRound(newFont.pointSizeF() / 72.0 * logicalDpiX()); - newFont.setPixelSize(pixelSize); - } - - // prevent mask for unchanged attributes, don't change other attributes (like kerning, etc...) - if (m_font.family() != newFont.family()) - f.setFamily(newFont.family()); - if (m_font.pixelSize() != newFont.pixelSize() && newFont.pixelSize() != -1) - f.setPixelSize(newFont.pixelSize()); - if (m_font.pointSize() != newFont.pointSize() && newFont.pointSize() != -1) - f.setPointSizeF(newFont.pointSizeF()); - if (m_font.bold() != newFont.bold()) - f.setBold(newFont.bold()); - if (m_font.italic() != newFont.italic()) - f.setItalic(newFont.italic()); - if (m_font.underline() != newFont.underline()) - f.setUnderline(newFont.underline()); - if (m_font.strikeOut() != newFont.strikeOut()) - f.setStrikeOut(newFont.strikeOut()); - setValue(f); - emit valueChanged(m_font); - } -} - -bool QtFontEditWidget::eventFilter(QObject *obj, QEvent *ev) -{ - if (obj == m_button) { - switch (ev->type()) { - case QEvent::KeyPress: - case QEvent::KeyRelease: { // Prevent the QToolButton from handling Enter/Escape meant control the delegate - switch (static_cast(ev)->key()) { - case Qt::Key_Escape: - case Qt::Key_Enter: - case Qt::Key_Return: - ev->ignore(); - return true; - default: - break; - } - } - break; - default: - break; - } - } - return QWidget::eventFilter(obj, ev); -} - -void QtFontEditWidget::paintEvent(QPaintEvent *) -{ - QStyleOption opt; - opt.initFrom(this); - QPainter p(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); -} - -// QtFontEditorFactoryPrivate - -class QtFontEditorFactoryPrivate : public EditorFactoryPrivate -{ - QtFontEditorFactory *q_ptr; - Q_DECLARE_PUBLIC(QtFontEditorFactory) -public: - - void slotPropertyChanged(QtProperty *property, const QFont &value); - void slotSetValue(const QFont &value); -}; - -void QtFontEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, - const QFont &value) -{ - const PropertyToEditorListMap::iterator it = m_createdEditors.find(property); - if (it == m_createdEditors.end()) - return; - QListIterator itEditor(it.value()); - - while (itEditor.hasNext()) - itEditor.next()->setValue(value); -} - -void QtFontEditorFactoryPrivate::slotSetValue(const QFont &value) -{ - QObject *object = q_ptr->sender(); - const EditorToPropertyMap::ConstIterator ecend = m_editorToProperty.constEnd(); - for (EditorToPropertyMap::ConstIterator itEditor = m_editorToProperty.constBegin(); itEditor != ecend; ++itEditor) - if (itEditor.key() == object) { - QtProperty *property = itEditor.value(); - QtFontPropertyManager *manager = q_ptr->propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - return; - } -} - -/*! - \class QtFontEditorFactory - - \brief The QtFontEditorFactory class provides font editing for - properties created by QtFontPropertyManager objects. - - \sa QtAbstractEditorFactory, QtFontPropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtFontEditorFactory::QtFontEditorFactory(QObject *parent) : - QtAbstractEditorFactory(parent), - d_ptr(new QtFontEditorFactoryPrivate()) -{ - d_ptr->q_ptr = this; -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtFontEditorFactory::~QtFontEditorFactory() -{ - qDeleteAll(d_ptr->m_editorToProperty.keys()); - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtFontEditorFactory::connectPropertyManager(QtFontPropertyManager *manager) -{ - connect(manager, SIGNAL(valueChanged(QtProperty*,QFont)), - this, SLOT(slotPropertyChanged(QtProperty*,QFont))); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtFontEditorFactory::createEditor(QtFontPropertyManager *manager, - QtProperty *property, QWidget *parent) -{ - QtFontEditWidget *editor = d_ptr->createEditor(property, parent); - editor->setValue(manager->value(property)); - connect(editor, SIGNAL(valueChanged(QFont)), this, SLOT(slotSetValue(QFont))); - connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); - return editor; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtFontEditorFactory::disconnectPropertyManager(QtFontPropertyManager *manager) -{ - disconnect(manager, SIGNAL(valueChanged(QtProperty*,QFont)), this, SLOT(slotPropertyChanged(QtProperty*,QFont))); -} - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#include "moc_qteditorfactory.cpp" -#include "qteditorfactory.moc" diff --git a/src/qtpropertybrowser/src/qteditorfactory.h b/src/qtpropertybrowser/src/qteditorfactory.h deleted file mode 100644 index c258ae7be8..0000000000 --- a/src/qtpropertybrowser/src/qteditorfactory.h +++ /dev/null @@ -1,406 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QTEDITORFACTORY_H -#define QTEDITORFACTORY_H - -#include "qtpropertymanager.h" - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QtSpinBoxFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtSpinBoxFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtSpinBoxFactory(QObject *parent = 0); - ~QtSpinBoxFactory(); -protected: - void connectPropertyManager(QtIntPropertyManager *manager); - QWidget *createEditor(QtIntPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtIntPropertyManager *manager); -private: - QtSpinBoxFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtSpinBoxFactory) - Q_DISABLE_COPY(QtSpinBoxFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, int, int)) - Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotReadOnlyChanged(QtProperty *, bool)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(int)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtSliderFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtSliderFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtSliderFactory(QObject *parent = 0); - ~QtSliderFactory(); -protected: - void connectPropertyManager(QtIntPropertyManager *manager); - QWidget *createEditor(QtIntPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtIntPropertyManager *manager); -private: - QtSliderFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtSliderFactory) - Q_DISABLE_COPY(QtSliderFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, int, int)) - Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(int)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtScrollBarFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtScrollBarFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtScrollBarFactory(QObject *parent = 0); - ~QtScrollBarFactory(); -protected: - void connectPropertyManager(QtIntPropertyManager *manager); - QWidget *createEditor(QtIntPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtIntPropertyManager *manager); -private: - QtScrollBarFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtScrollBarFactory) - Q_DISABLE_COPY(QtScrollBarFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, int, int)) - Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(int)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtCheckBoxFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtCheckBoxFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtCheckBoxFactory(QObject *parent = 0); - ~QtCheckBoxFactory(); -protected: - void connectPropertyManager(QtBoolPropertyManager *manager); - QWidget *createEditor(QtBoolPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtBoolPropertyManager *manager); -private: - QtCheckBoxFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtCheckBoxFactory) - Q_DISABLE_COPY(QtCheckBoxFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, bool)) - Q_PRIVATE_SLOT(d_func(), void slotTextVisibleChanged(QtProperty *, bool)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(bool)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtDoubleSpinBoxFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtDoubleSpinBoxFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtDoubleSpinBoxFactory(QObject *parent = 0); - ~QtDoubleSpinBoxFactory(); -protected: - void connectPropertyManager(QtDoublePropertyManager *manager); - QWidget *createEditor(QtDoublePropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtDoublePropertyManager *manager); -private: - QtDoubleSpinBoxFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtDoubleSpinBoxFactory) - Q_DISABLE_COPY(QtDoubleSpinBoxFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, double)) - Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, double, double)) - Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, double)) - Q_PRIVATE_SLOT(d_func(), void slotDecimalsChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotReadOnlyChanged(QtProperty *, bool)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(double)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtLineEditFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtLineEditFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtLineEditFactory(QObject *parent = 0); - ~QtLineEditFactory(); -protected: - void connectPropertyManager(QtStringPropertyManager *manager); - QWidget *createEditor(QtStringPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtStringPropertyManager *manager); -private: - QtLineEditFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtLineEditFactory) - Q_DISABLE_COPY(QtLineEditFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QString &)) - Q_PRIVATE_SLOT(d_func(), void slotRegExpChanged(QtProperty *, const QRegularExpression &)) - Q_PRIVATE_SLOT(d_func(), void slotEchoModeChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotReadOnlyChanged(QtProperty *, bool)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QString &)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtDateEditFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtDateEditFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtDateEditFactory(QObject *parent = 0); - ~QtDateEditFactory(); -protected: - void connectPropertyManager(QtDatePropertyManager *manager); - QWidget *createEditor(QtDatePropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtDatePropertyManager *manager); -private: - QtDateEditFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtDateEditFactory) - Q_DISABLE_COPY(QtDateEditFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QDate &)) - Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, - const QDate &, const QDate &)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QDate &)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtTimeEditFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtTimeEditFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtTimeEditFactory(QObject *parent = 0); - ~QtTimeEditFactory(); -protected: - void connectPropertyManager(QtTimePropertyManager *manager); - QWidget *createEditor(QtTimePropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtTimePropertyManager *manager); -private: - QtTimeEditFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtTimeEditFactory) - Q_DISABLE_COPY(QtTimeEditFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QTime &)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QTime &)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtDateTimeEditFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtDateTimeEditFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtDateTimeEditFactory(QObject *parent = 0); - ~QtDateTimeEditFactory(); -protected: - void connectPropertyManager(QtDateTimePropertyManager *manager); - QWidget *createEditor(QtDateTimePropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtDateTimePropertyManager *manager); -private: - QtDateTimeEditFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtDateTimeEditFactory) - Q_DISABLE_COPY(QtDateTimeEditFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QDateTime &)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QDateTime &)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtKeySequenceEditorFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtKeySequenceEditorFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtKeySequenceEditorFactory(QObject *parent = 0); - ~QtKeySequenceEditorFactory(); -protected: - void connectPropertyManager(QtKeySequencePropertyManager *manager); - QWidget *createEditor(QtKeySequencePropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtKeySequencePropertyManager *manager); -private: - QtKeySequenceEditorFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtKeySequenceEditorFactory) - Q_DISABLE_COPY(QtKeySequenceEditorFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QKeySequence &)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QKeySequence &)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtCharEditorFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtCharEditorFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtCharEditorFactory(QObject *parent = 0); - ~QtCharEditorFactory(); -protected: - void connectPropertyManager(QtCharPropertyManager *manager); - QWidget *createEditor(QtCharPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtCharPropertyManager *manager); -private: - QtCharEditorFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtCharEditorFactory) - Q_DISABLE_COPY(QtCharEditorFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QChar &)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QChar &)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtEnumEditorFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtEnumEditorFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtEnumEditorFactory(QObject *parent = 0); - ~QtEnumEditorFactory(); -protected: - void connectPropertyManager(QtEnumPropertyManager *manager); - QWidget *createEditor(QtEnumPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtEnumPropertyManager *manager); -private: - QtEnumEditorFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtEnumEditorFactory) - Q_DISABLE_COPY(QtEnumEditorFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotEnumNamesChanged(QtProperty *, - const QStringList &)) - Q_PRIVATE_SLOT(d_func(), void slotEnumIconsChanged(QtProperty *, - const QMap &)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(int)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtCursorEditorFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtCursorEditorFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtCursorEditorFactory(QObject *parent = 0); - ~QtCursorEditorFactory(); -protected: - void connectPropertyManager(QtCursorPropertyManager *manager); - QWidget *createEditor(QtCursorPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtCursorPropertyManager *manager); -private: - QtCursorEditorFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtCursorEditorFactory) - Q_DISABLE_COPY(QtCursorEditorFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QCursor &)) - Q_PRIVATE_SLOT(d_func(), void slotEnumChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) -}; - -class QtColorEditorFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtColorEditorFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtColorEditorFactory(QObject *parent = 0); - ~QtColorEditorFactory(); -protected: - void connectPropertyManager(QtColorPropertyManager *manager); - QWidget *createEditor(QtColorPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtColorPropertyManager *manager); -private: - QtColorEditorFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtColorEditorFactory) - Q_DISABLE_COPY(QtColorEditorFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QColor &)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QColor &)) -}; - -class QtFontEditorFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtFontEditorFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtFontEditorFactory(QObject *parent = 0); - ~QtFontEditorFactory(); -protected: - void connectPropertyManager(QtFontPropertyManager *manager); - QWidget *createEditor(QtFontPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtFontPropertyManager *manager); -private: - QtFontEditorFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtFontEditorFactory) - Q_DISABLE_COPY(QtFontEditorFactory) - Q_PRIVATE_SLOT(d_func(), void slotPropertyChanged(QtProperty *, const QFont &)) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed(QObject *)) - Q_PRIVATE_SLOT(d_func(), void slotSetValue(const QFont &)) -}; - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#endif diff --git a/src/qtpropertybrowser/src/qtgroupboxpropertybrowser.cpp b/src/qtpropertybrowser/src/qtgroupboxpropertybrowser.cpp deleted file mode 100644 index b2c4989d5d..0000000000 --- a/src/qtpropertybrowser/src/qtgroupboxpropertybrowser.cpp +++ /dev/null @@ -1,534 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qtgroupboxpropertybrowser.h" -#include -#include -#include -#include -#include -#include - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QtGroupBoxPropertyBrowserPrivate -{ - QtGroupBoxPropertyBrowser *q_ptr; - Q_DECLARE_PUBLIC(QtGroupBoxPropertyBrowser) -public: - - void init(QWidget *parent); - - void propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex); - void propertyRemoved(QtBrowserItem *index); - void propertyChanged(QtBrowserItem *index); - QWidget *createEditor(QtProperty *property, QWidget *parent) const - { return q_ptr->createEditor(property, parent); } - - void slotEditorDestroyed(); - void slotUpdate(); - - struct WidgetItem - { - WidgetItem() : widget(0), label(0), widgetLabel(0), - groupBox(0), layout(0), line(0), parent(0) { } - QWidget *widget; // can be null - QLabel *label; - QLabel *widgetLabel; - QGroupBox *groupBox; - QGridLayout *layout; - QFrame *line; - WidgetItem *parent; - QList children; - }; -private: - void updateLater(); - void updateItem(WidgetItem *item); - void insertRow(QGridLayout *layout, int row) const; - void removeRow(QGridLayout *layout, int row) const; - - bool hasHeader(WidgetItem *item) const; - - QMap m_indexToItem; - QMap m_itemToIndex; - QMap m_widgetToItem; - QGridLayout *m_mainLayout; - QList m_children; - QList m_recreateQueue; -}; - -void QtGroupBoxPropertyBrowserPrivate::init(QWidget *parent) -{ - m_mainLayout = new QGridLayout(); - parent->setLayout(m_mainLayout); - QLayoutItem *item = new QSpacerItem(0, 0, - QSizePolicy::Fixed, QSizePolicy::Expanding); - m_mainLayout->addItem(item, 0, 0); -} - -void QtGroupBoxPropertyBrowserPrivate::slotEditorDestroyed() -{ - QWidget *editor = qobject_cast(q_ptr->sender()); - if (!editor) - return; - if (!m_widgetToItem.contains(editor)) - return; - m_widgetToItem[editor]->widget = 0; - m_widgetToItem.remove(editor); -} - -void QtGroupBoxPropertyBrowserPrivate::slotUpdate() -{ - QListIterator itItem(m_recreateQueue); - while (itItem.hasNext()) { - WidgetItem *item = itItem.next(); - - WidgetItem *par = item->parent; - QWidget *w = 0; - QGridLayout *l = 0; - int oldRow = -1; - if (!par) { - w = q_ptr; - l = m_mainLayout; - oldRow = m_children.indexOf(item); - } else { - w = par->groupBox; - l = par->layout; - oldRow = par->children.indexOf(item); - if (hasHeader(par)) - oldRow += 2; - } - - if (item->widget) { - item->widget->setParent(w); - } else if (item->widgetLabel) { - item->widgetLabel->setParent(w); - } else { - item->widgetLabel = new QLabel(w); - item->widgetLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed)); - item->widgetLabel->setTextFormat(Qt::PlainText); - } - int span = 1; - if (item->widget) - l->addWidget(item->widget, oldRow, 1, 1, 1); - else if (item->widgetLabel) - l->addWidget(item->widgetLabel, oldRow, 1, 1, 1); - else - span = 2; - item->label = new QLabel(w); - item->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); - l->addWidget(item->label, oldRow, 0, 1, span); - - updateItem(item); - } - m_recreateQueue.clear(); -} - -void QtGroupBoxPropertyBrowserPrivate::updateLater() -{ - QTimer::singleShot(0, q_ptr, SLOT(slotUpdate())); -} - -void QtGroupBoxPropertyBrowserPrivate::propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex) -{ - WidgetItem *afterItem = m_indexToItem.value(afterIndex); - WidgetItem *parentItem = m_indexToItem.value(index->parent()); - - WidgetItem *newItem = new WidgetItem(); - newItem->parent = parentItem; - - QGridLayout *layout = 0; - QWidget *parentWidget = 0; - int row = -1; - if (!afterItem) { - row = 0; - if (parentItem) - parentItem->children.insert(0, newItem); - else - m_children.insert(0, newItem); - } else { - if (parentItem) { - row = parentItem->children.indexOf(afterItem) + 1; - parentItem->children.insert(row, newItem); - } else { - row = m_children.indexOf(afterItem) + 1; - m_children.insert(row, newItem); - } - } - if (parentItem && hasHeader(parentItem)) - row += 2; - - if (!parentItem) { - layout = m_mainLayout; - parentWidget = q_ptr;; - } else { - if (!parentItem->groupBox) { - m_recreateQueue.removeAll(parentItem); - WidgetItem *par = parentItem->parent; - QWidget *w = 0; - QGridLayout *l = 0; - int oldRow = -1; - if (!par) { - w = q_ptr; - l = m_mainLayout; - oldRow = m_children.indexOf(parentItem); - } else { - w = par->groupBox; - l = par->layout; - oldRow = par->children.indexOf(parentItem); - if (hasHeader(par)) - oldRow += 2; - } - parentItem->groupBox = new QGroupBox(w); - parentItem->layout = new QGridLayout(); - parentItem->groupBox->setLayout(parentItem->layout); - if (parentItem->label) { - l->removeWidget(parentItem->label); - delete parentItem->label; - parentItem->label = 0; - } - if (parentItem->widget) { - l->removeWidget(parentItem->widget); - parentItem->widget->setParent(parentItem->groupBox); - parentItem->layout->addWidget(parentItem->widget, 0, 0, 1, 2); - parentItem->line = new QFrame(parentItem->groupBox); - } else if (parentItem->widgetLabel) { - l->removeWidget(parentItem->widgetLabel); - delete parentItem->widgetLabel; - parentItem->widgetLabel = 0; - } - if (parentItem->line) { - parentItem->line->setFrameShape(QFrame::HLine); - parentItem->line->setFrameShadow(QFrame::Sunken); - parentItem->layout->addWidget(parentItem->line, 1, 0, 1, 2); - } - l->addWidget(parentItem->groupBox, oldRow, 0, 1, 2); - updateItem(parentItem); - } - layout = parentItem->layout; - parentWidget = parentItem->groupBox; - } - - newItem->label = new QLabel(parentWidget); - newItem->label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); - newItem->widget = createEditor(index->property(), parentWidget); - if (!newItem->widget) { - newItem->widgetLabel = new QLabel(parentWidget); - newItem->widgetLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed)); - newItem->widgetLabel->setTextFormat(Qt::PlainText); - } else { - QObject::connect(newItem->widget, SIGNAL(destroyed()), q_ptr, SLOT(slotEditorDestroyed())); - m_widgetToItem[newItem->widget] = newItem; - } - - insertRow(layout, row); - int span = 1; - if (newItem->widget) - layout->addWidget(newItem->widget, row, 1); - else if (newItem->widgetLabel) - layout->addWidget(newItem->widgetLabel, row, 1); - else - span = 2; - layout->addWidget(newItem->label, row, 0, 1, span); - - m_itemToIndex[newItem] = index; - m_indexToItem[index] = newItem; - - updateItem(newItem); -} - -void QtGroupBoxPropertyBrowserPrivate::propertyRemoved(QtBrowserItem *index) -{ - WidgetItem *item = m_indexToItem.value(index); - - m_indexToItem.remove(index); - m_itemToIndex.remove(item); - - WidgetItem *parentItem = item->parent; - - int row = -1; - - if (parentItem) { - row = parentItem->children.indexOf(item); - parentItem->children.removeAt(row); - if (hasHeader(parentItem)) - row += 2; - } else { - row = m_children.indexOf(item); - m_children.removeAt(row); - } - - if (item->widget) - delete item->widget; - if (item->label) - delete item->label; - if (item->widgetLabel) - delete item->widgetLabel; - if (item->groupBox) - delete item->groupBox; - - if (!parentItem) { - removeRow(m_mainLayout, row); - } else if (parentItem->children.count() != 0) { - removeRow(parentItem->layout, row); - } else { - WidgetItem *par = parentItem->parent; - QGridLayout *l = 0; - int oldRow = -1; - if (!par) { - l = m_mainLayout; - oldRow = m_children.indexOf(parentItem); - } else { - l = par->layout; - oldRow = par->children.indexOf(parentItem); - if (hasHeader(par)) - oldRow += 2; - } - - if (parentItem->widget) { - parentItem->widget->hide(); - parentItem->widget->setParent(0); - } else if (parentItem->widgetLabel) { - parentItem->widgetLabel->hide(); - parentItem->widgetLabel->setParent(0); - } else { - //parentItem->widgetLabel = new QLabel(w); - } - l->removeWidget(parentItem->groupBox); - delete parentItem->groupBox; - parentItem->groupBox = 0; - parentItem->line = 0; - parentItem->layout = 0; - if (!m_recreateQueue.contains(parentItem)) - m_recreateQueue.append(parentItem); - updateLater(); - } - m_recreateQueue.removeAll(item); - - delete item; -} - -void QtGroupBoxPropertyBrowserPrivate::insertRow(QGridLayout *layout, int row) const -{ - QMap itemToPos; - int idx = 0; - while (idx < layout->count()) { - int r, c, rs, cs; - layout->getItemPosition(idx, &r, &c, &rs, &cs); - if (r >= row) { - itemToPos[layout->takeAt(idx)] = QRect(r + 1, c, rs, cs); - } else { - idx++; - } - } - - const QMap::ConstIterator icend = itemToPos.constEnd(); - for (QMap::ConstIterator it = itemToPos.constBegin(); it != icend; ++it) { - const QRect r = it.value(); - layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height()); - } -} - -void QtGroupBoxPropertyBrowserPrivate::removeRow(QGridLayout *layout, int row) const -{ - QMap itemToPos; - int idx = 0; - while (idx < layout->count()) { - int r, c, rs, cs; - layout->getItemPosition(idx, &r, &c, &rs, &cs); - if (r > row) { - itemToPos[layout->takeAt(idx)] = QRect(r - 1, c, rs, cs); - } else { - idx++; - } - } - - const QMap::ConstIterator icend = itemToPos.constEnd(); - for (QMap::ConstIterator it = itemToPos.constBegin(); it != icend; ++it) { - const QRect r = it.value(); - layout->addItem(it.key(), r.x(), r.y(), r.width(), r.height()); - } -} - -bool QtGroupBoxPropertyBrowserPrivate::hasHeader(WidgetItem *item) const -{ - if (item->widget) - return true; - return false; -} - -void QtGroupBoxPropertyBrowserPrivate::propertyChanged(QtBrowserItem *index) -{ - WidgetItem *item = m_indexToItem.value(index); - - updateItem(item); -} - -void QtGroupBoxPropertyBrowserPrivate::updateItem(WidgetItem *item) -{ - QtProperty *property = m_itemToIndex[item]->property(); - if (item->groupBox) { - QFont font = item->groupBox->font(); - font.setUnderline(property->isModified()); - item->groupBox->setFont(font); - item->groupBox->setTitle(property->propertyName()); - item->groupBox->setToolTip(property->toolTip()); - item->groupBox->setStatusTip(property->statusTip()); - item->groupBox->setWhatsThis(property->whatsThis()); - item->groupBox->setEnabled(property->isEnabled()); - } - if (item->label) { - QFont font = item->label->font(); - font.setUnderline(property->isModified()); - item->label->setFont(font); - item->label->setText(property->propertyName()); - item->label->setToolTip(property->toolTip()); - item->label->setStatusTip(property->statusTip()); - item->label->setWhatsThis(property->whatsThis()); - item->label->setEnabled(property->isEnabled()); - } - if (item->widgetLabel) { - QFont font = item->widgetLabel->font(); - font.setUnderline(false); - item->widgetLabel->setFont(font); - item->widgetLabel->setText(property->valueText()); - item->widgetLabel->setToolTip(property->valueText()); - item->widgetLabel->setEnabled(property->isEnabled()); - } - if (item->widget) { - QFont font = item->widget->font(); - font.setUnderline(false); - item->widget->setFont(font); - item->widget->setEnabled(property->isEnabled()); - item->widget->setToolTip(property->valueText()); - } - //item->setIcon(1, property->valueIcon()); -} - - - -/*! - \class QtGroupBoxPropertyBrowser - - \brief The QtGroupBoxPropertyBrowser class provides a QGroupBox - based property browser. - - A property browser is a widget that enables the user to edit a - given set of properties. Each property is represented by a label - specifying the property's name, and an editing widget (e.g. a line - edit or a combobox) holding its value. A property can have zero or - more subproperties. - - QtGroupBoxPropertyBrowser provides group boxes for all nested - properties, i.e. subproperties are enclosed by a group box with - the parent property's name as its title. For example: - - \image qtgroupboxpropertybrowser.png - - Use the QtAbstractPropertyBrowser API to add, insert and remove - properties from an instance of the QtGroupBoxPropertyBrowser - class. The properties themselves are created and managed by - implementations of the QtAbstractPropertyManager class. - - \sa QtTreePropertyBrowser, QtAbstractPropertyBrowser -*/ - -/*! - Creates a property browser with the given \a parent. -*/ -QtGroupBoxPropertyBrowser::QtGroupBoxPropertyBrowser(QWidget *parent) - : QtAbstractPropertyBrowser(parent) -{ - d_ptr = new QtGroupBoxPropertyBrowserPrivate; - d_ptr->q_ptr = this; - - d_ptr->init(this); -} - -/*! - Destroys this property browser. - - Note that the properties that were inserted into this browser are - \e not destroyed since they may still be used in other - browsers. The properties are owned by the manager that created - them. - - \sa QtProperty, QtAbstractPropertyManager -*/ -QtGroupBoxPropertyBrowser::~QtGroupBoxPropertyBrowser() -{ - const QMap::ConstIterator icend = d_ptr->m_itemToIndex.constEnd(); - for (QMap::ConstIterator it = d_ptr->m_itemToIndex.constBegin(); it != icend; ++it) - delete it.key(); - delete d_ptr; -} - -/*! - \reimp -*/ -void QtGroupBoxPropertyBrowser::itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem) -{ - d_ptr->propertyInserted(item, afterItem); -} - -/*! - \reimp -*/ -void QtGroupBoxPropertyBrowser::itemRemoved(QtBrowserItem *item) -{ - d_ptr->propertyRemoved(item); -} - -/*! - \reimp -*/ -void QtGroupBoxPropertyBrowser::itemChanged(QtBrowserItem *item) -{ - d_ptr->propertyChanged(item); -} - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#include "moc_qtgroupboxpropertybrowser.cpp" diff --git a/src/qtpropertybrowser/src/qtgroupboxpropertybrowser.h b/src/qtpropertybrowser/src/qtgroupboxpropertybrowser.h deleted file mode 100644 index 78b4a9b101..0000000000 --- a/src/qtpropertybrowser/src/qtgroupboxpropertybrowser.h +++ /dev/null @@ -1,80 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QTGROUPBOXPROPERTYBROWSER_H -#define QTGROUPBOXPROPERTYBROWSER_H - -#include "qtpropertybrowser.h" - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QtGroupBoxPropertyBrowserPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtGroupBoxPropertyBrowser : public QtAbstractPropertyBrowser -{ - Q_OBJECT -public: - - QtGroupBoxPropertyBrowser(QWidget *parent = 0); - ~QtGroupBoxPropertyBrowser(); - -protected: - virtual void itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem); - virtual void itemRemoved(QtBrowserItem *item); - virtual void itemChanged(QtBrowserItem *item); - -private: - - QtGroupBoxPropertyBrowserPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtGroupBoxPropertyBrowser) - Q_DISABLE_COPY(QtGroupBoxPropertyBrowser) - Q_PRIVATE_SLOT(d_func(), void slotUpdate()) - Q_PRIVATE_SLOT(d_func(), void slotEditorDestroyed()) - -}; - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#endif diff --git a/src/qtpropertybrowser/src/qtpropertybrowser.cpp b/src/qtpropertybrowser/src/qtpropertybrowser.cpp deleted file mode 100644 index 8bc0ee397a..0000000000 --- a/src/qtpropertybrowser/src/qtpropertybrowser.cpp +++ /dev/null @@ -1,2079 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qtpropertybrowser.h" -#include -#include -#include -#include - -#if defined(Q_CC_MSVC) -# pragma warning(disable: 4786) /* MS VS 6: truncating debug info after 255 characters */ -#endif - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QtPropertyPrivate -{ -public: - explicit QtPropertyPrivate(QtAbstractPropertyManager *manager) - : m_enabled(true), - m_modified(false), - m_manager(manager) {} - QtProperty *q_ptr; - - QSet m_parentItems; - QList m_subItems; - - QString m_toolTip; - QString m_statusTip; - QString m_whatsThis; - QString m_name; - QColor m_nameColor; - QColor m_valueColor; - bool m_enabled; - bool m_modified; - - QtAbstractPropertyManager * const m_manager; -}; - -class QtAbstractPropertyManagerPrivate -{ - QtAbstractPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtAbstractPropertyManager) -public: - void propertyDestroyed(QtProperty *property); - void propertyChanged(QtProperty *property) const; - void propertyRemoved(QtProperty *property, - QtProperty *parentProperty) const; - void propertyInserted(QtProperty *property, QtProperty *parentProperty, - QtProperty *afterProperty) const; - - QSet m_properties; -}; - -/*! - \class QtProperty - - \brief The QtProperty class encapsulates an instance of a property. - - Properties are created by objects of QtAbstractPropertyManager - subclasses; a manager can create properties of a given type, and - is used in conjunction with the QtAbstractPropertyBrowser class. A - property is always owned by the manager that created it, which can - be retrieved using the propertyManager() function. - - QtProperty contains the most common property attributes, and - provides functions for retrieving as well as setting their values: - - \table - \header \o Getter \o Setter - \row - \o propertyName() \o setPropertyName() - \row - \o statusTip() \o setStatusTip() - \row - \o toolTip() \o setToolTip() - \row - \o whatsThis() \o setWhatsThis() - \row - \o isEnabled() \o setEnabled() - \row - \o isModified() \o setModified() - \row - \o valueText() \o Nop - \row - \o valueIcon() \o Nop - \endtable - - It is also possible to nest properties: QtProperty provides the - addSubProperty(), insertSubProperty() and removeSubProperty() functions to - manipulate the set of subproperties. Use the subProperties() - function to retrieve a property's current set of subproperties. - Note that nested properties are not owned by the parent property, - i.e. each subproperty is owned by the manager that created it. - - \sa QtAbstractPropertyManager, QtBrowserItem -*/ - -/*! - Creates a property with the given \a manager. - - This constructor is only useful when creating a custom QtProperty - subclass (e.g. QtVariantProperty). To create a regular QtProperty - object, use the QtAbstractPropertyManager::addProperty() - function instead. - - \sa QtAbstractPropertyManager::addProperty() -*/ -QtProperty::QtProperty(QtAbstractPropertyManager *manager) -{ - d_ptr = new QtPropertyPrivate(manager); - d_ptr->q_ptr = this; -} - -/*! - Destroys this property. - - Note that subproperties are detached but not destroyed, i.e. they - can still be used in another context. - - \sa QtAbstractPropertyManager::clear() - -*/ -QtProperty::~QtProperty() -{ - QSetIterator itParent(d_ptr->m_parentItems); - while (itParent.hasNext()) { - QtProperty *property = itParent.next(); - property->d_ptr->m_manager->d_ptr->propertyRemoved(this, property); - } - - d_ptr->m_manager->d_ptr->propertyDestroyed(this); - - QListIterator itChild(d_ptr->m_subItems); - while (itChild.hasNext()) { - QtProperty *property = itChild.next(); - property->d_ptr->m_parentItems.remove(this); - } - - itParent.toFront(); - while (itParent.hasNext()) { - QtProperty *property = itParent.next(); - property->d_ptr->m_subItems.removeAll(this); - } - delete d_ptr; -} - -/*! - Returns the set of subproperties. - - Note that subproperties are not owned by \e this property, but by - the manager that created them. - - \sa insertSubProperty(), removeSubProperty() -*/ -QList QtProperty::subProperties() const -{ - return d_ptr->m_subItems; -} - -/*! - Returns a pointer to the manager that owns this property. -*/ -QtAbstractPropertyManager *QtProperty::propertyManager() const -{ - return d_ptr->m_manager; -} - -/*! - Returns the property's tool tip. - - \sa setToolTip() -*/ -QString QtProperty::toolTip() const -{ - return d_ptr->m_toolTip; -} - -/*! - Returns the property's status tip. - - \sa setStatusTip() -*/ -QString QtProperty::statusTip() const -{ - return d_ptr->m_statusTip; -} - -/*! - Returns the property's "What's This" help text. - - \sa setWhatsThis() -*/ -QString QtProperty::whatsThis() const -{ - return d_ptr->m_whatsThis; -} - -/*! - Returns the property's name. - - \sa setPropertyName() -*/ -QString QtProperty::propertyName() const -{ - return d_ptr->m_name; -} - -/*! - Returns the property's name color. - - \sa setNameColor() -*/ -QColor QtProperty::nameColor() const -{ - return d_ptr->m_nameColor; -} - -/*! - Returns the property's value color. - - \sa setValueColor() -*/ -QColor QtProperty::valueColor() const -{ - return d_ptr->m_valueColor; -} - -/*! - Returns whether the property is enabled. - - \sa setEnabled() -*/ -bool QtProperty::isEnabled() const -{ - return d_ptr->m_enabled; -} - -/*! - Returns whether the property is modified. - - \sa setModified() -*/ -bool QtProperty::isModified() const -{ - return d_ptr->m_modified; -} - -/*! - Returns whether the property has a value. - - \sa QtAbstractPropertyManager::hasValue() -*/ -bool QtProperty::hasValue() const -{ - return d_ptr->m_manager->hasValue(this); -} - -/*! - Returns an icon representing the current state of this property. - - If the given property type can not generate such an icon, this - function returns an invalid icon. - - \sa QtAbstractPropertyManager::valueIcon() -*/ -QIcon QtProperty::valueIcon() const -{ - return d_ptr->m_manager->valueIcon(this); -} - -/*! - Returns a string representing the current state of this property. - - If the given property type can not generate such a string, this - function returns an empty string. - - \sa QtAbstractPropertyManager::valueText() -*/ -QString QtProperty::valueText() const -{ - return d_ptr->m_manager->valueText(this); -} - -/*! - Returns the display text according to the echo-mode set on the editor. - - When the editor is a QLineEdit, this will return a string equal to what - is displayed. - - \sa QtAbstractPropertyManager::valueText() -*/ -QString QtProperty::displayText() const -{ - return d_ptr->m_manager->displayText(this); -} - -/*! - Sets the property's tool tip to the given \a text. - - \sa toolTip() -*/ -void QtProperty::setToolTip(const QString &text) -{ - if (d_ptr->m_toolTip == text) - return; - - d_ptr->m_toolTip = text; - propertyChanged(); -} - -/*! - Sets the property's status tip to the given \a text. - - \sa statusTip() -*/ -void QtProperty::setStatusTip(const QString &text) -{ - if (d_ptr->m_statusTip == text) - return; - - d_ptr->m_statusTip = text; - propertyChanged(); -} - -/*! - Sets the property's "What's This" help text to the given \a text. - - \sa whatsThis() -*/ -void QtProperty::setWhatsThis(const QString &text) -{ - if (d_ptr->m_whatsThis == text) - return; - - d_ptr->m_whatsThis = text; - propertyChanged(); -} - -/*! - \fn void QtProperty::setPropertyName(const QString &name) - - Sets the property's name to the given \a name. - - \sa propertyName() -*/ -void QtProperty::setPropertyName(const QString &text) -{ - if (d_ptr->m_name == text) - return; - - d_ptr->m_name = text; - propertyChanged(); -} - -/*! - \fn void QtProperty::setNameColor(const QColor &color) - - Sets the property's name color to the given \a color. - - \sa nameColor() -*/ -void QtProperty::setNameColor(const QColor &color) -{ - if (d_ptr->m_nameColor == color) - return; - - d_ptr->m_nameColor = color; - propertyChanged(); -} - -/*! - \fn void QtProperty::setValueColor(const QColor &color) - - Sets the property's value color to the given \a color. - - \sa valueColor() -*/ -void QtProperty::setValueColor(const QColor &color) -{ - if (d_ptr->m_valueColor == color) - return; - - d_ptr->m_valueColor = color; - propertyChanged(); -} - -/*! - Enables or disables the property according to the passed \a enable value. - - \sa isEnabled() -*/ -void QtProperty::setEnabled(bool enable) -{ - if (d_ptr->m_enabled == enable) - return; - - d_ptr->m_enabled = enable; - propertyChanged(); -} - -/*! - Sets the property's modified state according to the passed \a modified value. - - \sa isModified() -*/ -void QtProperty::setModified(bool modified) -{ - if (d_ptr->m_modified == modified) - return; - - d_ptr->m_modified = modified; - propertyChanged(); -} - -/*! - Appends the given \a property to this property's subproperties. - - If the given \a property already is added, this function does - nothing. - - \sa insertSubProperty(), removeSubProperty() -*/ -void QtProperty::addSubProperty(QtProperty *property) -{ - QtProperty *after = 0; - if (d_ptr->m_subItems.count() > 0) - after = d_ptr->m_subItems.last(); - insertSubProperty(property, after); -} - -/*! - \fn void QtProperty::insertSubProperty(QtProperty *property, QtProperty *precedingProperty) - - Inserts the given \a property after the specified \a - precedingProperty into this property's list of subproperties. If - \a precedingProperty is 0, the specified \a property is inserted - at the beginning of the list. - - If the given \a property already is inserted, this function does - nothing. - - \sa addSubProperty(), removeSubProperty() -*/ -void QtProperty::insertSubProperty(QtProperty *property, - QtProperty *afterProperty) -{ - if (!property) - return; - - if (property == this) - return; - - // traverse all children of item. if this item is a child of item then cannot add. - QList pendingList = property->subProperties(); - QMap visited; - while (!pendingList.isEmpty()) { - QtProperty *i = pendingList.first(); - if (i == this) - return; - pendingList.removeFirst(); - if (visited.contains(i)) - continue; - visited[i] = true; - pendingList += i->subProperties(); - } - - pendingList = subProperties(); - int pos = 0; - int newPos = 0; - QtProperty *properAfterProperty = 0; - while (pos < pendingList.count()) { - QtProperty *i = pendingList.at(pos); - if (i == property) - return; // if item is already inserted in this item then cannot add. - if (i == afterProperty) { - newPos = pos + 1; - properAfterProperty = afterProperty; - } - pos++; - } - - d_ptr->m_subItems.insert(newPos, property); - property->d_ptr->m_parentItems.insert(this); - - d_ptr->m_manager->d_ptr->propertyInserted(property, this, properAfterProperty); -} - -/*! - Removes the given \a property from the list of subproperties - without deleting it. - - \sa addSubProperty(), insertSubProperty() -*/ -void QtProperty::removeSubProperty(QtProperty *property) -{ - if (!property) - return; - - d_ptr->m_manager->d_ptr->propertyRemoved(property, this); - - QList pendingList = subProperties(); - int pos = 0; - while (pos < pendingList.count()) { - if (pendingList.at(pos) == property) { - d_ptr->m_subItems.removeAt(pos); - property->d_ptr->m_parentItems.remove(this); - - return; - } - pos++; - } -} - -/*! - \internal -*/ -void QtProperty::propertyChanged() -{ - d_ptr->m_manager->d_ptr->propertyChanged(this); -} - -//////////////////////////////// - -void QtAbstractPropertyManagerPrivate::propertyDestroyed(QtProperty *property) -{ - if (m_properties.contains(property)) { - emit q_ptr->propertyDestroyed(property); - q_ptr->uninitializeProperty(property); - m_properties.remove(property); - } -} - -void QtAbstractPropertyManagerPrivate::propertyChanged(QtProperty *property) const -{ - emit q_ptr->propertyChanged(property); -} - -void QtAbstractPropertyManagerPrivate::propertyRemoved(QtProperty *property, - QtProperty *parentProperty) const -{ - emit q_ptr->propertyRemoved(property, parentProperty); -} - -void QtAbstractPropertyManagerPrivate::propertyInserted(QtProperty *property, - QtProperty *parentProperty, QtProperty *afterProperty) const -{ - emit q_ptr->propertyInserted(property, parentProperty, afterProperty); -} - -/*! - \class QtAbstractPropertyManager - - \brief The QtAbstractPropertyManager provides an interface for - property managers. - - A manager can create and manage properties of a given type, and is - used in conjunction with the QtAbstractPropertyBrowser class. - - When using a property browser widget, the properties are created - and managed by implementations of the QtAbstractPropertyManager - class. To ensure that the properties' values will be displayed - using suitable editing widgets, the managers are associated with - objects of QtAbstractEditorFactory subclasses. The property browser - will use these associations to determine which factories it should - use to create the preferred editing widgets. - - The QtAbstractPropertyManager class provides common functionality - like creating a property using the addProperty() function, and - retrieving the properties created by the manager using the - properties() function. The class also provides signals that are - emitted when the manager's properties change: propertyInserted(), - propertyRemoved(), propertyChanged() and propertyDestroyed(). - - QtAbstractPropertyManager subclasses are supposed to provide their - own type specific API. Note that several ready-made - implementations are available: - - \list - \o QtBoolPropertyManager - \o QtColorPropertyManager - \o QtDatePropertyManager - \o QtDateTimePropertyManager - \o QtDoublePropertyManager - \o QtEnumPropertyManager - \o QtFlagPropertyManager - \o QtFontPropertyManager - \o QtGroupPropertyManager - \o QtIntPropertyManager - \o QtPointPropertyManager - \o QtRectPropertyManager - \o QtSizePropertyManager - \o QtStringPropertyManager - \o QtTimePropertyManager - \o QtVariantPropertyManager - \endlist - - \sa QtAbstractEditorFactoryBase, QtAbstractPropertyBrowser, QtProperty -*/ - -/*! - \fn void QtAbstractPropertyManager::propertyInserted(QtProperty *newProperty, - QtProperty *parentProperty, QtProperty *precedingProperty) - - This signal is emitted when a new subproperty is inserted into an - existing property, passing pointers to the \a newProperty, \a - parentProperty and \a precedingProperty as parameters. - - If \a precedingProperty is 0, the \a newProperty was inserted at - the beginning of the \a parentProperty's subproperties list. - - Note that signal is emitted only if the \a parentProperty is created - by this manager. - - \sa QtAbstractPropertyBrowser::itemInserted() -*/ - -/*! - \fn void QtAbstractPropertyManager::propertyChanged(QtProperty *property) - - This signal is emitted whenever a property's data changes, passing - a pointer to the \a property as parameter. - - Note that signal is only emitted for properties that are created by - this manager. - - \sa QtAbstractPropertyBrowser::itemChanged() -*/ - -/*! - \fn void QtAbstractPropertyManager::propertyRemoved(QtProperty *property, QtProperty *parent) - - This signal is emitted when a subproperty is removed, passing - pointers to the removed \a property and the \a parent property as - parameters. - - Note that signal is emitted only when the \a parent property is - created by this manager. - - \sa QtAbstractPropertyBrowser::itemRemoved() -*/ - -/*! - \fn void QtAbstractPropertyManager::propertyDestroyed(QtProperty *property) - - This signal is emitted when the specified \a property is about to - be destroyed. - - Note that signal is only emitted for properties that are created - by this manager. - - \sa clear(), uninitializeProperty() -*/ - -/*! - \fn void QtAbstractPropertyBrowser::currentItemChanged(QtBrowserItem *current) - - This signal is emitted when the current item changes. The current item is specified by \a current. - - \sa QtAbstractPropertyBrowser::setCurrentItem() -*/ - -/*! - Creates an abstract property manager with the given \a parent. -*/ -QtAbstractPropertyManager::QtAbstractPropertyManager(QObject *parent) - : QObject(parent) -{ - d_ptr = new QtAbstractPropertyManagerPrivate; - d_ptr->q_ptr = this; - -} - -/*! - Destroys the manager. All properties created by the manager are - destroyed. -*/ -QtAbstractPropertyManager::~QtAbstractPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Destroys all the properties that this manager has created. - - \sa propertyDestroyed(), uninitializeProperty() -*/ -void QtAbstractPropertyManager::clear() const -{ - while (!properties().isEmpty()) { - QSetIterator itProperty(properties()); - QtProperty *prop = itProperty.next(); - delete prop; - } -} - -/*! - Returns the set of properties created by this manager. - - \sa addProperty() -*/ -QSet QtAbstractPropertyManager::properties() const -{ - return d_ptr->m_properties; -} - -/*! - Returns whether the given \a property has a value. - - The default implementation of this function returns true. - - \sa QtProperty::hasValue() -*/ -bool QtAbstractPropertyManager::hasValue(const QtProperty *property) const -{ - Q_UNUSED(property) - return true; -} - -/*! - Returns an icon representing the current state of the given \a - property. - - The default implementation of this function returns an invalid - icon. - - \sa QtProperty::valueIcon() -*/ -QIcon QtAbstractPropertyManager::valueIcon(const QtProperty *property) const -{ - Q_UNUSED(property) - return QIcon(); -} - -/*! - Returns a string representing the current state of the given \a - property. - - The default implementation of this function returns an empty - string. - - \sa QtProperty::valueText() -*/ -QString QtAbstractPropertyManager::valueText(const QtProperty *property) const -{ - Q_UNUSED(property) - return QString(); -} - -/*! - Returns a string representing the current state of the given \a - property. - - The default implementation of this function returns an empty - string. - - \sa QtProperty::valueText() -*/ -QString QtAbstractPropertyManager::displayText(const QtProperty *property) const -{ - Q_UNUSED(property) - return QString(); -} - -/*! - Returns the echo mode representing the current state of the given \a - property. - - The default implementation of this function returns QLineEdit::Normal. - - \sa QtProperty::valueText() -*/ -EchoMode QtAbstractPropertyManager::echoMode(const QtProperty *property) const -{ - Q_UNUSED(property) - return QLineEdit::Normal; -} - -/*! - Creates a property with the given \a name which then is owned by this manager. - - Internally, this function calls the createProperty() and - initializeProperty() functions. - - \sa initializeProperty(), properties() -*/ -QtProperty *QtAbstractPropertyManager::addProperty(const QString &name) -{ - QtProperty *property = createProperty(); - if (property) { - property->setPropertyName(name); - d_ptr->m_properties.insert(property); - initializeProperty(property); - } - return property; -} - -/*! - Creates a property. - - The base implementation produce QtProperty instances; Reimplement - this function to make this manager produce objects of a QtProperty - subclass. - - \sa addProperty(), initializeProperty() -*/ -QtProperty *QtAbstractPropertyManager::createProperty() -{ - return new QtProperty(this); -} - -/*! - \fn void QtAbstractPropertyManager::initializeProperty(QtProperty *property) = 0 - - This function is called whenever a new valid property pointer has - been created, passing the pointer as parameter. - - The purpose is to let the manager know that the \a property has - been created so that it can provide additional attributes for the - new property, e.g. QtIntPropertyManager adds \l - {QtIntPropertyManager::value()}{value}, \l - {QtIntPropertyManager::minimum()}{minimum} and \l - {QtIntPropertyManager::maximum()}{maximum} attributes. Since each manager - subclass adds type specific attributes, this function is pure - virtual and must be reimplemented when deriving from the - QtAbstractPropertyManager class. - - \sa addProperty(), createProperty() -*/ - -/*! - This function is called just before the specified \a property is destroyed. - - The purpose is to let the property manager know that the \a - property is being destroyed so that it can remove the property's - additional attributes. - - \sa clear(), propertyDestroyed() -*/ -void QtAbstractPropertyManager::uninitializeProperty(QtProperty *property) -{ - Q_UNUSED(property) -} - -//////////////////////////////////// - -/*! - \class QtAbstractEditorFactoryBase - - \brief The QtAbstractEditorFactoryBase provides an interface for - editor factories. - - An editor factory is a class that is able to create an editing - widget of a specified type (e.g. line edits or comboboxes) for a - given QtProperty object, and it is used in conjunction with the - QtAbstractPropertyManager and QtAbstractPropertyBrowser classes. - - When using a property browser widget, the properties are created - and managed by implementations of the QtAbstractPropertyManager - class. To ensure that the properties' values will be displayed - using suitable editing widgets, the managers are associated with - objects of QtAbstractEditorFactory subclasses. The property browser - will use these associations to determine which factories it should - use to create the preferred editing widgets. - - Typically, an editor factory is created by subclassing the - QtAbstractEditorFactory template class which inherits - QtAbstractEditorFactoryBase. But note that several ready-made - implementations are available: - - \list - \o QtCheckBoxFactory - \o QtDateEditFactory - \o QtDateTimeEditFactory - \o QtDoubleSpinBoxFactory - \o QtEnumEditorFactory - \o QtLineEditFactory - \o QtScrollBarFactory - \o QtSliderFactory - \o QtSpinBoxFactory - \o QtTimeEditFactory - \o QtVariantEditorFactory - \endlist - - \sa QtAbstractPropertyManager, QtAbstractPropertyBrowser -*/ - -/*! - \fn virtual QWidget *QtAbstractEditorFactoryBase::createEditor(QtProperty *property, - QWidget *parent) = 0 - - Creates an editing widget (with the given \a parent) for the given - \a property. - - This function is reimplemented in QtAbstractEditorFactory template class - which also provides a pure virtual convenience overload of this - function enabling access to the property's manager. - - \sa QtAbstractEditorFactory::createEditor() -*/ - -/*! - \fn QtAbstractEditorFactoryBase::QtAbstractEditorFactoryBase(QObject *parent = 0) - - Creates an abstract editor factory with the given \a parent. -*/ - -/*! - \fn virtual void QtAbstractEditorFactoryBase::breakConnection(QtAbstractPropertyManager *manager) = 0 - - \internal - - Detaches property manager from factory. - This method is reimplemented in QtAbstractEditorFactory template subclass. - You don't need to reimplement it in your subclasses. Instead implement more convenient - QtAbstractEditorFactory::disconnectPropertyManager() which gives you access to particular manager subclass. -*/ - -/*! - \fn virtual void QtAbstractEditorFactoryBase::managerDestroyed(QObject *manager) = 0 - - \internal - - This method is called when property manager is being destroyed. - Basically it notifies factory not to produce editors for properties owned by \a manager. - You don't need to reimplement it in your subclass. This method is implemented in - QtAbstractEditorFactory template subclass. -*/ - -/*! - \class QtAbstractEditorFactory - - \brief The QtAbstractEditorFactory is the base template class for editor - factories. - - An editor factory is a class that is able to create an editing - widget of a specified type (e.g. line edits or comboboxes) for a - given QtProperty object, and it is used in conjunction with the - QtAbstractPropertyManager and QtAbstractPropertyBrowser classes. - - Note that the QtAbstractEditorFactory functions are using the - PropertyManager template argument class which can be any - QtAbstractPropertyManager subclass. For example: - - \code - QtSpinBoxFactory *factory; - QSet managers = factory->propertyManagers(); - \endcode - - Note that QtSpinBoxFactory by definition creates editing widgets - \e only for properties created by QtIntPropertyManager. - - When using a property browser widget, the properties are created - and managed by implementations of the QtAbstractPropertyManager - class. To ensure that the properties' values will be displayed - using suitable editing widgets, the managers are associated with - objects of QtAbstractEditorFactory subclasses. The property browser will - use these associations to determine which factories it should use - to create the preferred editing widgets. - - A QtAbstractEditorFactory object is capable of producing editors for - several property managers at the same time. To create an - association between this factory and a given manager, use the - addPropertyManager() function. Use the removePropertyManager() function to make - this factory stop producing editors for a given property - manager. Use the propertyManagers() function to retrieve the set of - managers currently associated with this factory. - - Several ready-made implementations of the QtAbstractEditorFactory class - are available: - - \list - \o QtCheckBoxFactory - \o QtDateEditFactory - \o QtDateTimeEditFactory - \o QtDoubleSpinBoxFactory - \o QtEnumEditorFactory - \o QtLineEditFactory - \o QtScrollBarFactory - \o QtSliderFactory - \o QtSpinBoxFactory - \o QtTimeEditFactory - \o QtVariantEditorFactory - \endlist - - When deriving from the QtAbstractEditorFactory class, several pure virtual - functions must be implemented: the connectPropertyManager() function is - used by the factory to connect to the given manager's signals, the - createEditor() function is supposed to create an editor for the - given property controlled by the given manager, and finally the - disconnectPropertyManager() function is used by the factory to disconnect - from the specified manager's signals. - - \sa QtAbstractEditorFactoryBase, QtAbstractPropertyManager -*/ - -/*! - \fn QtAbstractEditorFactory::QtAbstractEditorFactory(QObject *parent = 0) - - Creates an editor factory with the given \a parent. - - \sa addPropertyManager() -*/ - -/*! - \fn QWidget *QtAbstractEditorFactory::createEditor(QtProperty *property, QWidget *parent) - - Creates an editing widget (with the given \a parent) for the given - \a property. -*/ - -/*! - \fn void QtAbstractEditorFactory::addPropertyManager(PropertyManager *manager) - - Adds the given \a manager to this factory's set of managers, - making this factory produce editing widgets for properties created - by the given manager. - - The PropertyManager type is a template argument class, and represents the chosen - QtAbstractPropertyManager subclass. - - \sa propertyManagers(), removePropertyManager() -*/ - -/*! - \fn void QtAbstractEditorFactory::removePropertyManager(PropertyManager *manager) - - Removes the given \a manager from this factory's set of - managers. The PropertyManager type is a template argument class, and may be - any QtAbstractPropertyManager subclass. - - \sa propertyManagers(), addPropertyManager() -*/ - -/*! - \fn virtual void QtAbstractEditorFactory::connectPropertyManager(PropertyManager *manager) = 0 - - Connects this factory to the given \a manager's signals. The - PropertyManager type is a template argument class, and represents - the chosen QtAbstractPropertyManager subclass. - - This function is used internally by the addPropertyManager() function, and - makes it possible to update an editing widget when the associated - property's data changes. This is typically done in custom slots - responding to the signals emitted by the property's manager, - e.g. QtIntPropertyManager::valueChanged() and - QtIntPropertyManager::rangeChanged(). - - \sa propertyManagers(), disconnectPropertyManager() -*/ - -/*! - \fn virtual QWidget *QtAbstractEditorFactory::createEditor(PropertyManager *manager, QtProperty *property, - QWidget *parent) = 0 - - Creates an editing widget with the given \a parent for the - specified \a property created by the given \a manager. The - PropertyManager type is a template argument class, and represents - the chosen QtAbstractPropertyManager subclass. - - This function must be implemented in derived classes: It is - recommended to store a pointer to the widget and map it to the - given \a property, since the widget must be updated whenever the - associated property's data changes. This is typically done in - custom slots responding to the signals emitted by the property's - manager, e.g. QtIntPropertyManager::valueChanged() and - QtIntPropertyManager::rangeChanged(). - - \sa connectPropertyManager() -*/ - -/*! - \fn virtual void QtAbstractEditorFactory::disconnectPropertyManager(PropertyManager *manager) = 0 - - Disconnects this factory from the given \a manager's signals. The - PropertyManager type is a template argument class, and represents - the chosen QtAbstractPropertyManager subclass. - - This function is used internally by the removePropertyManager() function. - - \sa propertyManagers(), connectPropertyManager() -*/ - -/*! - \fn QSet QtAbstractEditorFactory::propertyManagers() const - - Returns the factory's set of associated managers. The - PropertyManager type is a template argument class, and represents - the chosen QtAbstractPropertyManager subclass. - - \sa addPropertyManager(), removePropertyManager() -*/ - -/*! - \fn PropertyManager *QtAbstractEditorFactory::propertyManager(QtProperty *property) const - - Returns the property manager for the given \a property, or 0 if - the given \a property doesn't belong to any of this factory's - registered managers. - - The PropertyManager type is a template argument class, and represents the chosen - QtAbstractPropertyManager subclass. - - \sa propertyManagers() -*/ - -/*! - \fn virtual void QtAbstractEditorFactory::managerDestroyed(QObject *manager) - - \internal - \reimp -*/ - -//////////////////////////////////// -class QtBrowserItemPrivate -{ -public: - QtBrowserItemPrivate(QtAbstractPropertyBrowser *browser, QtProperty *property, QtBrowserItem *parent) - : m_browser(browser), m_property(property), m_parent(parent), q_ptr(0) {} - - void addChild(QtBrowserItem *index, QtBrowserItem *after); - void removeChild(QtBrowserItem *index); - - QtAbstractPropertyBrowser * const m_browser; - QtProperty *m_property; - QtBrowserItem *m_parent; - - QtBrowserItem *q_ptr; - - QList m_children; - -}; - -void QtBrowserItemPrivate::addChild(QtBrowserItem *index, QtBrowserItem *after) -{ - if (m_children.contains(index)) - return; - int idx = m_children.indexOf(after) + 1; // we insert after returned idx, if it was -1 then we set idx to 0; - m_children.insert(idx, index); -} - -void QtBrowserItemPrivate::removeChild(QtBrowserItem *index) -{ - m_children.removeAll(index); -} - - -/*! - \class QtBrowserItem - - \brief The QtBrowserItem class represents a property in - a property browser instance. - - Browser items are created whenever a QtProperty is inserted to the - property browser. A QtBrowserItem uniquely identifies a - browser's item. Thus, if the same QtProperty is inserted multiple - times, each occurrence gets its own unique QtBrowserItem. The - items are owned by QtAbstractPropertyBrowser and automatically - deleted when they are removed from the browser. - - You can traverse a browser's properties by calling parent() and - children(). The property and the browser associated with an item - are available as property() and browser(). - - \sa QtAbstractPropertyBrowser, QtProperty -*/ - -/*! - Returns the property which is accosiated with this item. Note that - several items can be associated with the same property instance in - the same property browser. - - \sa QtAbstractPropertyBrowser::items() -*/ - -QtProperty *QtBrowserItem::property() const -{ - return d_ptr->m_property; -} - -/*! - Returns the parent item of \e this item. Returns 0 if \e this item - is associated with top-level property in item's property browser. - - \sa children() -*/ - -QtBrowserItem *QtBrowserItem::parent() const -{ - return d_ptr->m_parent; -} - -/*! - Returns the children items of \e this item. The properties - reproduced from children items are always the same as - reproduced from associated property' children, for example: - - \code - QtBrowserItem *item; - QList childrenItems = item->children(); - - QList childrenProperties = item->property()->subProperties(); - \endcode - - The \e childrenItems list represents the same list as \e childrenProperties. -*/ - -QList QtBrowserItem::children() const -{ - return d_ptr->m_children; -} - -/*! - Returns the property browser which owns \e this item. -*/ - -QtAbstractPropertyBrowser *QtBrowserItem::browser() const -{ - return d_ptr->m_browser; -} - -QtBrowserItem::QtBrowserItem(QtAbstractPropertyBrowser *browser, QtProperty *property, QtBrowserItem *parent) -{ - d_ptr = new QtBrowserItemPrivate(browser, property, parent); - d_ptr->q_ptr = this; -} - -QtBrowserItem::~QtBrowserItem() -{ - delete d_ptr; -} - - -//////////////////////////////////// - -typedef QMap > Map1; -typedef QMap > > Map2; -Q_GLOBAL_STATIC(Map1, m_viewToManagerToFactory) -Q_GLOBAL_STATIC(Map2, m_managerToFactoryToViews) - -class QtAbstractPropertyBrowserPrivate -{ - QtAbstractPropertyBrowser *q_ptr; - Q_DECLARE_PUBLIC(QtAbstractPropertyBrowser) -public: - QtAbstractPropertyBrowserPrivate(); - - void insertSubTree(QtProperty *property, - QtProperty *parentProperty); - void removeSubTree(QtProperty *property, - QtProperty *parentProperty); - void createBrowserIndexes(QtProperty *property, QtProperty *parentProperty, QtProperty *afterProperty); - void removeBrowserIndexes(QtProperty *property, QtProperty *parentProperty); - QtBrowserItem *createBrowserIndex(QtProperty *property, QtBrowserItem *parentIndex, QtBrowserItem *afterIndex); - void removeBrowserIndex(QtBrowserItem *index); - void clearIndex(QtBrowserItem *index); - - void slotPropertyInserted(QtProperty *property, - QtProperty *parentProperty, QtProperty *afterProperty); - void slotPropertyRemoved(QtProperty *property, QtProperty *parentProperty); - void slotPropertyDestroyed(QtProperty *property); - void slotPropertyDataChanged(QtProperty *property); - - QList m_subItems; - QMap > m_managerToProperties; - QMap > m_propertyToParents; - - QMap m_topLevelPropertyToIndex; - QList m_topLevelIndexes; - QMap > m_propertyToIndexes; - - QtBrowserItem *m_currentItem; -}; - -QtAbstractPropertyBrowserPrivate::QtAbstractPropertyBrowserPrivate() : - m_currentItem(0) -{ -} - -void QtAbstractPropertyBrowserPrivate::insertSubTree(QtProperty *property, - QtProperty *parentProperty) -{ - if (m_propertyToParents.contains(property)) { - // property was already inserted, so its manager is connected - // and all its children are inserted and theirs managers are connected - // we just register new parent (parent has to be new). - m_propertyToParents[property].append(parentProperty); - // don't need to update m_managerToProperties map since - // m_managerToProperties[manager] already contains property. - return; - } - QtAbstractPropertyManager *manager = property->propertyManager(); - if (m_managerToProperties[manager].isEmpty()) { - // connect manager's signals - q_ptr->connect(manager, SIGNAL(propertyInserted(QtProperty *, - QtProperty *, QtProperty *)), - q_ptr, SLOT(slotPropertyInserted(QtProperty *, - QtProperty *, QtProperty *))); - q_ptr->connect(manager, SIGNAL(propertyRemoved(QtProperty *, - QtProperty *)), - q_ptr, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - q_ptr->connect(manager, SIGNAL(propertyDestroyed(QtProperty *)), - q_ptr, SLOT(slotPropertyDestroyed(QtProperty *))); - q_ptr->connect(manager, SIGNAL(propertyChanged(QtProperty *)), - q_ptr, SLOT(slotPropertyDataChanged(QtProperty *))); - } - m_managerToProperties[manager].append(property); - m_propertyToParents[property].append(parentProperty); - - QList subList = property->subProperties(); - QListIterator itSub(subList); - while (itSub.hasNext()) { - QtProperty *subProperty = itSub.next(); - insertSubTree(subProperty, property); - } -} - -void QtAbstractPropertyBrowserPrivate::removeSubTree(QtProperty *property, - QtProperty *parentProperty) -{ - if (!m_propertyToParents.contains(property)) { - // ASSERT - return; - } - - m_propertyToParents[property].removeAll(parentProperty); - if (!m_propertyToParents[property].isEmpty()) - return; - - m_propertyToParents.remove(property); - QtAbstractPropertyManager *manager = property->propertyManager(); - m_managerToProperties[manager].removeAll(property); - if (m_managerToProperties[manager].isEmpty()) { - // disconnect manager's signals - q_ptr->disconnect(manager, SIGNAL(propertyInserted(QtProperty *, - QtProperty *, QtProperty *)), - q_ptr, SLOT(slotPropertyInserted(QtProperty *, - QtProperty *, QtProperty *))); - q_ptr->disconnect(manager, SIGNAL(propertyRemoved(QtProperty *, - QtProperty *)), - q_ptr, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - q_ptr->disconnect(manager, SIGNAL(propertyDestroyed(QtProperty *)), - q_ptr, SLOT(slotPropertyDestroyed(QtProperty *))); - q_ptr->disconnect(manager, SIGNAL(propertyChanged(QtProperty *)), - q_ptr, SLOT(slotPropertyDataChanged(QtProperty *))); - - m_managerToProperties.remove(manager); - } - - QList subList = property->subProperties(); - QListIterator itSub(subList); - while (itSub.hasNext()) { - QtProperty *subProperty = itSub.next(); - removeSubTree(subProperty, property); - } -} - -void QtAbstractPropertyBrowserPrivate::createBrowserIndexes(QtProperty *property, QtProperty *parentProperty, QtProperty *afterProperty) -{ - QMap parentToAfter; - if (afterProperty) { - QMap >::ConstIterator it = - m_propertyToIndexes.find(afterProperty); - if (it == m_propertyToIndexes.constEnd()) - return; - - QList indexes = it.value(); - QListIterator itIndex(indexes); - while (itIndex.hasNext()) { - QtBrowserItem *idx = itIndex.next(); - QtBrowserItem *parentIdx = idx->parent(); - if ((parentProperty && parentIdx && parentIdx->property() == parentProperty) || (!parentProperty && !parentIdx)) - parentToAfter[idx->parent()] = idx; - } - } else if (parentProperty) { - QMap >::ConstIterator it = - m_propertyToIndexes.find(parentProperty); - if (it == m_propertyToIndexes.constEnd()) - return; - - QList indexes = it.value(); - QListIterator itIndex(indexes); - while (itIndex.hasNext()) { - QtBrowserItem *idx = itIndex.next(); - parentToAfter[idx] = 0; - } - } else { - parentToAfter[0] = 0; - } - - const QMap::ConstIterator pcend = parentToAfter.constEnd(); - for (QMap::ConstIterator it = parentToAfter.constBegin(); it != pcend; ++it) - createBrowserIndex(property, it.key(), it.value()); -} - -QtBrowserItem *QtAbstractPropertyBrowserPrivate::createBrowserIndex(QtProperty *property, - QtBrowserItem *parentIndex, QtBrowserItem *afterIndex) -{ - QtBrowserItem *newIndex = new QtBrowserItem(q_ptr, property, parentIndex); - if (parentIndex) { - parentIndex->d_ptr->addChild(newIndex, afterIndex); - } else { - m_topLevelPropertyToIndex[property] = newIndex; - m_topLevelIndexes.insert(m_topLevelIndexes.indexOf(afterIndex) + 1, newIndex); - } - m_propertyToIndexes[property].append(newIndex); - - q_ptr->itemInserted(newIndex, afterIndex); - - QList subItems = property->subProperties(); - QListIterator itChild(subItems); - QtBrowserItem *afterChild = 0; - while (itChild.hasNext()) { - QtProperty *child = itChild.next(); - afterChild = createBrowserIndex(child, newIndex, afterChild); - } - return newIndex; -} - -void QtAbstractPropertyBrowserPrivate::removeBrowserIndexes(QtProperty *property, QtProperty *parentProperty) -{ - QList toRemove; - QMap >::ConstIterator it = - m_propertyToIndexes.find(property); - if (it == m_propertyToIndexes.constEnd()) - return; - - QList indexes = it.value(); - QListIterator itIndex(indexes); - while (itIndex.hasNext()) { - QtBrowserItem *idx = itIndex.next(); - QtBrowserItem *parentIdx = idx->parent(); - if ((parentProperty && parentIdx && parentIdx->property() == parentProperty) || (!parentProperty && !parentIdx)) - toRemove.append(idx); - } - - QListIterator itRemove(toRemove); - while (itRemove.hasNext()) { - QtBrowserItem *index = itRemove.next(); - removeBrowserIndex(index); - } -} - -void QtAbstractPropertyBrowserPrivate::removeBrowserIndex(QtBrowserItem *index) -{ - QList children = index->children(); - for (int i = children.count(); i > 0; i--) { - removeBrowserIndex(children.at(i - 1)); - } - - q_ptr->itemRemoved(index); - - if (index->parent()) { - index->parent()->d_ptr->removeChild(index); - } else { - m_topLevelPropertyToIndex.remove(index->property()); - m_topLevelIndexes.removeAll(index); - } - - QtProperty *property = index->property(); - - m_propertyToIndexes[property].removeAll(index); - if (m_propertyToIndexes[property].isEmpty()) - m_propertyToIndexes.remove(property); - - delete index; -} - -void QtAbstractPropertyBrowserPrivate::clearIndex(QtBrowserItem *index) -{ - QList children = index->children(); - QListIterator itChild(children); - while (itChild.hasNext()) { - clearIndex(itChild.next()); - } - delete index; -} - -void QtAbstractPropertyBrowserPrivate::slotPropertyInserted(QtProperty *property, - QtProperty *parentProperty, QtProperty *afterProperty) -{ - if (!m_propertyToParents.contains(parentProperty)) - return; - createBrowserIndexes(property, parentProperty, afterProperty); - insertSubTree(property, parentProperty); - //q_ptr->propertyInserted(property, parentProperty, afterProperty); -} - -void QtAbstractPropertyBrowserPrivate::slotPropertyRemoved(QtProperty *property, - QtProperty *parentProperty) -{ - if (!m_propertyToParents.contains(parentProperty)) - return; - removeSubTree(property, parentProperty); // this line should be probably moved down after propertyRemoved call - //q_ptr->propertyRemoved(property, parentProperty); - removeBrowserIndexes(property, parentProperty); -} - -void QtAbstractPropertyBrowserPrivate::slotPropertyDestroyed(QtProperty *property) -{ - if (!m_subItems.contains(property)) - return; - q_ptr->removeProperty(property); -} - -void QtAbstractPropertyBrowserPrivate::slotPropertyDataChanged(QtProperty *property) -{ - if (!m_propertyToParents.contains(property)) - return; - - QMap >::ConstIterator it = - m_propertyToIndexes.find(property); - if (it == m_propertyToIndexes.constEnd()) - return; - - QList indexes = it.value(); - QListIterator itIndex(indexes); - while (itIndex.hasNext()) { - QtBrowserItem *idx = itIndex.next(); - q_ptr->itemChanged(idx); - } - //q_ptr->propertyChanged(property); -} - -/*! - \class QtAbstractPropertyBrowser - - \brief QtAbstractPropertyBrowser provides a base class for - implementing property browsers. - - A property browser is a widget that enables the user to edit a - given set of properties. Each property is represented by a label - specifying the property's name, and an editing widget (e.g. a line - edit or a combobox) holding its value. A property can have zero or - more subproperties. - - \image qtpropertybrowser.png - - The top level properties can be retrieved using the - properties() function. To traverse each property's - subproperties, use the QtProperty::subProperties() function. In - addition, the set of top level properties can be manipulated using - the addProperty(), insertProperty() and removeProperty() - functions. Note that the QtProperty class provides a corresponding - set of functions making it possible to manipulate the set of - subproperties as well. - - To remove all the properties from the property browser widget, use - the clear() function. This function will clear the editor, but it - will not delete the properties since they can still be used in - other editors. - - The properties themselves are created and managed by - implementations of the QtAbstractPropertyManager class. A manager - can handle (i.e. create and manage) properties of a given type. In - the property browser the managers are associated with - implementations of the QtAbstractEditorFactory: A factory is a - class able to create an editing widget of a specified type. - - When using a property browser widget, managers must be created for - each of the required property types before the properties - themselves can be created. To ensure that the properties' values - will be displayed using suitable editing widgets, the managers - must be associated with objects of the preferred factory - implementations using the setFactoryForManager() function. The - property browser will use these associations to determine which - factory it should use to create the preferred editing widget. - - Note that a factory can be associated with many managers, but a - manager can only be associated with one single factory within the - context of a single property browser. The associations between - managers and factories can at any time be removed using the - unsetFactoryForManager() function. - - Whenever the property data changes or a property is inserted or - removed, the itemChanged(), itemInserted() or - itemRemoved() functions are called, respectively. These - functions must be reimplemented in derived classes in order to - update the property browser widget. Be aware that some property - instances can appear several times in an abstract tree - structure. For example: - - \table 100% - \row - \o - \code - QtProperty *property1, *property2, *property3; - - property2->addSubProperty(property1); - property3->addSubProperty(property2); - - QtAbstractPropertyBrowser *editor; - - editor->addProperty(property1); - editor->addProperty(property2); - editor->addProperty(property3); - \endcode - \o \image qtpropertybrowser-duplicate.png - \endtable - - The addProperty() function returns a QtBrowserItem that uniquely - identifies the created item. - - To make a property editable in the property browser, the - createEditor() function must be called to provide the - property with a suitable editing widget. - - Note that there are two ready-made property browser - implementations: - - \list - \o QtGroupBoxPropertyBrowser - \o QtTreePropertyBrowser - \endlist - - \sa QtAbstractPropertyManager, QtAbstractEditorFactoryBase -*/ - -/*! - \fn void QtAbstractPropertyBrowser::setFactoryForManager(PropertyManager *manager, - QtAbstractEditorFactory *factory) - - Connects the given \a manager to the given \a factory, ensuring - that properties of the \a manager's type will be displayed with an - editing widget suitable for their value. - - For example: - - \code - QtIntPropertyManager *intManager; - QtDoublePropertyManager *doubleManager; - - QtProperty *myInteger = intManager->addProperty(); - QtProperty *myDouble = doubleManager->addProperty(); - - QtSpinBoxFactory *spinBoxFactory; - QtDoubleSpinBoxFactory *doubleSpinBoxFactory; - - QtAbstractPropertyBrowser *editor; - editor->setFactoryForManager(intManager, spinBoxFactory); - editor->setFactoryForManager(doubleManager, doubleSpinBoxFactory); - - editor->addProperty(myInteger); - editor->addProperty(myDouble); - \endcode - - In this example the \c myInteger property's value is displayed - with a QSpinBox widget, while the \c myDouble property's value is - displayed with a QDoubleSpinBox widget. - - Note that a factory can be associated with many managers, but a - manager can only be associated with one single factory. If the - given \a manager already is associated with another factory, the - old association is broken before the new one established. - - This function ensures that the given \a manager and the given \a - factory are compatible, and it automatically calls the - QtAbstractEditorFactory::addPropertyManager() function if necessary. - - \sa unsetFactoryForManager() -*/ - -/*! - \fn virtual void QtAbstractPropertyBrowser::itemInserted(QtBrowserItem *insertedItem, - QtBrowserItem *precedingItem) = 0 - - This function is called to update the widget whenever a property - is inserted or added to the property browser, passing pointers to - the \a insertedItem of property and the specified - \a precedingItem as parameters. - - If \a precedingItem is 0, the \a insertedItem was put at - the beginning of its parent item's list of subproperties. If - the parent of \a insertedItem is 0, the \a insertedItem was added as a top - level property of \e this property browser. - - This function must be reimplemented in derived classes. Note that - if the \a insertedItem's property has subproperties, this - method will be called for those properties as soon as the current call is finished. - - \sa insertProperty(), addProperty() -*/ - -/*! - \fn virtual void QtAbstractPropertyBrowser::itemRemoved(QtBrowserItem *item) = 0 - - This function is called to update the widget whenever a property - is removed from the property browser, passing the pointer to the - \a item of the property as parameters. The passed \a item is - deleted just after this call is finished. - - If the the parent of \a item is 0, the removed \a item was a - top level property in this editor. - - This function must be reimplemented in derived classes. Note that - if the removed \a item's property has subproperties, this - method will be called for those properties just before the current call is started. - - \sa removeProperty() -*/ - -/*! - \fn virtual void QtAbstractPropertyBrowser::itemChanged(QtBrowserItem *item) = 0 - - This function is called whenever a property's data changes, - passing a pointer to the \a item of property as parameter. - - This function must be reimplemented in derived classes in order to - update the property browser widget whenever a property's name, - tool tip, status tip, "what's this" text, value text or value icon - changes. - - Note that if the property browser contains several occurrences of - the same property, this method will be called once for each - occurrence (with a different item each time). - - \sa QtProperty, items() -*/ - -/*! - Creates an abstract property browser with the given \a parent. -*/ -QtAbstractPropertyBrowser::QtAbstractPropertyBrowser(QWidget *parent) - : QWidget(parent) -{ - d_ptr = new QtAbstractPropertyBrowserPrivate; - d_ptr->q_ptr = this; - -} - -/*! - Destroys the property browser, and destroys all the items that were - created by this property browser. - - Note that the properties that were displayed in the editor are not - deleted since they still can be used in other editors. Neither - does the destructor delete the property managers and editor - factories that were used by this property browser widget unless - this widget was their parent. - - \sa QtAbstractPropertyManager::~QtAbstractPropertyManager() -*/ -QtAbstractPropertyBrowser::~QtAbstractPropertyBrowser() -{ - QList indexes = topLevelItems(); - QListIterator itItem(indexes); - while (itItem.hasNext()) - d_ptr->clearIndex(itItem.next()); - delete d_ptr; -} - -/*! - Returns the property browser's list of top level properties. - - To traverse the subproperties, use the QtProperty::subProperties() - function. - - \sa addProperty(), insertProperty(), removeProperty() -*/ -QList QtAbstractPropertyBrowser::properties() const -{ - return d_ptr->m_subItems; -} - -/*! - Returns the property browser's list of all items associated - with the given \a property. - - There is one item per instance of the property in the browser. - - \sa topLevelItem() -*/ - -QList QtAbstractPropertyBrowser::items(QtProperty *property) const -{ - return d_ptr->m_propertyToIndexes.value(property); -} - -/*! - Returns the top-level items associated with the given \a property. - - Returns 0 if \a property wasn't inserted into this property - browser or isn't a top-level one. - - \sa topLevelItems(), items() -*/ - -QtBrowserItem *QtAbstractPropertyBrowser::topLevelItem(QtProperty *property) const -{ - return d_ptr->m_topLevelPropertyToIndex.value(property); -} - -/*! - Returns the list of top-level items. - - \sa topLevelItem() -*/ - -QList QtAbstractPropertyBrowser::topLevelItems() const -{ - return d_ptr->m_topLevelIndexes; -} - -/*! - Removes all the properties from the editor, but does not delete - them since they can still be used in other editors. - - \sa removeProperty(), QtAbstractPropertyManager::clear() -*/ -void QtAbstractPropertyBrowser::clear() -{ - QList subList = properties(); - QListIterator itSub(subList); - itSub.toBack(); - while (itSub.hasPrevious()) { - QtProperty *property = itSub.previous(); - removeProperty(property); - } -} - -/*! - Appends the given \a property (and its subproperties) to the - property browser's list of top level properties. Returns the item - created by property browser which is associated with the \a property. - In order to get all children items created by the property - browser in this call, the returned item should be traversed. - - If the specified \a property is already added, this function does - nothing and returns 0. - - \sa insertProperty(), QtProperty::addSubProperty(), properties() -*/ -QtBrowserItem *QtAbstractPropertyBrowser::addProperty(QtProperty *property) -{ - QtProperty *afterProperty = 0; - if (d_ptr->m_subItems.count() > 0) - afterProperty = d_ptr->m_subItems.last(); - return insertProperty(property, afterProperty); -} - -/*! - \fn QtBrowserItem *QtAbstractPropertyBrowser::insertProperty(QtProperty *property, - QtProperty *afterProperty) - - Inserts the given \a property (and its subproperties) after - the specified \a afterProperty in the browser's list of top - level properties. Returns item created by property browser which - is associated with the \a property. In order to get all children items - created by the property browser in this call returned item should be traversed. - - If the specified \a afterProperty is 0, the given \a property is - inserted at the beginning of the list. If \a property is - already inserted, this function does nothing and returns 0. - - \sa addProperty(), QtProperty::insertSubProperty(), properties() -*/ -QtBrowserItem *QtAbstractPropertyBrowser::insertProperty(QtProperty *property, - QtProperty *afterProperty) -{ - if (!property) - return 0; - - // if item is already inserted in this item then cannot add. - QList pendingList = properties(); - int pos = 0; - int newPos = 0; - while (pos < pendingList.count()) { - QtProperty *prop = pendingList.at(pos); - if (prop == property) - return 0; - if (prop == afterProperty) { - newPos = pos + 1; - } - pos++; - } - d_ptr->createBrowserIndexes(property, 0, afterProperty); - - // traverse inserted subtree and connect to manager's signals - d_ptr->insertSubTree(property, 0); - - d_ptr->m_subItems.insert(newPos, property); - //propertyInserted(property, 0, properAfterProperty); - return topLevelItem(property); -} - -/*! - Removes the specified \a property (and its subproperties) from the - property browser's list of top level properties. All items - that were associated with the given \a property and its children - are deleted. - - Note that the properties are \e not deleted since they can still - be used in other editors. - - \sa clear(), QtProperty::removeSubProperty(), properties() -*/ -void QtAbstractPropertyBrowser::removeProperty(QtProperty *property) -{ - if (!property) - return; - - QList pendingList = properties(); - int pos = 0; - while (pos < pendingList.count()) { - if (pendingList.at(pos) == property) { - d_ptr->m_subItems.removeAt(pos); //perhaps this two lines - d_ptr->removeSubTree(property, 0); //should be moved down after propertyRemoved call. - //propertyRemoved(property, 0); - - d_ptr->removeBrowserIndexes(property, 0); - - // when item is deleted, item will call removeItem for top level items, - // and itemRemoved for nested items. - - return; - } - pos++; - } -} - -/*! - Creates an editing widget (with the given \a parent) for the given - \a property according to the previously established associations - between property managers and editor factories. - - If the property is created by a property manager which was not - associated with any of the existing factories in \e this property - editor, the function returns 0. - - To make a property editable in the property browser, the - createEditor() function must be called to provide the - property with a suitable editing widget. - - Reimplement this function to provide additional decoration for the - editing widgets created by the installed factories. - - \sa setFactoryForManager() -*/ -QWidget *QtAbstractPropertyBrowser::createEditor(QtProperty *property, - QWidget *parent) -{ - QtAbstractEditorFactoryBase *factory = 0; - QtAbstractPropertyManager *manager = property->propertyManager(); - - if (m_viewToManagerToFactory()->contains(this) && - (*m_viewToManagerToFactory())[this].contains(manager)) { - factory = (*m_viewToManagerToFactory())[this][manager]; - } - - if (!factory) - return 0; - return factory->createEditor(property, parent); -} - -bool QtAbstractPropertyBrowser::addFactory(QtAbstractPropertyManager *abstractManager, - QtAbstractEditorFactoryBase *abstractFactory) -{ - bool connectNeeded = false; - if (!m_managerToFactoryToViews()->contains(abstractManager) || - !(*m_managerToFactoryToViews())[abstractManager].contains(abstractFactory)) { - connectNeeded = true; - } else if ((*m_managerToFactoryToViews())[abstractManager][abstractFactory] - .contains(this)) { - return connectNeeded; - } - - if (m_viewToManagerToFactory()->contains(this) && - (*m_viewToManagerToFactory())[this].contains(abstractManager)) { - unsetFactoryForManager(abstractManager); - } - - (*m_managerToFactoryToViews())[abstractManager][abstractFactory].append(this); - (*m_viewToManagerToFactory())[this][abstractManager] = abstractFactory; - - return connectNeeded; -} - -/*! - Removes the association between the given \a manager and the - factory bound to it, automatically calling the - QtAbstractEditorFactory::removePropertyManager() function if necessary. - - \sa setFactoryForManager() -*/ -void QtAbstractPropertyBrowser::unsetFactoryForManager(QtAbstractPropertyManager *manager) -{ - if (!m_viewToManagerToFactory()->contains(this) || - !(*m_viewToManagerToFactory())[this].contains(manager)) { - return; - } - - QtAbstractEditorFactoryBase *abstractFactory = - (*m_viewToManagerToFactory())[this][manager]; - (*m_viewToManagerToFactory())[this].remove(manager); - if ((*m_viewToManagerToFactory())[this].isEmpty()) { - (*m_viewToManagerToFactory()).remove(this); - } - - (*m_managerToFactoryToViews())[manager][abstractFactory].removeAll(this); - if ((*m_managerToFactoryToViews())[manager][abstractFactory].isEmpty()) { - (*m_managerToFactoryToViews())[manager].remove(abstractFactory); - abstractFactory->breakConnection(manager); - if ((*m_managerToFactoryToViews())[manager].isEmpty()) { - (*m_managerToFactoryToViews()).remove(manager); - } - } -} - -/*! - Returns the current item in the property browser. - - \sa setCurrentItem() -*/ -QtBrowserItem *QtAbstractPropertyBrowser::currentItem() const -{ - return d_ptr->m_currentItem; -} - -/*! - Sets the current item in the property browser to \a item. - - \sa currentItem(), currentItemChanged() -*/ -void QtAbstractPropertyBrowser::setCurrentItem(QtBrowserItem *item) -{ - QtBrowserItem *oldItem = d_ptr->m_currentItem; - d_ptr->m_currentItem = item; - if (oldItem != item) - emit currentItemChanged(item); -} - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#include "moc_qtpropertybrowser.cpp" diff --git a/src/qtpropertybrowser/src/qtpropertybrowser.h b/src/qtpropertybrowser/src/qtpropertybrowser.h deleted file mode 100644 index 3a04452c98..0000000000 --- a/src/qtpropertybrowser/src/qtpropertybrowser.h +++ /dev/null @@ -1,339 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QTPROPERTYBROWSER_H -#define QTPROPERTYBROWSER_H - -#include -#include -#include - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -#if defined(Q_OS_WIN) -# if !defined(QT_QTPROPERTYBROWSER_EXPORT) && !defined(QT_QTPROPERTYBROWSER_IMPORT) -# define QT_QTPROPERTYBROWSER_EXPORT -# elif defined(QT_QTPROPERTYBROWSER_IMPORT) -# if defined(QT_QTPROPERTYBROWSER_EXPORT) -# undef QT_QTPROPERTYBROWSER_EXPORT -# endif -# define QT_QTPROPERTYBROWSER_EXPORT __declspec(dllimport) -# elif defined(QT_QTPROPERTYBROWSER_EXPORT) -# undef QT_QTPROPERTYBROWSER_EXPORT -# define QT_QTPROPERTYBROWSER_EXPORT __declspec(dllexport) -# endif -#else -# define QT_QTPROPERTYBROWSER_EXPORT -#endif - -typedef QLineEdit::EchoMode EchoMode; - -class QtAbstractPropertyManager; -class QtPropertyPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtProperty -{ -public: - virtual ~QtProperty(); - - QList subProperties() const; - - QtAbstractPropertyManager *propertyManager() const; - - QString toolTip() const; - QString statusTip() const; - QString whatsThis() const; - QString propertyName() const; - QColor nameColor() const; - QColor valueColor() const; - bool isEnabled() const; - bool isModified() const; - - bool hasValue() const; - QIcon valueIcon() const; - QString valueText() const; - QString displayText() const; - - void setToolTip(const QString &text); - void setStatusTip(const QString &text); - void setWhatsThis(const QString &text); - void setPropertyName(const QString &text); - void setNameColor(const QColor &color); - void setValueColor(const QColor &color); - void setEnabled(bool enable); - void setModified(bool modified); - - void addSubProperty(QtProperty *property); - void insertSubProperty(QtProperty *property, QtProperty *afterProperty); - void removeSubProperty(QtProperty *property); -protected: - explicit QtProperty(QtAbstractPropertyManager *manager); - void propertyChanged(); -private: - friend class QtAbstractPropertyManager; - QtPropertyPrivate *d_ptr; -}; - -class QtAbstractPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtAbstractPropertyManager : public QObject -{ - Q_OBJECT -public: - - explicit QtAbstractPropertyManager(QObject *parent = 0); - ~QtAbstractPropertyManager(); - - QSet properties() const; - void clear() const; - - QtProperty *addProperty(const QString &name = QString()); -Q_SIGNALS: - - void propertyInserted(QtProperty *property, - QtProperty *parent, QtProperty *after); - void propertyChanged(QtProperty *property); - void propertyRemoved(QtProperty *property, QtProperty *parent); - void propertyDestroyed(QtProperty *property); -protected: - virtual bool hasValue(const QtProperty *property) const; - virtual QIcon valueIcon(const QtProperty *property) const; - virtual QString valueText(const QtProperty *property) const; - virtual QString displayText(const QtProperty *property) const; - virtual EchoMode echoMode(const QtProperty *) const; - virtual void initializeProperty(QtProperty *property) = 0; - virtual void uninitializeProperty(QtProperty *property); - virtual QtProperty *createProperty(); -private: - friend class QtProperty; - QtAbstractPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtAbstractPropertyManager) - Q_DISABLE_COPY(QtAbstractPropertyManager) -}; - -class QT_QTPROPERTYBROWSER_EXPORT QtAbstractEditorFactoryBase : public QObject -{ - Q_OBJECT -public: - virtual QWidget *createEditor(QtProperty *property, QWidget *parent) = 0; -protected: - explicit QtAbstractEditorFactoryBase(QObject *parent = 0) - : QObject(parent) {} - - virtual void breakConnection(QtAbstractPropertyManager *manager) = 0; -protected Q_SLOTS: - virtual void managerDestroyed(QObject *manager) = 0; - - friend class QtAbstractPropertyBrowser; -}; - -template -class QtAbstractEditorFactory : public QtAbstractEditorFactoryBase -{ -public: - explicit QtAbstractEditorFactory(QObject *parent) : QtAbstractEditorFactoryBase(parent) {} - QWidget *createEditor(QtProperty *property, QWidget *parent) - { - QSetIterator it(m_managers); - while (it.hasNext()) { - PropertyManager *manager = it.next(); - if (manager == property->propertyManager()) { - return createEditor(manager, property, parent); - } - } - return 0; - } - void addPropertyManager(PropertyManager *manager) - { - if (m_managers.contains(manager)) - return; - m_managers.insert(manager); - connectPropertyManager(manager); - connect(manager, SIGNAL(destroyed(QObject *)), - this, SLOT(managerDestroyed(QObject *))); - } - void removePropertyManager(PropertyManager *manager) - { - if (!m_managers.contains(manager)) - return; - disconnect(manager, SIGNAL(destroyed(QObject *)), - this, SLOT(managerDestroyed(QObject *))); - disconnectPropertyManager(manager); - m_managers.remove(manager); - } - QSet propertyManagers() const - { - return m_managers; - } - PropertyManager *propertyManager(QtProperty *property) const - { - QtAbstractPropertyManager *manager = property->propertyManager(); - QSetIterator itManager(m_managers); - while (itManager.hasNext()) { - PropertyManager *m = itManager.next(); - if (m == manager) { - return m; - } - } - return 0; - } -protected: - virtual void connectPropertyManager(PropertyManager *manager) = 0; - virtual QWidget *createEditor(PropertyManager *manager, QtProperty *property, - QWidget *parent) = 0; - virtual void disconnectPropertyManager(PropertyManager *manager) = 0; - void managerDestroyed(QObject *manager) - { - QSetIterator it(m_managers); - while (it.hasNext()) { - PropertyManager *m = it.next(); - if (m == manager) { - m_managers.remove(m); - return; - } - } - } -private: - void breakConnection(QtAbstractPropertyManager *manager) - { - QSetIterator it(m_managers); - while (it.hasNext()) { - PropertyManager *m = it.next(); - if (m == manager) { - removePropertyManager(m); - return; - } - } - } -private: - QSet m_managers; - friend class QtAbstractPropertyEditor; -}; - -class QtAbstractPropertyBrowser; -class QtBrowserItemPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtBrowserItem -{ -public: - QtProperty *property() const; - QtBrowserItem *parent() const; - QList children() const; - QtAbstractPropertyBrowser *browser() const; -private: - explicit QtBrowserItem(QtAbstractPropertyBrowser *browser, QtProperty *property, QtBrowserItem *parent); - ~QtBrowserItem(); - QtBrowserItemPrivate *d_ptr; - friend class QtAbstractPropertyBrowserPrivate; -}; - -class QtAbstractPropertyBrowserPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtAbstractPropertyBrowser : public QWidget -{ - Q_OBJECT -public: - - explicit QtAbstractPropertyBrowser(QWidget *parent = 0); - ~QtAbstractPropertyBrowser(); - - QList properties() const; - QList items(QtProperty *property) const; - QtBrowserItem *topLevelItem(QtProperty *property) const; - QList topLevelItems() const; - void clear(); - - template - void setFactoryForManager(PropertyManager *manager, - QtAbstractEditorFactory *factory) { - QtAbstractPropertyManager *abstractManager = manager; - QtAbstractEditorFactoryBase *abstractFactory = factory; - - if (addFactory(abstractManager, abstractFactory)) - factory->addPropertyManager(manager); - } - - void unsetFactoryForManager(QtAbstractPropertyManager *manager); - - QtBrowserItem *currentItem() const; - void setCurrentItem(QtBrowserItem *); - -Q_SIGNALS: - void currentItemChanged(QtBrowserItem *); - -public Q_SLOTS: - - QtBrowserItem *addProperty(QtProperty *property); - QtBrowserItem *insertProperty(QtProperty *property, QtProperty *afterProperty); - void removeProperty(QtProperty *property); - -protected: - - virtual void itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem) = 0; - virtual void itemRemoved(QtBrowserItem *item) = 0; - // can be tooltip, statustip, whatsthis, name, icon, text. - virtual void itemChanged(QtBrowserItem *item) = 0; - - virtual QWidget *createEditor(QtProperty *property, QWidget *parent); -private: - - bool addFactory(QtAbstractPropertyManager *abstractManager, - QtAbstractEditorFactoryBase *abstractFactory); - - QtAbstractPropertyBrowserPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtAbstractPropertyBrowser) - Q_DISABLE_COPY(QtAbstractPropertyBrowser) - Q_PRIVATE_SLOT(d_func(), void slotPropertyInserted(QtProperty *, - QtProperty *, QtProperty *)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyRemoved(QtProperty *, - QtProperty *)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDataChanged(QtProperty *)) - -}; - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#endif // QTPROPERTYBROWSER_H diff --git a/src/qtpropertybrowser/src/qtpropertybrowser.pri b/src/qtpropertybrowser/src/qtpropertybrowser.pri deleted file mode 100644 index 4ae6e103ed..0000000000 --- a/src/qtpropertybrowser/src/qtpropertybrowser.pri +++ /dev/null @@ -1,31 +0,0 @@ -include(../common.pri) -greaterThan(QT_MAJOR_VERSION, 4): QT *= widgets -INCLUDEPATH += $$PWD -DEPENDPATH += $$PWD - -qtpropertybrowser-uselib:!qtpropertybrowser-buildlib { - LIBS += -L$$QTPROPERTYBROWSER_LIBDIR -l$$QTPROPERTYBROWSER_LIBNAME -} else { - SOURCES += $$PWD/qtpropertybrowser.cpp \ - $$PWD/qtpropertymanager.cpp \ - $$PWD/qteditorfactory.cpp \ - $$PWD/qtvariantproperty.cpp \ - $$PWD/qttreepropertybrowser.cpp \ - $$PWD/qtbuttonpropertybrowser.cpp \ - $$PWD/qtgroupboxpropertybrowser.cpp \ - $$PWD/qtpropertybrowserutils.cpp - HEADERS += $$PWD/qtpropertybrowser.h \ - $$PWD/qtpropertymanager.h \ - $$PWD/qteditorfactory.h \ - $$PWD/qtvariantproperty.h \ - $$PWD/qttreepropertybrowser.h \ - $$PWD/qtbuttonpropertybrowser.h \ - $$PWD/qtgroupboxpropertybrowser.h \ - $$PWD/qtpropertybrowserutils_p.h - RESOURCES += $$PWD/qtpropertybrowser.qrc -} - -win32 { - contains(TEMPLATE, lib):contains(CONFIG, shared):DEFINES += QT_QTPROPERTYBROWSER_EXPORT - else:qtpropertybrowser-uselib:DEFINES += QT_QTPROPERTYBROWSER_IMPORT -} diff --git a/src/qtpropertybrowser/src/qtpropertybrowser.qrc b/src/qtpropertybrowser/src/qtpropertybrowser.qrc deleted file mode 100644 index 03e9c5612e..0000000000 --- a/src/qtpropertybrowser/src/qtpropertybrowser.qrc +++ /dev/null @@ -1,23 +0,0 @@ - - - images/cursor-arrow.png - images/cursor-busy.png - images/cursor-closedhand.png - images/cursor-cross.png - images/cursor-forbidden.png - images/cursor-hand.png - images/cursor-hsplit.png - images/cursor-ibeam.png - images/cursor-openhand.png - images/cursor-sizeall.png - images/cursor-sizeb.png - images/cursor-sizef.png - images/cursor-sizeh.png - images/cursor-sizev.png - images/cursor-uparrow.png - images/cursor-vsplit.png - images/cursor-wait.png - images/cursor-whatsthis.png - - - diff --git a/src/qtpropertybrowser/src/qtpropertybrowserutils.cpp b/src/qtpropertybrowser/src/qtpropertybrowserutils.cpp deleted file mode 100644 index 74755cb1bc..0000000000 --- a/src/qtpropertybrowser/src/qtpropertybrowserutils.cpp +++ /dev/null @@ -1,331 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qtpropertybrowserutils_p.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -QtCursorDatabase::QtCursorDatabase() -{ - appendCursor(Qt::ArrowCursor, QCoreApplication::translate("QtCursorDatabase", "Arrow"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-arrow.png"))); - appendCursor(Qt::UpArrowCursor, QCoreApplication::translate("QtCursorDatabase", "Up Arrow"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-uparrow.png"))); - appendCursor(Qt::CrossCursor, QCoreApplication::translate("QtCursorDatabase", "Cross"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-cross.png"))); - appendCursor(Qt::WaitCursor, QCoreApplication::translate("QtCursorDatabase", "Wait"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-wait.png"))); - appendCursor(Qt::IBeamCursor, QCoreApplication::translate("QtCursorDatabase", "IBeam"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-ibeam.png"))); - appendCursor(Qt::SizeVerCursor, QCoreApplication::translate("QtCursorDatabase", "Size Vertical"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizev.png"))); - appendCursor(Qt::SizeHorCursor, QCoreApplication::translate("QtCursorDatabase", "Size Horizontal"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizeh.png"))); - appendCursor(Qt::SizeFDiagCursor, QCoreApplication::translate("QtCursorDatabase", "Size Backslash"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizef.png"))); - appendCursor(Qt::SizeBDiagCursor, QCoreApplication::translate("QtCursorDatabase", "Size Slash"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizeb.png"))); - appendCursor(Qt::SizeAllCursor, QCoreApplication::translate("QtCursorDatabase", "Size All"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-sizeall.png"))); - appendCursor(Qt::BlankCursor, QCoreApplication::translate("QtCursorDatabase", "Blank"), - QIcon()); - appendCursor(Qt::SplitVCursor, QCoreApplication::translate("QtCursorDatabase", "Split Vertical"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-vsplit.png"))); - appendCursor(Qt::SplitHCursor, QCoreApplication::translate("QtCursorDatabase", "Split Horizontal"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-hsplit.png"))); - appendCursor(Qt::PointingHandCursor, QCoreApplication::translate("QtCursorDatabase", "Pointing Hand"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-hand.png"))); - appendCursor(Qt::ForbiddenCursor, QCoreApplication::translate("QtCursorDatabase", "Forbidden"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-forbidden.png"))); - appendCursor(Qt::OpenHandCursor, QCoreApplication::translate("QtCursorDatabase", "Open Hand"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-openhand.png"))); - appendCursor(Qt::ClosedHandCursor, QCoreApplication::translate("QtCursorDatabase", "Closed Hand"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-closedhand.png"))); - appendCursor(Qt::WhatsThisCursor, QCoreApplication::translate("QtCursorDatabase", "What's This"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-whatsthis.png"))); - appendCursor(Qt::BusyCursor, QCoreApplication::translate("QtCursorDatabase", "Busy"), - QIcon(QLatin1String(":/qt-project.org/qtpropertybrowser/images/cursor-busy.png"))); -} - -void QtCursorDatabase::clear() -{ - m_cursorNames.clear(); - m_cursorIcons.clear(); - m_valueToCursorShape.clear(); - m_cursorShapeToValue.clear(); -} - -void QtCursorDatabase::appendCursor(Qt::CursorShape shape, const QString &name, const QIcon &icon) -{ - if (m_cursorShapeToValue.contains(shape)) - return; - const int value = m_cursorNames.count(); - m_cursorNames.append(name); - m_cursorIcons.insert(value, icon); - m_valueToCursorShape.insert(value, shape); - m_cursorShapeToValue.insert(shape, value); -} - -QStringList QtCursorDatabase::cursorShapeNames() const -{ - return m_cursorNames; -} - -QMap QtCursorDatabase::cursorShapeIcons() const -{ - return m_cursorIcons; -} - -QString QtCursorDatabase::cursorToShapeName(const QCursor &cursor) const -{ - int val = cursorToValue(cursor); - if (val >= 0) - return m_cursorNames.at(val); - return QString(); -} - -QIcon QtCursorDatabase::cursorToShapeIcon(const QCursor &cursor) const -{ - int val = cursorToValue(cursor); - return m_cursorIcons.value(val); -} - -int QtCursorDatabase::cursorToValue(const QCursor &cursor) const -{ -#ifndef QT_NO_CURSOR - Qt::CursorShape shape = cursor.shape(); - if (m_cursorShapeToValue.contains(shape)) - return m_cursorShapeToValue[shape]; -#endif - return -1; -} - -#ifndef QT_NO_CURSOR -QCursor QtCursorDatabase::valueToCursor(int value) const -{ - if (m_valueToCursorShape.contains(value)) - return QCursor(m_valueToCursorShape[value]); - return QCursor(); -} -#endif - -QPixmap QtPropertyBrowserUtils::brushValuePixmap(const QBrush &b) -{ - QImage img(16, 16, QImage::Format_ARGB32_Premultiplied); - img.fill(0); - - QPainter painter(&img); - painter.setCompositionMode(QPainter::CompositionMode_Source); - painter.fillRect(0, 0, img.width(), img.height(), b); - QColor color = b.color(); - if (color.alpha() != 255) { // indicate alpha by an inset - QBrush opaqueBrush = b; - color.setAlpha(255); - opaqueBrush.setColor(color); - painter.fillRect(img.width() / 4, img.height() / 4, - img.width() / 2, img.height() / 2, opaqueBrush); - } - painter.end(); - return QPixmap::fromImage(img); -} - -QIcon QtPropertyBrowserUtils::brushValueIcon(const QBrush &b) -{ - return QIcon(brushValuePixmap(b)); -} - -QString QtPropertyBrowserUtils::colorValueText(const QColor &c) -{ - if (c.isValid()) { - return QCoreApplication::translate("QtPropertyBrowserUtils", "[%1, %2, %3] (%4)") - .arg(c.red()).arg(c.green()).arg(c.blue()).arg(c.alpha()); - } else { - return QCoreApplication::translate("QtPropertyBrowserUtils", "Not set"); - } -} - -QPixmap QtPropertyBrowserUtils::fontValuePixmap(const QFont &font, int size) -{ - QFont f = font; - QImage img(size, size, QImage::Format_ARGB32_Premultiplied); - img.fill(0); - QPainter p(&img); - p.setRenderHint(QPainter::TextAntialiasing, true); - p.setRenderHint(QPainter::Antialiasing, true); - f.setPixelSize(img.height() - 2); - p.setFont(f); - QTextOption t; - t.setAlignment(Qt::AlignCenter); - p.drawText(img.rect(), QString(QLatin1Char('A')), t); - return QPixmap::fromImage(img); -} - -QIcon QtPropertyBrowserUtils::fontValueIcon(const QFont &f) -{ - QIcon icon(fontValuePixmap(f, 16)); - icon.addPixmap(fontValuePixmap(f, 32)); - return icon; -} - -QString QtPropertyBrowserUtils::fontValueText(const QFont &f) -{ - int size = f.pointSize(); - if (size == -1) - size = f.pixelSize(); - - return QCoreApplication::translate("QtPropertyBrowserUtils", "[%1, %2]") - .arg(f.family()).arg(size); -} - - -QtBoolEdit::QtBoolEdit(QWidget *parent) : - QWidget(parent), - m_checkBox(new QCheckBox(this)), - m_textVisible(true) -{ - QHBoxLayout *lt = new QHBoxLayout; - if (QApplication::layoutDirection() == Qt::LeftToRight) - lt->setContentsMargins(4, 0, 0, 0); - else - lt->setContentsMargins(0, 0, 4, 0); - lt->addWidget(m_checkBox); - setLayout(lt); - connect(m_checkBox, SIGNAL(toggled(bool)), this, SIGNAL(toggled(bool))); - setFocusProxy(m_checkBox); - m_checkBox->setText(tr("True")); -} - -void QtBoolEdit::setTextVisible(bool textVisible) -{ - if (m_textVisible == textVisible) - return; - - m_textVisible = textVisible; - if (m_textVisible) - m_checkBox->setText(isChecked() ? tr("True") : tr("False")); - else - m_checkBox->setText(QString()); -} - -Qt::CheckState QtBoolEdit::checkState() const -{ - return m_checkBox->checkState(); -} - -void QtBoolEdit::setCheckState(Qt::CheckState state) -{ - m_checkBox->setCheckState(state); -} - -bool QtBoolEdit::isChecked() const -{ - return m_checkBox->isChecked(); -} - -void QtBoolEdit::setChecked(bool c) -{ - m_checkBox->setChecked(c); - if (!m_textVisible) - return; - m_checkBox->setText(isChecked() ? tr("True") : tr("False")); -} - -bool QtBoolEdit::blockCheckBoxSignals(bool block) -{ - return m_checkBox->blockSignals(block); -} - -void QtBoolEdit::mousePressEvent(QMouseEvent *event) -{ - if (event->buttons() == Qt::LeftButton) { - m_checkBox->click(); - event->accept(); - } else { - QWidget::mousePressEvent(event); - } -} - -void QtBoolEdit::paintEvent(QPaintEvent *) -{ - QStyleOption opt; - opt.initFrom(this); - QPainter p(this); - style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); -} - - -/** - * Strips a floating point number representation of redundant trailing zeros. - * Examples: - * - * 0.01000 -> 0.01 - * 3.000 -> 3.0 - */ -QString removeRedundantTrialingZeros(const QString &text) -{ - const QString decimalPoint = QLocale::system().decimalPoint(); - const auto decimalPointIndex = text.lastIndexOf(decimalPoint); - if (decimalPointIndex < 0) // return if there is no decimal point - return text; - - const auto afterDecimalPoint = decimalPointIndex + decimalPoint.length(); - int redundantZeros = 0; - - for (int i = text.length() - 1; i > afterDecimalPoint && text.at(i) == QLatin1Char('0'); --i) - ++redundantZeros; - - return text.left(text.length() - redundantZeros); -} - - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif diff --git a/src/qtpropertybrowser/src/qtpropertybrowserutils_p.h b/src/qtpropertybrowser/src/qtpropertybrowserutils_p.h deleted file mode 100644 index ca90d4e72b..0000000000 --- a/src/qtpropertybrowser/src/qtpropertybrowserutils_p.h +++ /dev/null @@ -1,136 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of Qt Designer. This header -// file may change from version to version without notice, or even be removed. -// -// We mean it. -// - -#ifndef QTPROPERTYBROWSERUTILS_H -#define QTPROPERTYBROWSERUTILS_H - -#include -#include -#include -#include - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QMouseEvent; -class QCheckBox; -class QLineEdit; - -class QtCursorDatabase -{ -public: - QtCursorDatabase(); - void clear(); - - QStringList cursorShapeNames() const; - QMap cursorShapeIcons() const; - QString cursorToShapeName(const QCursor &cursor) const; - QIcon cursorToShapeIcon(const QCursor &cursor) const; - int cursorToValue(const QCursor &cursor) const; -#ifndef QT_NO_CURSOR - QCursor valueToCursor(int value) const; -#endif -private: - void appendCursor(Qt::CursorShape shape, const QString &name, const QIcon &icon); - QStringList m_cursorNames; - QMap m_cursorIcons; - QMap m_valueToCursorShape; - QMap m_cursorShapeToValue; -}; - -class QtPropertyBrowserUtils -{ -public: - static QPixmap brushValuePixmap(const QBrush &b); - static QIcon brushValueIcon(const QBrush &b); - static QString colorValueText(const QColor &c); - static QPixmap fontValuePixmap(const QFont &f, int size = 16); - static QIcon fontValueIcon(const QFont &f); - static QString fontValueText(const QFont &f); -}; - -class QtBoolEdit : public QWidget { - Q_OBJECT -public: - QtBoolEdit(QWidget *parent = 0); - - bool textVisible() const { return m_textVisible; } - void setTextVisible(bool textVisible); - - Qt::CheckState checkState() const; - void setCheckState(Qt::CheckState state); - - bool isChecked() const; - void setChecked(bool c); - - bool blockCheckBoxSignals(bool block); - -Q_SIGNALS: - void toggled(bool); - -protected: - void mousePressEvent(QMouseEvent * event); - void paintEvent(QPaintEvent *); - -private: - QCheckBox *m_checkBox; - bool m_textVisible; -}; - -QString removeRedundantTrialingZeros(const QString &text); - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#endif diff --git a/src/qtpropertybrowser/src/qtpropertymanager.cpp b/src/qtpropertybrowser/src/qtpropertymanager.cpp deleted file mode 100644 index e1eae9cd4d..0000000000 --- a/src/qtpropertybrowser/src/qtpropertymanager.cpp +++ /dev/null @@ -1,5995 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qtpropertymanager.h" -#include "qtpropertybrowserutils_p.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#if defined(Q_CC_MSVC) -# pragma warning(disable: 4786) /* MS VS 6: truncating debug info after 255 characters */ -#endif - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -template -static void setSimpleMinimumData(PrivateData *data, const Value &minVal) -{ - data->minVal = minVal; - if (data->maxVal < data->minVal) - data->maxVal = data->minVal; - - if (data->val < data->minVal) - data->val = data->minVal; -} - -template -static void setSimpleMaximumData(PrivateData *data, const Value &maxVal) -{ - data->maxVal = maxVal; - if (data->minVal > data->maxVal) - data->minVal = data->maxVal; - - if (data->val > data->maxVal) - data->val = data->maxVal; -} - -template -static void setSizeMinimumData(PrivateData *data, const Value &newMinVal) -{ - data->minVal = newMinVal; - if (data->maxVal.width() < data->minVal.width()) - data->maxVal.setWidth(data->minVal.width()); - if (data->maxVal.height() < data->minVal.height()) - data->maxVal.setHeight(data->minVal.height()); - - if (data->val.width() < data->minVal.width()) - data->val.setWidth(data->minVal.width()); - if (data->val.height() < data->minVal.height()) - data->val.setHeight(data->minVal.height()); -} - -template -static void setSizeMaximumData(PrivateData *data, const Value &newMaxVal) -{ - data->maxVal = newMaxVal; - if (data->minVal.width() > data->maxVal.width()) - data->minVal.setWidth(data->maxVal.width()); - if (data->minVal.height() > data->maxVal.height()) - data->minVal.setHeight(data->maxVal.height()); - - if (data->val.width() > data->maxVal.width()) - data->val.setWidth(data->maxVal.width()); - if (data->val.height() > data->maxVal.height()) - data->val.setHeight(data->maxVal.height()); -} - -template -static SizeValue qBoundSize(const SizeValue &minVal, const SizeValue &val, const SizeValue &maxVal) -{ - SizeValue croppedVal = val; - if (minVal.width() > val.width()) - croppedVal.setWidth(minVal.width()); - else if (maxVal.width() < val.width()) - croppedVal.setWidth(maxVal.width()); - - if (minVal.height() > val.height()) - croppedVal.setHeight(minVal.height()); - else if (maxVal.height() < val.height()) - croppedVal.setHeight(maxVal.height()); - - return croppedVal; -} - -// Match the exact signature of qBound for VS 6. -QSize qBound(QSize minVal, QSize val, QSize maxVal) -{ - return qBoundSize(minVal, val, maxVal); -} - -QSizeF qBound(QSizeF minVal, QSizeF val, QSizeF maxVal) -{ - return qBoundSize(minVal, val, maxVal); -} - -namespace { - -namespace { -template -void orderBorders(Value &minVal, Value &maxVal) -{ - if (minVal > maxVal) - qSwap(minVal, maxVal); -} - -template -static void orderSizeBorders(Value &minVal, Value &maxVal) -{ - Value fromSize = minVal; - Value toSize = maxVal; - if (fromSize.width() > toSize.width()) { - fromSize.setWidth(maxVal.width()); - toSize.setWidth(minVal.width()); - } - if (fromSize.height() > toSize.height()) { - fromSize.setHeight(maxVal.height()); - toSize.setHeight(minVal.height()); - } - minVal = fromSize; - maxVal = toSize; -} - -void orderBorders(QSize &minVal, QSize &maxVal) -{ - orderSizeBorders(minVal, maxVal); -} - -void orderBorders(QSizeF &minVal, QSizeF &maxVal) -{ - orderSizeBorders(minVal, maxVal); -} - -} -} -//////// - -template -static Value getData(const QMap &propertyMap, - Value PrivateData::*data, - const QtProperty *property, const Value &defaultValue = Value()) -{ - typedef QMap PropertyToData; - typedef typename PropertyToData::const_iterator PropertyToDataConstIterator; - const PropertyToDataConstIterator it = propertyMap.constFind(property); - if (it == propertyMap.constEnd()) - return defaultValue; - return it.value().*data; -} - -template -static Value getValue(const QMap &propertyMap, - const QtProperty *property, const Value &defaultValue = Value()) -{ - return getData(propertyMap, &PrivateData::val, property, defaultValue); -} - -template -static Value getMinimum(const QMap &propertyMap, - const QtProperty *property, const Value &defaultValue = Value()) -{ - return getData(propertyMap, &PrivateData::minVal, property, defaultValue); -} - -template -static Value getMaximum(const QMap &propertyMap, - const QtProperty *property, const Value &defaultValue = Value()) -{ - return getData(propertyMap, &PrivateData::maxVal, property, defaultValue); -} - -template -static void setSimpleValue(QMap &propertyMap, - PropertyManager *manager, - void (PropertyManager::*propertyChangedSignal)(QtProperty *), - void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter), - QtProperty *property, const Value &val) -{ - typedef QMap PropertyToData; - typedef typename PropertyToData::iterator PropertyToDataIterator; - const PropertyToDataIterator it = propertyMap.find(property); - if (it == propertyMap.end()) - return; - - if (it.value() == val) - return; - - it.value() = val; - - emit (manager->*propertyChangedSignal)(property); - emit (manager->*valueChangedSignal)(property, val); -} - -template -static void setValueInRange(PropertyManager *manager, PropertyManagerPrivate *managerPrivate, - void (PropertyManager::*propertyChangedSignal)(QtProperty *), - void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter), - QtProperty *property, const Value &val, - void (PropertyManagerPrivate::*setSubPropertyValue)(QtProperty *, ValueChangeParameter)) -{ - typedef typename PropertyManagerPrivate::Data PrivateData; - typedef QMap PropertyToData; - typedef typename PropertyToData::iterator PropertyToDataIterator; - const PropertyToDataIterator it = managerPrivate->m_values.find(property); - if (it == managerPrivate->m_values.end()) - return; - - PrivateData &data = it.value(); - - if (data.val == val) - return; - - const Value oldVal = data.val; - - data.val = qBound(data.minVal, val, data.maxVal); - - if (data.val == oldVal) - return; - - if (setSubPropertyValue) - (managerPrivate->*setSubPropertyValue)(property, data.val); - - emit (manager->*propertyChangedSignal)(property); - emit (manager->*valueChangedSignal)(property, data.val); -} - -template -static void setBorderValues(PropertyManager *manager, PropertyManagerPrivate *managerPrivate, - void (PropertyManager::*propertyChangedSignal)(QtProperty *), - void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter), - void (PropertyManager::*rangeChangedSignal)(QtProperty *, ValueChangeParameter, ValueChangeParameter), - QtProperty *property, const Value &minVal, const Value &maxVal, - void (PropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, - ValueChangeParameter, ValueChangeParameter, ValueChangeParameter)) -{ - typedef typename PropertyManagerPrivate::Data PrivateData; - typedef QMap PropertyToData; - typedef typename PropertyToData::iterator PropertyToDataIterator; - const PropertyToDataIterator it = managerPrivate->m_values.find(property); - if (it == managerPrivate->m_values.end()) - return; - - Value fromVal = minVal; - Value toVal = maxVal; - orderBorders(fromVal, toVal); - - PrivateData &data = it.value(); - - if (data.minVal == fromVal && data.maxVal == toVal) - return; - - const Value oldVal = data.val; - - data.setMinimumValue(fromVal); - data.setMaximumValue(toVal); - - emit (manager->*rangeChangedSignal)(property, data.minVal, data.maxVal); - - if (setSubPropertyRange) - (managerPrivate->*setSubPropertyRange)(property, data.minVal, data.maxVal, data.val); - - if (data.val == oldVal) - return; - - emit (manager->*propertyChangedSignal)(property); - emit (manager->*valueChangedSignal)(property, data.val); -} - -template -static void setBorderValue(PropertyManager *manager, PropertyManagerPrivate *managerPrivate, - void (PropertyManager::*propertyChangedSignal)(QtProperty *), - void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter), - void (PropertyManager::*rangeChangedSignal)(QtProperty *, ValueChangeParameter, ValueChangeParameter), - QtProperty *property, - Value (PrivateData::*getRangeVal)() const, - void (PrivateData::*setRangeVal)(ValueChangeParameter), const Value &borderVal, - void (PropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, - ValueChangeParameter, ValueChangeParameter, ValueChangeParameter)) -{ - typedef QMap PropertyToData; - typedef typename PropertyToData::iterator PropertyToDataIterator; - const PropertyToDataIterator it = managerPrivate->m_values.find(property); - if (it == managerPrivate->m_values.end()) - return; - - PrivateData &data = it.value(); - - if ((data.*getRangeVal)() == borderVal) - return; - - const Value oldVal = data.val; - - (data.*setRangeVal)(borderVal); - - emit (manager->*rangeChangedSignal)(property, data.minVal, data.maxVal); - - if (setSubPropertyRange) - (managerPrivate->*setSubPropertyRange)(property, data.minVal, data.maxVal, data.val); - - if (data.val == oldVal) - return; - - emit (manager->*propertyChangedSignal)(property); - emit (manager->*valueChangedSignal)(property, data.val); -} - -template -static void setMinimumValue(PropertyManager *manager, PropertyManagerPrivate *managerPrivate, - void (PropertyManager::*propertyChangedSignal)(QtProperty *), - void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter), - void (PropertyManager::*rangeChangedSignal)(QtProperty *, ValueChangeParameter, ValueChangeParameter), - QtProperty *property, const Value &minVal) -{ - void (PropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, - ValueChangeParameter, ValueChangeParameter, ValueChangeParameter) = 0; - setBorderValue(manager, managerPrivate, - propertyChangedSignal, valueChangedSignal, rangeChangedSignal, - property, &PropertyManagerPrivate::Data::minimumValue, &PropertyManagerPrivate::Data::setMinimumValue, minVal, setSubPropertyRange); -} - -template -static void setMaximumValue(PropertyManager *manager, PropertyManagerPrivate *managerPrivate, - void (PropertyManager::*propertyChangedSignal)(QtProperty *), - void (PropertyManager::*valueChangedSignal)(QtProperty *, ValueChangeParameter), - void (PropertyManager::*rangeChangedSignal)(QtProperty *, ValueChangeParameter, ValueChangeParameter), - QtProperty *property, const Value &maxVal) -{ - void (PropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, - ValueChangeParameter, ValueChangeParameter, ValueChangeParameter) = 0; - setBorderValue(manager, managerPrivate, - propertyChangedSignal, valueChangedSignal, rangeChangedSignal, - property, &PropertyManagerPrivate::Data::maximumValue, &PropertyManagerPrivate::Data::setMaximumValue, maxVal, setSubPropertyRange); -} - -class QtMetaEnumWrapper : public QObject -{ - Q_OBJECT - Q_PROPERTY(QSizePolicy::Policy policy READ policy) -public: - QSizePolicy::Policy policy() const { return QSizePolicy::Ignored; } -private: - explicit QtMetaEnumWrapper(QObject *parent) : QObject(parent) {} -}; - -// QtGroupPropertyManager - -/*! - \class QtGroupPropertyManager - - \brief The QtGroupPropertyManager provides and manages group properties. - - This class is intended to provide a grouping element without any value. - - \sa QtAbstractPropertyManager -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtGroupPropertyManager::QtGroupPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtGroupPropertyManager::~QtGroupPropertyManager() -{ - -} - -/*! - \reimp -*/ -bool QtGroupPropertyManager::hasValue(const QtProperty *property) const -{ - Q_UNUSED(property) - return false; -} - -/*! - \reimp -*/ -void QtGroupPropertyManager::initializeProperty(QtProperty *property) -{ - Q_UNUSED(property) -} - -/*! - \reimp -*/ -void QtGroupPropertyManager::uninitializeProperty(QtProperty *property) -{ - Q_UNUSED(property) -} - -// QtIntPropertyManager - -class QtIntPropertyManagerPrivate -{ - QtIntPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtIntPropertyManager) -public: - - struct Data - { - Data() : val(0), minVal(-INT_MAX), maxVal(INT_MAX), singleStep(1), readOnly(false) {} - int val; - int minVal; - int maxVal; - int singleStep; - bool readOnly; - int minimumValue() const { return minVal; } - int maximumValue() const { return maxVal; } - void setMinimumValue(int newMinVal) { setSimpleMinimumData(this, newMinVal); } - void setMaximumValue(int newMaxVal) { setSimpleMaximumData(this, newMaxVal); } - }; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; -}; - -/*! - \class QtIntPropertyManager - - \brief The QtIntPropertyManager provides and manages int properties. - - An int property has a current value, and a range specifying the - valid values. The range is defined by a minimum and a maximum - value. - - The property's value and range can be retrieved using the value(), - minimum() and maximum() functions, and can be set using the - setValue(), setMinimum() and setMaximum() slots. Alternatively, - the range can be defined in one go using the setRange() slot. - - In addition, QtIntPropertyManager provides the valueChanged() signal which - is emitted whenever a property created by this manager changes, - and the rangeChanged() signal which is emitted whenever such a - property changes its range of valid values. - - \sa QtAbstractPropertyManager, QtSpinBoxFactory, QtSliderFactory, QtScrollBarFactory -*/ - -/*! - \fn void QtIntPropertyManager::valueChanged(QtProperty *property, int value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtIntPropertyManager::rangeChanged(QtProperty *property, int minimum, int maximum) - - This signal is emitted whenever a property created by this manager - changes its range of valid values, passing a pointer to the - \a property and the new \a minimum and \a maximum values. - - \sa setRange() -*/ - -/*! - \fn void QtIntPropertyManager::singleStepChanged(QtProperty *property, int step) - - This signal is emitted whenever a property created by this manager - changes its single step property, passing a pointer to the - \a property and the new \a step value - - \sa setSingleStep() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtIntPropertyManager::QtIntPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtIntPropertyManagerPrivate; - d_ptr->q_ptr = this; -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtIntPropertyManager::~QtIntPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value. - - If the given property is not managed by this manager, this - function returns 0. - - \sa setValue() -*/ -int QtIntPropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property, 0); -} - -/*! - Returns the given \a property's minimum value. - - \sa setMinimum(), maximum(), setRange() -*/ -int QtIntPropertyManager::minimum(const QtProperty *property) const -{ - return getMinimum(d_ptr->m_values, property, 0); -} - -/*! - Returns the given \a property's maximum value. - - \sa setMaximum(), minimum(), setRange() -*/ -int QtIntPropertyManager::maximum(const QtProperty *property) const -{ - return getMaximum(d_ptr->m_values, property, 0); -} - -/*! - Returns the given \a property's step value. - - The step is typically used to increment or decrement a property value while pressing an arrow key. - - \sa setSingleStep() -*/ -int QtIntPropertyManager::singleStep(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtIntPropertyManagerPrivate::Data::singleStep, property, 0); -} - -/*! - Returns read-only status of the property. - - When property is read-only it's value can be selected and copied from editor but not modified. - - \sa QtIntPropertyManager::setReadOnly -*/ -bool QtIntPropertyManager::isReadOnly(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtIntPropertyManagerPrivate::Data::readOnly, property, false); -} - -/*! - \reimp -*/ -QString QtIntPropertyManager::valueText(const QtProperty *property) const -{ - const QtIntPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - return QString::number(it.value().val); -} - -/*! - \fn void QtIntPropertyManager::setValue(QtProperty *property, int value) - - Sets the value of the given \a property to \a value. - - If the specified \a value is not valid according to the given \a - property's range, the \a value is adjusted to the nearest valid - value within the range. - - \sa value(), setRange(), valueChanged() -*/ -void QtIntPropertyManager::setValue(QtProperty *property, int val) -{ - void (QtIntPropertyManagerPrivate::*setSubPropertyValue)(QtProperty *, int) = 0; - setValueInRange(this, d_ptr, - &QtIntPropertyManager::propertyChanged, - &QtIntPropertyManager::valueChanged, - property, val, setSubPropertyValue); -} - -/*! - Sets the minimum value for the given \a property to \a minVal. - - When setting the minimum value, the maximum and current values are - adjusted if necessary (ensuring that the range remains valid and - that the current value is within the range). - - \sa minimum(), setRange(), rangeChanged() -*/ -void QtIntPropertyManager::setMinimum(QtProperty *property, int minVal) -{ - setMinimumValue(this, d_ptr, - &QtIntPropertyManager::propertyChanged, - &QtIntPropertyManager::valueChanged, - &QtIntPropertyManager::rangeChanged, - property, minVal); -} - -/*! - Sets the maximum value for the given \a property to \a maxVal. - - When setting maximum value, the minimum and current values are - adjusted if necessary (ensuring that the range remains valid and - that the current value is within the range). - - \sa maximum(), setRange(), rangeChanged() -*/ -void QtIntPropertyManager::setMaximum(QtProperty *property, int maxVal) -{ - setMaximumValue(this, d_ptr, - &QtIntPropertyManager::propertyChanged, - &QtIntPropertyManager::valueChanged, - &QtIntPropertyManager::rangeChanged, - property, maxVal); -} - -/*! - \fn void QtIntPropertyManager::setRange(QtProperty *property, int minimum, int maximum) - - Sets the range of valid values. - - This is a convenience function defining the range of valid values - in one go; setting the \a minimum and \a maximum values for the - given \a property with a single function call. - - When setting a new range, the current value is adjusted if - necessary (ensuring that the value remains within range). - - \sa setMinimum(), setMaximum(), rangeChanged() -*/ -void QtIntPropertyManager::setRange(QtProperty *property, int minVal, int maxVal) -{ - void (QtIntPropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, int, int, int) = 0; - setBorderValues(this, d_ptr, - &QtIntPropertyManager::propertyChanged, - &QtIntPropertyManager::valueChanged, - &QtIntPropertyManager::rangeChanged, - property, minVal, maxVal, setSubPropertyRange); -} - -/*! - Sets the step value for the given \a property to \a step. - - The step is typically used to increment or decrement a property value while pressing an arrow key. - - \sa singleStep() -*/ -void QtIntPropertyManager::setSingleStep(QtProperty *property, int step) -{ - const QtIntPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtIntPropertyManagerPrivate::Data data = it.value(); - - if (step < 0) - step = 0; - - if (data.singleStep == step) - return; - - data.singleStep = step; - - it.value() = data; - - emit singleStepChanged(property, data.singleStep); -} - -/*! - Sets read-only status of the property. - - \sa QtIntPropertyManager::setReadOnly -*/ -void QtIntPropertyManager::setReadOnly(QtProperty *property, bool readOnly) -{ - const QtIntPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtIntPropertyManagerPrivate::Data data = it.value(); - - if (data.readOnly == readOnly) - return; - - data.readOnly = readOnly; - it.value() = data; - - emit propertyChanged(property); - emit readOnlyChanged(property, data.readOnly); -} - -/*! - \reimp -*/ -void QtIntPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtIntPropertyManagerPrivate::Data(); -} - -/*! - \reimp -*/ -void QtIntPropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -// QtDoublePropertyManager - -class QtDoublePropertyManagerPrivate -{ - QtDoublePropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtDoublePropertyManager) -public: - - struct Data - { - Data() : val(0), minVal(-INT_MAX), maxVal(INT_MAX), singleStep(1), decimals(2), readOnly(false) {} - double val; - double minVal; - double maxVal; - double singleStep; - int decimals; - bool readOnly; - double minimumValue() const { return minVal; } - double maximumValue() const { return maxVal; } - void setMinimumValue(double newMinVal) { setSimpleMinimumData(this, newMinVal); } - void setMaximumValue(double newMaxVal) { setSimpleMaximumData(this, newMaxVal); } - }; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; -}; - -/*! - \class QtDoublePropertyManager - - \brief The QtDoublePropertyManager provides and manages double properties. - - A double property has a current value, and a range specifying the - valid values. The range is defined by a minimum and a maximum - value. - - The property's value and range can be retrieved using the value(), - minimum() and maximum() functions, and can be set using the - setValue(), setMinimum() and setMaximum() slots. - Alternatively, the range can be defined in one go using the - setRange() slot. - - In addition, QtDoublePropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes, and the rangeChanged() signal which is emitted whenever - such a property changes its range of valid values. - - \sa QtAbstractPropertyManager, QtDoubleSpinBoxFactory -*/ - -/*! - \fn void QtDoublePropertyManager::valueChanged(QtProperty *property, double value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtDoublePropertyManager::rangeChanged(QtProperty *property, double minimum, double maximum) - - This signal is emitted whenever a property created by this manager - changes its range of valid values, passing a pointer to the - \a property and the new \a minimum and \a maximum values - - \sa setRange() -*/ - -/*! - \fn void QtDoublePropertyManager::decimalsChanged(QtProperty *property, int prec) - - This signal is emitted whenever a property created by this manager - changes its precision of value, passing a pointer to the - \a property and the new \a prec value - - \sa setDecimals() -*/ - -/*! - \fn void QtDoublePropertyManager::singleStepChanged(QtProperty *property, double step) - - This signal is emitted whenever a property created by this manager - changes its single step property, passing a pointer to the - \a property and the new \a step value - - \sa setSingleStep() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtDoublePropertyManager::QtDoublePropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtDoublePropertyManagerPrivate; - d_ptr->q_ptr = this; -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtDoublePropertyManager::~QtDoublePropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value. - - If the given property is not managed by this manager, this - function returns 0. - - \sa setValue() -*/ -double QtDoublePropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property, 0.0); -} - -/*! - Returns the given \a property's minimum value. - - \sa maximum(), setRange() -*/ -double QtDoublePropertyManager::minimum(const QtProperty *property) const -{ - return getMinimum(d_ptr->m_values, property, 0.0); -} - -/*! - Returns the given \a property's maximum value. - - \sa minimum(), setRange() -*/ -double QtDoublePropertyManager::maximum(const QtProperty *property) const -{ - return getMaximum(d_ptr->m_values, property, 0.0); -} - -/*! - Returns the given \a property's step value. - - The step is typically used to increment or decrement a property value while pressing an arrow key. - - \sa setSingleStep() -*/ -double QtDoublePropertyManager::singleStep(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtDoublePropertyManagerPrivate::Data::singleStep, property, 0); -} - -/*! - Returns the given \a property's precision, in decimals. - - \sa setDecimals() -*/ -int QtDoublePropertyManager::decimals(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtDoublePropertyManagerPrivate::Data::decimals, property, 0); -} - -/*! - Returns read-only status of the property. - - When property is read-only it's value can be selected and copied from editor but not modified. - - \sa QtDoublePropertyManager::setReadOnly -*/ -bool QtDoublePropertyManager::isReadOnly(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtDoublePropertyManagerPrivate::Data::readOnly, property, false); -} - -/*! - \reimp -*/ -QString QtDoublePropertyManager::valueText(const QtProperty *property) const -{ - const QtDoublePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - const int decimals = it.value().decimals; - const QString text = QLocale::system().toString(it.value().val, 'f', decimals); - - // remove redundant trailing 0's in case of high precision - if (decimals > 3) - return removeRedundantTrialingZeros(text); - - return text; -} - -/*! - \fn void QtDoublePropertyManager::setValue(QtProperty *property, double value) - - Sets the value of the given \a property to \a value. - - If the specified \a value is not valid according to the given - \a property's range, the \a value is adjusted to the nearest valid value - within the range. - - \sa value(), setRange(), valueChanged() -*/ -void QtDoublePropertyManager::setValue(QtProperty *property, double val) -{ - void (QtDoublePropertyManagerPrivate::*setSubPropertyValue)(QtProperty *, double) = 0; - setValueInRange(this, d_ptr, - &QtDoublePropertyManager::propertyChanged, - &QtDoublePropertyManager::valueChanged, - property, val, setSubPropertyValue); -} - -/*! - Sets the step value for the given \a property to \a step. - - The step is typically used to increment or decrement a property value while pressing an arrow key. - - \sa singleStep() -*/ -void QtDoublePropertyManager::setSingleStep(QtProperty *property, double step) -{ - const QtDoublePropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtDoublePropertyManagerPrivate::Data data = it.value(); - - if (step < 0) - step = 0; - - if (data.singleStep == step) - return; - - data.singleStep = step; - - it.value() = data; - - emit singleStepChanged(property, data.singleStep); -} - -/*! - Sets read-only status of the property. - - \sa QtDoublePropertyManager::setReadOnly -*/ -void QtDoublePropertyManager::setReadOnly(QtProperty *property, bool readOnly) -{ - const QtDoublePropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtDoublePropertyManagerPrivate::Data data = it.value(); - - if (data.readOnly == readOnly) - return; - - data.readOnly = readOnly; - it.value() = data; - - emit propertyChanged(property); - emit readOnlyChanged(property, data.readOnly); -} - -/*! - \fn void QtDoublePropertyManager::setDecimals(QtProperty *property, int prec) - - Sets the precision of the given \a property to \a prec. - - The valid decimal range is 0-13. The default is 2. - - \sa decimals() -*/ -void QtDoublePropertyManager::setDecimals(QtProperty *property, int prec) -{ - const QtDoublePropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtDoublePropertyManagerPrivate::Data data = it.value(); - - if (prec > 13) - prec = 13; - else if (prec < 0) - prec = 0; - - if (data.decimals == prec) - return; - - data.decimals = prec; - - it.value() = data; - - emit decimalsChanged(property, data.decimals); -} - -/*! - Sets the minimum value for the given \a property to \a minVal. - - When setting the minimum value, the maximum and current values are - adjusted if necessary (ensuring that the range remains valid and - that the current value is within in the range). - - \sa minimum(), setRange(), rangeChanged() -*/ -void QtDoublePropertyManager::setMinimum(QtProperty *property, double minVal) -{ - setMinimumValue(this, d_ptr, - &QtDoublePropertyManager::propertyChanged, - &QtDoublePropertyManager::valueChanged, - &QtDoublePropertyManager::rangeChanged, - property, minVal); -} - -/*! - Sets the maximum value for the given \a property to \a maxVal. - - When setting the maximum value, the minimum and current values are - adjusted if necessary (ensuring that the range remains valid and - that the current value is within in the range). - - \sa maximum(), setRange(), rangeChanged() -*/ -void QtDoublePropertyManager::setMaximum(QtProperty *property, double maxVal) -{ - setMaximumValue(this, d_ptr, - &QtDoublePropertyManager::propertyChanged, - &QtDoublePropertyManager::valueChanged, - &QtDoublePropertyManager::rangeChanged, - property, maxVal); -} - -/*! - \fn void QtDoublePropertyManager::setRange(QtProperty *property, double minimum, double maximum) - - Sets the range of valid values. - - This is a convenience function defining the range of valid values - in one go; setting the \a minimum and \a maximum values for the - given \a property with a single function call. - - When setting a new range, the current value is adjusted if - necessary (ensuring that the value remains within range). - - \sa setMinimum(), setMaximum(), rangeChanged() -*/ -void QtDoublePropertyManager::setRange(QtProperty *property, double minVal, double maxVal) -{ - void (QtDoublePropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, double, double, double) = 0; - setBorderValues(this, d_ptr, - &QtDoublePropertyManager::propertyChanged, - &QtDoublePropertyManager::valueChanged, - &QtDoublePropertyManager::rangeChanged, - property, minVal, maxVal, setSubPropertyRange); -} - -/*! - \reimp -*/ -void QtDoublePropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtDoublePropertyManagerPrivate::Data(); -} - -/*! - \reimp -*/ -void QtDoublePropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -// QtStringPropertyManager - -class QtStringPropertyManagerPrivate -{ - QtStringPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtStringPropertyManager) -public: - - struct Data - { - Data() : - regExp(QStringLiteral(".*"), QRegularExpression::CaseInsensitiveOption), - echoMode(QLineEdit::Normal), - readOnly(false) - { - } - QString val; - QRegularExpression regExp; - int echoMode; - bool readOnly; - }; - - typedef QMap PropertyValueMap; - QMap m_values; -}; - -/*! - \class QtStringPropertyManager - - \brief The QtStringPropertyManager provides and manages QString properties. - - A string property's value can be retrieved using the value() - function, and set using the setValue() slot. - - The current value can be checked against a regular expression. To - set the regular expression use the setRegExp() slot, use the - regExp() function to retrieve the currently set expression. - - In addition, QtStringPropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes, and the regExpChanged() signal which is emitted whenever - such a property changes its currently set regular expression. - - \sa QtAbstractPropertyManager, QtLineEditFactory -*/ - -/*! - \fn void QtStringPropertyManager::valueChanged(QtProperty *property, const QString &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the - new \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtStringPropertyManager::regExpChanged(QtProperty *property, const QRegularExpression ®Exp) - - This signal is emitted whenever a property created by this manager - changes its currenlty set regular expression, passing a pointer to - the \a property and the new \a regExp as parameters. - - \sa setRegExp() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtStringPropertyManager::QtStringPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtStringPropertyManagerPrivate; - d_ptr->q_ptr = this; -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtStringPropertyManager::~QtStringPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value. - - If the given property is not managed by this manager, this - function returns an empty string. - - \sa setValue() -*/ -QString QtStringPropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property); -} - -/*! - Returns the given \a property's currently set regular expression. - - If the given \a property is not managed by this manager, this - function returns an empty expression. - - \sa setRegExp() -*/ -QRegularExpression QtStringPropertyManager::regExp(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtStringPropertyManagerPrivate::Data::regExp, property, QRegularExpression()); -} - -/*! - \reimp -*/ -EchoMode QtStringPropertyManager::echoMode(const QtProperty *property) const -{ - return (EchoMode)getData(d_ptr->m_values, &QtStringPropertyManagerPrivate::Data::echoMode, property, 0); -} - -/*! - Returns read-only status of the property. - - When property is read-only it's value can be selected and copied from editor but not modified. - - \sa QtStringPropertyManager::setReadOnly -*/ -bool QtStringPropertyManager::isReadOnly(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtStringPropertyManagerPrivate::Data::readOnly, property, false); -} - -/*! - \reimp -*/ -QString QtStringPropertyManager::valueText(const QtProperty *property) const -{ - const QtStringPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - - return it.value().val; -} - -/*! - \reimp -*/ -QString QtStringPropertyManager::displayText(const QtProperty *property) const -{ - const QtStringPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - - QLineEdit edit; - edit.setEchoMode((EchoMode)it.value().echoMode); - edit.setText(it.value().val); - return edit.displayText(); -} - -/*! - \fn void QtStringPropertyManager::setValue(QtProperty *property, const QString &value) - - Sets the value of the given \a property to \a value. - - If the specified \a value doesn't match the given \a property's - regular expression, this function does nothing. - - \sa value(), setRegExp(), valueChanged() -*/ -void QtStringPropertyManager::setValue(QtProperty *property, const QString &val) -{ - const QtStringPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtStringPropertyManagerPrivate::Data data = it.value(); - - if (data.val == val) - return; - - if (data.regExp.isValid() && !data.regExp.match(val).hasMatch()) - return; - - data.val = val; - - it.value() = data; - - emit propertyChanged(property); - emit valueChanged(property, data.val); -} - -/*! - Sets the regular expression of the given \a property to \a regExp. - - \sa regExp(), setValue(), regExpChanged() -*/ -void QtStringPropertyManager::setRegExp(QtProperty *property, const QRegularExpression ®Exp) -{ - const QtStringPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtStringPropertyManagerPrivate::Data data = it.value() ; - - if (data.regExp == regExp) - return; - - data.regExp = regExp; - - it.value() = data; - - emit regExpChanged(property, data.regExp); -} - - -void QtStringPropertyManager::setEchoMode(QtProperty *property, EchoMode echoMode) -{ - const QtStringPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtStringPropertyManagerPrivate::Data data = it.value(); - - if (data.echoMode == echoMode) - return; - - data.echoMode = echoMode; - it.value() = data; - - emit propertyChanged(property); - emit echoModeChanged(property, data.echoMode); -} - -/*! - Sets read-only status of the property. - - \sa QtStringPropertyManager::setReadOnly -*/ -void QtStringPropertyManager::setReadOnly(QtProperty *property, bool readOnly) -{ - const QtStringPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtStringPropertyManagerPrivate::Data data = it.value(); - - if (data.readOnly == readOnly) - return; - - data.readOnly = readOnly; - it.value() = data; - - emit propertyChanged(property); - emit echoModeChanged(property, data.echoMode); -} - -/*! - \reimp -*/ -void QtStringPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtStringPropertyManagerPrivate::Data(); -} - -/*! - \reimp -*/ -void QtStringPropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -// QtBoolPropertyManager -// Return an icon containing a check box indicator -static QIcon drawCheckBox(bool value) -{ - QStyleOptionButton opt; - opt.state |= value ? QStyle::State_On : QStyle::State_Off; - opt.state |= QStyle::State_Enabled; - const QStyle *style = QApplication::style(); - // Figure out size of an indicator and make sure it is not scaled down in a list view item - // by making the pixmap as big as a list view icon and centering the indicator in it. - // (if it is smaller, it can't be helped) - const int indicatorWidth = style->pixelMetric(QStyle::PM_IndicatorWidth, &opt); - const int indicatorHeight = style->pixelMetric(QStyle::PM_IndicatorHeight, &opt); - const int listViewIconSize = indicatorWidth; - const int pixmapWidth = indicatorWidth; - const int pixmapHeight = qMax(indicatorHeight, listViewIconSize); - - opt.rect = QRect(0, 0, indicatorWidth, indicatorHeight); - QPixmap pixmap = QPixmap(pixmapWidth, pixmapHeight); - pixmap.fill(Qt::transparent); - { - // Center? - const int xoff = (pixmapWidth > indicatorWidth) ? (pixmapWidth - indicatorWidth) / 2 : 0; - const int yoff = (pixmapHeight > indicatorHeight) ? (pixmapHeight - indicatorHeight) / 2 : 0; - QPainter painter(&pixmap); - painter.translate(xoff, yoff); - style->drawPrimitive(QStyle::PE_IndicatorCheckBox, &opt, &painter); - } - return QIcon(pixmap); -} - -class QtBoolPropertyManagerPrivate -{ - QtBoolPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtBoolPropertyManager) -public: - QtBoolPropertyManagerPrivate(); - - struct Data - { - Data() : val(false), textVisible(true) {} - bool val; - bool textVisible; - }; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - static QIcon m_checkedIcon; - static QIcon m_uncheckedIcon; -}; - -QIcon QtBoolPropertyManagerPrivate::m_checkedIcon; -QIcon QtBoolPropertyManagerPrivate::m_uncheckedIcon; - -QtBoolPropertyManagerPrivate::QtBoolPropertyManagerPrivate() -{ -} - -/*! - \class QtBoolPropertyManager - - \brief The QtBoolPropertyManager class provides and manages boolean properties. - - The property's value can be retrieved using the value() function, - and set using the setValue() slot. - - In addition, QtBoolPropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes. - - \sa QtAbstractPropertyManager, QtCheckBoxFactory -*/ - -/*! - \fn void QtBoolPropertyManager::valueChanged(QtProperty *property, bool value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the - new \a value as parameters. -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtBoolPropertyManager::QtBoolPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtBoolPropertyManagerPrivate; - d_ptr->q_ptr = this; -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtBoolPropertyManager::~QtBoolPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by \e this manager, this - function returns false. - - \sa setValue() -*/ -bool QtBoolPropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property, false); -} - -bool QtBoolPropertyManager::textVisible(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtBoolPropertyManagerPrivate::Data::textVisible, property, false); -} - -/*! - Resets the icons used to draw the checked and unchecked states. Should be - called after theme changes. -*/ -void QtBoolPropertyManager::resetIcons() -{ - QtBoolPropertyManagerPrivate::m_checkedIcon = QIcon(); - QtBoolPropertyManagerPrivate::m_uncheckedIcon = QIcon(); -} - -/*! - \reimp -*/ -QString QtBoolPropertyManager::valueText(const QtProperty *property) const -{ - const QtBoolPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - - const QtBoolPropertyManagerPrivate::Data &data = it.value(); - if (!data.textVisible) - return QString(); - - return data.val ? tr("True") : tr("False"); -} - -/*! - \reimp -*/ -QIcon QtBoolPropertyManager::valueIcon(const QtProperty *property) const -{ - const QtBoolPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QIcon(); - - if (QtBoolPropertyManagerPrivate::m_checkedIcon.isNull()) { - QtBoolPropertyManagerPrivate::m_checkedIcon = drawCheckBox(true); - QtBoolPropertyManagerPrivate::m_uncheckedIcon = drawCheckBox(false); - } - - return it.value().val ? d_ptr->m_checkedIcon : d_ptr->m_uncheckedIcon; -} - -/*! - \fn void QtBoolPropertyManager::setValue(QtProperty *property, bool value) - - Sets the value of the given \a property to \a value. - - \sa value() -*/ -void QtBoolPropertyManager::setValue(QtProperty *property, bool val) -{ - const QtBoolPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtBoolPropertyManagerPrivate::Data data = it.value(); - - if (data.val == val) - return; - - data.val = val; - it.value() = data; - - emit propertyChanged(property); - emit valueChanged(property, data.val); -} - -void QtBoolPropertyManager::setTextVisible(QtProperty *property, bool textVisible) -{ - const QtBoolPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtBoolPropertyManagerPrivate::Data data = it.value(); - - if (data.textVisible == textVisible) - return; - - data.textVisible = textVisible; - it.value() = data; - - emit propertyChanged(property); - emit textVisibleChanged(property, data.textVisible); -} - -/*! - \reimp -*/ -void QtBoolPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtBoolPropertyManagerPrivate::Data(); -} - -/*! - \reimp -*/ -void QtBoolPropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -// QtDatePropertyManager - -class QtDatePropertyManagerPrivate -{ - QtDatePropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtDatePropertyManager) -public: - - struct Data - { - Data() : val(QDate::currentDate()), minVal(QDate(1752, 9, 14)), - maxVal(QDate(7999, 12, 31)) {} - QDate val; - QDate minVal; - QDate maxVal; - QDate minimumValue() const { return minVal; } - QDate maximumValue() const { return maxVal; } - void setMinimumValue(const QDate &newMinVal) { setSimpleMinimumData(this, newMinVal); } - void setMaximumValue(const QDate &newMaxVal) { setSimpleMaximumData(this, newMaxVal); } - }; - - QString m_format; - - typedef QMap PropertyValueMap; - QMap m_values; -}; - -/*! - \class QtDatePropertyManager - - \brief The QtDatePropertyManager provides and manages QDate properties. - - A date property has a current value, and a range specifying the - valid dates. The range is defined by a minimum and a maximum - value. - - The property's values can be retrieved using the minimum(), - maximum() and value() functions, and can be set using the - setMinimum(), setMaximum() and setValue() slots. Alternatively, - the range can be defined in one go using the setRange() slot. - - In addition, QtDatePropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes, and the rangeChanged() signal which is emitted whenever - such a property changes its range of valid dates. - - \sa QtAbstractPropertyManager, QtDateEditFactory, QtDateTimePropertyManager -*/ - -/*! - \fn void QtDatePropertyManager::valueChanged(QtProperty *property, const QDate &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtDatePropertyManager::rangeChanged(QtProperty *property, const QDate &minimum, const QDate &maximum) - - This signal is emitted whenever a property created by this manager - changes its range of valid dates, passing a pointer to the \a - property and the new \a minimum and \a maximum dates. - - \sa setRange() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtDatePropertyManager::QtDatePropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtDatePropertyManagerPrivate; - d_ptr->q_ptr = this; - - QLocale loc; - d_ptr->m_format = loc.dateFormat(QLocale::ShortFormat); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtDatePropertyManager::~QtDatePropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by \e this manager, this - function returns an invalid date. - - \sa setValue() -*/ -QDate QtDatePropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property); -} - -/*! - Returns the given \a property's minimum date. - - \sa maximum(), setRange() -*/ -QDate QtDatePropertyManager::minimum(const QtProperty *property) const -{ - return getMinimum(d_ptr->m_values, property); -} - -/*! - Returns the given \a property's maximum date. - - \sa minimum(), setRange() -*/ -QDate QtDatePropertyManager::maximum(const QtProperty *property) const -{ - return getMaximum(d_ptr->m_values, property); -} - -/*! - \reimp -*/ -QString QtDatePropertyManager::valueText(const QtProperty *property) const -{ - const QtDatePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - return it.value().val.toString(d_ptr->m_format); -} - -/*! - \fn void QtDatePropertyManager::setValue(QtProperty *property, const QDate &value) - - Sets the value of the given \a property to \a value. - - If the specified \a value is not a valid date according to the - given \a property's range, the value is adjusted to the nearest - valid value within the range. - - \sa value(), setRange(), valueChanged() -*/ -void QtDatePropertyManager::setValue(QtProperty *property, const QDate &val) -{ - void (QtDatePropertyManagerPrivate::*setSubPropertyValue)(QtProperty *, const QDate &) = 0; - setValueInRange(this, d_ptr, - &QtDatePropertyManager::propertyChanged, - &QtDatePropertyManager::valueChanged, - property, val, setSubPropertyValue); -} - -/*! - Sets the minimum value for the given \a property to \a minVal. - - When setting the minimum value, the maximum and current values are - adjusted if necessary (ensuring that the range remains valid and - that the current value is within in the range). - - \sa minimum(), setRange() -*/ -void QtDatePropertyManager::setMinimum(QtProperty *property, const QDate &minVal) -{ - setMinimumValue(this, d_ptr, - &QtDatePropertyManager::propertyChanged, - &QtDatePropertyManager::valueChanged, - &QtDatePropertyManager::rangeChanged, - property, minVal); -} - -/*! - Sets the maximum value for the given \a property to \a maxVal. - - When setting the maximum value, the minimum and current - values are adjusted if necessary (ensuring that the range remains - valid and that the current value is within in the range). - - \sa maximum(), setRange() -*/ -void QtDatePropertyManager::setMaximum(QtProperty *property, const QDate &maxVal) -{ - setMaximumValue(this, d_ptr, - &QtDatePropertyManager::propertyChanged, - &QtDatePropertyManager::valueChanged, - &QtDatePropertyManager::rangeChanged, - property, maxVal); -} - -/*! - \fn void QtDatePropertyManager::setRange(QtProperty *property, const QDate &minimum, const QDate &maximum) - - Sets the range of valid dates. - - This is a convenience function defining the range of valid dates - in one go; setting the \a minimum and \a maximum values for the - given \a property with a single function call. - - When setting a new date range, the current value is adjusted if - necessary (ensuring that the value remains in date range). - - \sa setMinimum(), setMaximum(), rangeChanged() -*/ -void QtDatePropertyManager::setRange(QtProperty *property, const QDate &minVal, const QDate &maxVal) -{ - void (QtDatePropertyManagerPrivate::*setSubPropertyRange)(QtProperty *, const QDate &, - const QDate &, const QDate &) = 0; - setBorderValues(this, d_ptr, - &QtDatePropertyManager::propertyChanged, - &QtDatePropertyManager::valueChanged, - &QtDatePropertyManager::rangeChanged, - property, minVal, maxVal, setSubPropertyRange); -} - -/*! - \reimp -*/ -void QtDatePropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtDatePropertyManagerPrivate::Data(); -} - -/*! - \reimp -*/ -void QtDatePropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -// QtTimePropertyManager - -class QtTimePropertyManagerPrivate -{ - QtTimePropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtTimePropertyManager) -public: - - QString m_format; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; -}; - -/*! - \class QtTimePropertyManager - - \brief The QtTimePropertyManager provides and manages QTime properties. - - A time property's value can be retrieved using the value() - function, and set using the setValue() slot. - - In addition, QtTimePropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes. - - \sa QtAbstractPropertyManager, QtTimeEditFactory -*/ - -/*! - \fn void QtTimePropertyManager::valueChanged(QtProperty *property, const QTime &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the - new \a value as parameters. - - \sa setValue() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtTimePropertyManager::QtTimePropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtTimePropertyManagerPrivate; - d_ptr->q_ptr = this; - - QLocale loc; - d_ptr->m_format = loc.timeFormat(QLocale::ShortFormat); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtTimePropertyManager::~QtTimePropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value. - - If the given property is not managed by this manager, this - function returns an invalid time object. - - \sa setValue() -*/ -QTime QtTimePropertyManager::value(const QtProperty *property) const -{ - return d_ptr->m_values.value(property, QTime()); -} - -/*! - \reimp -*/ -QString QtTimePropertyManager::valueText(const QtProperty *property) const -{ - const QtTimePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - return it.value().toString(d_ptr->m_format); -} - -/*! - \fn void QtTimePropertyManager::setValue(QtProperty *property, const QTime &value) - - Sets the value of the given \a property to \a value. - - \sa value(), valueChanged() -*/ -void QtTimePropertyManager::setValue(QtProperty *property, const QTime &val) -{ - setSimpleValue(d_ptr->m_values, this, - &QtTimePropertyManager::propertyChanged, - &QtTimePropertyManager::valueChanged, - property, val); -} - -/*! - \reimp -*/ -void QtTimePropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QTime::currentTime(); -} - -/*! - \reimp -*/ -void QtTimePropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -// QtDateTimePropertyManager - -class QtDateTimePropertyManagerPrivate -{ - QtDateTimePropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtDateTimePropertyManager) -public: - - QString m_format; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; -}; - -/*! \class QtDateTimePropertyManager - - \brief The QtDateTimePropertyManager provides and manages QDateTime properties. - - A date and time property has a current value which can be - retrieved using the value() function, and set using the setValue() - slot. In addition, QtDateTimePropertyManager provides the - valueChanged() signal which is emitted whenever a property created - by this manager changes. - - \sa QtAbstractPropertyManager, QtDateTimeEditFactory, QtDatePropertyManager -*/ - -/*! - \fn void QtDateTimePropertyManager::valueChanged(QtProperty *property, const QDateTime &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtDateTimePropertyManager::QtDateTimePropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtDateTimePropertyManagerPrivate; - d_ptr->q_ptr = this; - - QLocale loc; - d_ptr->m_format = loc.dateFormat(QLocale::ShortFormat); - d_ptr->m_format += QLatin1Char(' '); - d_ptr->m_format += loc.timeFormat(QLocale::ShortFormat); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtDateTimePropertyManager::~QtDateTimePropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns an invalid QDateTime object. - - \sa setValue() -*/ -QDateTime QtDateTimePropertyManager::value(const QtProperty *property) const -{ - return d_ptr->m_values.value(property, QDateTime()); -} - -/*! - \reimp -*/ -QString QtDateTimePropertyManager::valueText(const QtProperty *property) const -{ - const QtDateTimePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - return it.value().toString(d_ptr->m_format); -} - -/*! - \fn void QtDateTimePropertyManager::setValue(QtProperty *property, const QDateTime &value) - - Sets the value of the given \a property to \a value. - - \sa value(), valueChanged() -*/ -void QtDateTimePropertyManager::setValue(QtProperty *property, const QDateTime &val) -{ - setSimpleValue(d_ptr->m_values, this, - &QtDateTimePropertyManager::propertyChanged, - &QtDateTimePropertyManager::valueChanged, - property, val); -} - -/*! - \reimp -*/ -void QtDateTimePropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QDateTime::currentDateTime(); -} - -/*! - \reimp -*/ -void QtDateTimePropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -// QtKeySequencePropertyManager - -class QtKeySequencePropertyManagerPrivate -{ - QtKeySequencePropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtKeySequencePropertyManager) -public: - - QString m_format; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; -}; - -/*! \class QtKeySequencePropertyManager - - \brief The QtKeySequencePropertyManager provides and manages QKeySequence properties. - - A key sequence's value can be retrieved using the value() - function, and set using the setValue() slot. - - In addition, QtKeySequencePropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes. - - \sa QtAbstractPropertyManager -*/ - -/*! - \fn void QtKeySequencePropertyManager::valueChanged(QtProperty *property, const QKeySequence &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtKeySequencePropertyManager::QtKeySequencePropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtKeySequencePropertyManagerPrivate; - d_ptr->q_ptr = this; -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtKeySequencePropertyManager::~QtKeySequencePropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns an empty QKeySequence object. - - \sa setValue() -*/ -QKeySequence QtKeySequencePropertyManager::value(const QtProperty *property) const -{ - return d_ptr->m_values.value(property, QKeySequence()); -} - -/*! - \reimp -*/ -QString QtKeySequencePropertyManager::valueText(const QtProperty *property) const -{ - const QtKeySequencePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - return it.value().toString(QKeySequence::NativeText); -} - -/*! - \fn void QtKeySequencePropertyManager::setValue(QtProperty *property, const QKeySequence &value) - - Sets the value of the given \a property to \a value. - - \sa value(), valueChanged() -*/ -void QtKeySequencePropertyManager::setValue(QtProperty *property, const QKeySequence &val) -{ - setSimpleValue(d_ptr->m_values, this, - &QtKeySequencePropertyManager::propertyChanged, - &QtKeySequencePropertyManager::valueChanged, - property, val); -} - -/*! - \reimp -*/ -void QtKeySequencePropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QKeySequence(); -} - -/*! - \reimp -*/ -void QtKeySequencePropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -// QtCharPropertyManager - -class QtCharPropertyManagerPrivate -{ - QtCharPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtCharPropertyManager) -public: - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; -}; - -/*! \class QtCharPropertyManager - - \brief The QtCharPropertyManager provides and manages QChar properties. - - A char's value can be retrieved using the value() - function, and set using the setValue() slot. - - In addition, QtCharPropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes. - - \sa QtAbstractPropertyManager -*/ - -/*! - \fn void QtCharPropertyManager::valueChanged(QtProperty *property, const QChar &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtCharPropertyManager::QtCharPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtCharPropertyManagerPrivate; - d_ptr->q_ptr = this; -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtCharPropertyManager::~QtCharPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns an null QChar object. - - \sa setValue() -*/ -QChar QtCharPropertyManager::value(const QtProperty *property) const -{ - return d_ptr->m_values.value(property, QChar()); -} - -/*! - \reimp -*/ -QString QtCharPropertyManager::valueText(const QtProperty *property) const -{ - const QtCharPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - const QChar c = it.value(); - return c.isNull() ? QString() : QString(c); -} - -/*! - \fn void QtCharPropertyManager::setValue(QtProperty *property, const QChar &value) - - Sets the value of the given \a property to \a value. - - \sa value(), valueChanged() -*/ -void QtCharPropertyManager::setValue(QtProperty *property, const QChar &val) -{ - setSimpleValue(d_ptr->m_values, this, - &QtCharPropertyManager::propertyChanged, - &QtCharPropertyManager::valueChanged, - property, val); -} - -/*! - \reimp -*/ -void QtCharPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QChar(); -} - -/*! - \reimp -*/ -void QtCharPropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -// QtPointPropertyManager - -class QtPointPropertyManagerPrivate -{ - QtPointPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtPointPropertyManager) -public: - - void slotIntChanged(QtProperty *property, int value); - void slotPropertyDestroyed(QtProperty *property); - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - QtIntPropertyManager *m_intPropertyManager; - - QMap m_propertyToX; - QMap m_propertyToY; - - QMap m_xToProperty; - QMap m_yToProperty; -}; - -void QtPointPropertyManagerPrivate::slotIntChanged(QtProperty *property, int value) -{ - if (QtProperty *xprop = m_xToProperty.value(property, 0)) { - QPoint p = m_values[xprop]; - p.setX(value); - q_ptr->setValue(xprop, p); - } else if (QtProperty *yprop = m_yToProperty.value(property, 0)) { - QPoint p = m_values[yprop]; - p.setY(value); - q_ptr->setValue(yprop, p); - } -} - -void QtPointPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) -{ - if (QtProperty *pointProp = m_xToProperty.value(property, 0)) { - m_propertyToX[pointProp] = 0; - m_xToProperty.remove(property); - } else if (QtProperty *pointProp = m_yToProperty.value(property, 0)) { - m_propertyToY[pointProp] = 0; - m_yToProperty.remove(property); - } -} - -/*! \class QtPointPropertyManager - - \brief The QtPointPropertyManager provides and manages QPoint properties. - - A point property has nested \e x and \e y subproperties. The - top-level property's value can be retrieved using the value() - function, and set using the setValue() slot. - - The subproperties are created by a QtIntPropertyManager object. This - manager can be retrieved using the subIntPropertyManager() function. In - order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - In addition, QtPointPropertyManager provides the valueChanged() signal which - is emitted whenever a property created by this manager changes. - - \sa QtAbstractPropertyManager, QtIntPropertyManager, QtPointFPropertyManager -*/ - -/*! - \fn void QtPointPropertyManager::valueChanged(QtProperty *property, const QPoint &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the - new \a value as parameters. - - \sa setValue() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtPointPropertyManager::QtPointPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtPointPropertyManagerPrivate; - d_ptr->q_ptr = this; - - d_ptr->m_intPropertyManager = new QtIntPropertyManager(this); - connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotIntChanged(QtProperty *, int))); - connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtPointPropertyManager::~QtPointPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the manager that creates the nested \e x and \e y - subproperties. - - In order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtIntPropertyManager *QtPointPropertyManager::subIntPropertyManager() const -{ - return d_ptr->m_intPropertyManager; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns a point with coordinates (0, 0). - - \sa setValue() -*/ -QPoint QtPointPropertyManager::value(const QtProperty *property) const -{ - return d_ptr->m_values.value(property, QPoint()); -} - -/*! - \reimp -*/ -QString QtPointPropertyManager::valueText(const QtProperty *property) const -{ - const QtPointPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - const QPoint v = it.value(); - return QString(tr("(%1, %2)").arg(QString::number(v.x())) - .arg(QString::number(v.y()))); -} - -/*! - \fn void QtPointPropertyManager::setValue(QtProperty *property, const QPoint &value) - - Sets the value of the given \a property to \a value. Nested - properties are updated automatically. - - \sa value(), valueChanged() -*/ -void QtPointPropertyManager::setValue(QtProperty *property, const QPoint &val) -{ - const QtPointPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - if (it.value() == val) - return; - - it.value() = val; - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToX[property], val.x()); - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToY[property], val.y()); - - emit propertyChanged(property); - emit valueChanged(property, val); -} - -/*! - \reimp -*/ -void QtPointPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QPoint(0, 0); - - QtProperty *xProp = d_ptr->m_intPropertyManager->addProperty(); - xProp->setPropertyName(tr("X")); - d_ptr->m_intPropertyManager->setValue(xProp, 0); - d_ptr->m_propertyToX[property] = xProp; - d_ptr->m_xToProperty[xProp] = property; - property->addSubProperty(xProp); - - QtProperty *yProp = d_ptr->m_intPropertyManager->addProperty(); - yProp->setPropertyName(tr("Y")); - d_ptr->m_intPropertyManager->setValue(yProp, 0); - d_ptr->m_propertyToY[property] = yProp; - d_ptr->m_yToProperty[yProp] = property; - property->addSubProperty(yProp); -} - -/*! - \reimp -*/ -void QtPointPropertyManager::uninitializeProperty(QtProperty *property) -{ - QtProperty *xProp = d_ptr->m_propertyToX[property]; - if (xProp) { - d_ptr->m_xToProperty.remove(xProp); - delete xProp; - } - d_ptr->m_propertyToX.remove(property); - - QtProperty *yProp = d_ptr->m_propertyToY[property]; - if (yProp) { - d_ptr->m_yToProperty.remove(yProp); - delete yProp; - } - d_ptr->m_propertyToY.remove(property); - - d_ptr->m_values.remove(property); -} - -// QtPointFPropertyManager - -class QtPointFPropertyManagerPrivate -{ - QtPointFPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtPointFPropertyManager) -public: - - struct Data - { - QPointF val; - double singleStep = 1.0; - int decimals = 2; - }; - - void slotDoubleChanged(QtProperty *property, double value); - void slotPropertyDestroyed(QtProperty *property); - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - QtDoublePropertyManager *m_doublePropertyManager; - - QMap m_propertyToX; - QMap m_propertyToY; - - QMap m_xToProperty; - QMap m_yToProperty; -}; - -void QtPointFPropertyManagerPrivate::slotDoubleChanged(QtProperty *property, double value) -{ - if (QtProperty *prop = m_xToProperty.value(property, 0)) { - QPointF p = m_values[prop].val; - p.setX(value); - q_ptr->setValue(prop, p); - } else if (QtProperty *prop = m_yToProperty.value(property, 0)) { - QPointF p = m_values[prop].val; - p.setY(value); - q_ptr->setValue(prop, p); - } -} - -void QtPointFPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) -{ - if (QtProperty *pointProp = m_xToProperty.value(property, 0)) { - m_propertyToX[pointProp] = 0; - m_xToProperty.remove(property); - } else if (QtProperty *pointProp = m_yToProperty.value(property, 0)) { - m_propertyToY[pointProp] = 0; - m_yToProperty.remove(property); - } -} - -/*! \class QtPointFPropertyManager - - \brief The QtPointFPropertyManager provides and manages QPointF properties. - - A point property has nested \e x and \e y subproperties. The - top-level property's value can be retrieved using the value() - function, and set using the setValue() slot. - - The subproperties are created by a QtDoublePropertyManager object. This - manager can be retrieved using the subDoublePropertyManager() function. In - order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - In addition, QtPointFPropertyManager provides the valueChanged() signal which - is emitted whenever a property created by this manager changes. - - \sa QtAbstractPropertyManager, QtDoublePropertyManager, QtPointPropertyManager -*/ - -/*! - \fn void QtPointFPropertyManager::valueChanged(QtProperty *property, const QPointF &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the - new \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtPointFPropertyManager::decimalsChanged(QtProperty *property, int prec) - - This signal is emitted whenever a property created by this manager - changes its precision of value, passing a pointer to the - \a property and the new \a prec value - - \sa setDecimals() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtPointFPropertyManager::QtPointFPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtPointFPropertyManagerPrivate; - d_ptr->q_ptr = this; - - d_ptr->m_doublePropertyManager = new QtDoublePropertyManager(this); - connect(d_ptr->m_doublePropertyManager, SIGNAL(valueChanged(QtProperty *, double)), - this, SLOT(slotDoubleChanged(QtProperty *, double))); - connect(d_ptr->m_doublePropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtPointFPropertyManager::~QtPointFPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the manager that creates the nested \e x and \e y - subproperties. - - In order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtDoublePropertyManager *QtPointFPropertyManager::subDoublePropertyManager() const -{ - return d_ptr->m_doublePropertyManager; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns a point with coordinates (0, 0). - - \sa setValue() -*/ -QPointF QtPointFPropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property); -} - -/*! - Returns the given \a property's step value. - - The step is typically used to increment or decrement a property value while pressing an arrow key. - - \sa setSingleStep() -*/ -double QtPointFPropertyManager::singleStep(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtPointFPropertyManagerPrivate::Data::singleStep, property, 0); -} - -/*! - Returns the given \a property's precision, in decimals. - - \sa setDecimals() -*/ -int QtPointFPropertyManager::decimals(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtPointFPropertyManagerPrivate::Data::decimals, property, 0); -} - -/*! - \reimp -*/ -QString QtPointFPropertyManager::valueText(const QtProperty *property) const -{ - const QtPointFPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - const QPointF v = it.value().val; - const int dec = it.value().decimals; - return QString(tr("(%1, %2)").arg(QString::number(v.x(), 'f', dec)) - .arg(QString::number(v.y(), 'f', dec))); -} - -/*! - \fn void QtPointFPropertyManager::setValue(QtProperty *property, const QPointF &value) - - Sets the value of the given \a property to \a value. Nested - properties are updated automatically. - - \sa value(), valueChanged() -*/ -void QtPointFPropertyManager::setValue(QtProperty *property, const QPointF &val) -{ - const QtPointFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - if (it.value().val == val) - return; - - it.value().val = val; - d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToX[property], val.x()); - d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToY[property], val.y()); - - emit propertyChanged(property); - emit valueChanged(property, val); -} - -/*! - Sets the step value for the given \a property to \a step. - - The step is typically used to increment or decrement a property value while pressing an arrow key. - - \sa singleStep() -*/ -void QtPointFPropertyManager::setSingleStep(QtProperty *property, double step) -{ - const QtPointFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtPointFPropertyManagerPrivate::Data data = it.value(); - - if (step < 0) - step = 0; - - if (data.singleStep == step) - return; - - data.singleStep = step; - d_ptr->m_doublePropertyManager->setSingleStep(d_ptr->m_propertyToX[property], step); - d_ptr->m_doublePropertyManager->setSingleStep(d_ptr->m_propertyToY[property], step); - - it.value() = data; - - emit singleStepChanged(property, data.singleStep); -} - -/*! - \fn void QtPointFPropertyManager::setDecimals(QtProperty *property, int prec) - - Sets the precision of the given \a property to \a prec. - - The valid decimal range is 0-13. The default is 2. - - \sa decimals() -*/ -void QtPointFPropertyManager::setDecimals(QtProperty *property, int prec) -{ - const QtPointFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtPointFPropertyManagerPrivate::Data data = it.value(); - - if (prec > 13) - prec = 13; - else if (prec < 0) - prec = 0; - - if (data.decimals == prec) - return; - - data.decimals = prec; - d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToX[property], prec); - d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToY[property], prec); - - it.value() = data; - - emit decimalsChanged(property, data.decimals); -} - -/*! - \reimp -*/ -void QtPointFPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtPointFPropertyManagerPrivate::Data(); - - QtProperty *xProp = d_ptr->m_doublePropertyManager->addProperty(); - xProp->setPropertyName(tr("X")); - d_ptr->m_doublePropertyManager->setDecimals(xProp, decimals(property)); - d_ptr->m_doublePropertyManager->setValue(xProp, 0); - d_ptr->m_propertyToX[property] = xProp; - d_ptr->m_xToProperty[xProp] = property; - property->addSubProperty(xProp); - - QtProperty *yProp = d_ptr->m_doublePropertyManager->addProperty(); - yProp->setPropertyName(tr("Y")); - d_ptr->m_doublePropertyManager->setDecimals(yProp, decimals(property)); - d_ptr->m_doublePropertyManager->setValue(yProp, 0); - d_ptr->m_propertyToY[property] = yProp; - d_ptr->m_yToProperty[yProp] = property; - property->addSubProperty(yProp); -} - -/*! - \reimp -*/ -void QtPointFPropertyManager::uninitializeProperty(QtProperty *property) -{ - QtProperty *xProp = d_ptr->m_propertyToX[property]; - if (xProp) { - d_ptr->m_xToProperty.remove(xProp); - delete xProp; - } - d_ptr->m_propertyToX.remove(property); - - QtProperty *yProp = d_ptr->m_propertyToY[property]; - if (yProp) { - d_ptr->m_yToProperty.remove(yProp); - delete yProp; - } - d_ptr->m_propertyToY.remove(property); - - d_ptr->m_values.remove(property); -} - -// QtSizePropertyManager - -class QtSizePropertyManagerPrivate -{ - QtSizePropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtSizePropertyManager) -public: - - void slotIntChanged(QtProperty *property, int value); - void slotPropertyDestroyed(QtProperty *property); - void setValue(QtProperty *property, const QSize &val); - void setRange(QtProperty *property, - const QSize &minVal, const QSize &maxVal, const QSize &val); - - struct Data - { - Data() : val(QSize(0, 0)), minVal(QSize(0, 0)), maxVal(QSize(INT_MAX, INT_MAX)) {} - QSize val; - QSize minVal; - QSize maxVal; - QSize minimumValue() const { return minVal; } - QSize maximumValue() const { return maxVal; } - void setMinimumValue(const QSize &newMinVal) { setSizeMinimumData(this, newMinVal); } - void setMaximumValue(const QSize &newMaxVal) { setSizeMaximumData(this, newMaxVal); } - }; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - QtIntPropertyManager *m_intPropertyManager; - - QMap m_propertyToW; - QMap m_propertyToH; - - QMap m_wToProperty; - QMap m_hToProperty; -}; - -void QtSizePropertyManagerPrivate::slotIntChanged(QtProperty *property, int value) -{ - if (QtProperty *prop = m_wToProperty.value(property, 0)) { - QSize s = m_values[prop].val; - s.setWidth(value); - q_ptr->setValue(prop, s); - } else if (QtProperty *prop = m_hToProperty.value(property, 0)) { - QSize s = m_values[prop].val; - s.setHeight(value); - q_ptr->setValue(prop, s); - } -} - -void QtSizePropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) -{ - if (QtProperty *pointProp = m_wToProperty.value(property, 0)) { - m_propertyToW[pointProp] = 0; - m_wToProperty.remove(property); - } else if (QtProperty *pointProp = m_hToProperty.value(property, 0)) { - m_propertyToH[pointProp] = 0; - m_hToProperty.remove(property); - } -} - -void QtSizePropertyManagerPrivate::setValue(QtProperty *property, const QSize &val) -{ - m_intPropertyManager->setValue(m_propertyToW.value(property), val.width()); - m_intPropertyManager->setValue(m_propertyToH.value(property), val.height()); -} - -void QtSizePropertyManagerPrivate::setRange(QtProperty *property, - const QSize &minVal, const QSize &maxVal, const QSize &val) -{ - QtProperty *wProperty = m_propertyToW.value(property); - QtProperty *hProperty = m_propertyToH.value(property); - m_intPropertyManager->setRange(wProperty, minVal.width(), maxVal.width()); - m_intPropertyManager->setValue(wProperty, val.width()); - m_intPropertyManager->setRange(hProperty, minVal.height(), maxVal.height()); - m_intPropertyManager->setValue(hProperty, val.height()); -} - -/*! - \class QtSizePropertyManager - - \brief The QtSizePropertyManager provides and manages QSize properties. - - A size property has nested \e width and \e height - subproperties. The top-level property's value can be retrieved - using the value() function, and set using the setValue() slot. - - The subproperties are created by a QtIntPropertyManager object. This - manager can be retrieved using the subIntPropertyManager() function. In - order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - A size property also has a range of valid values defined by a - minimum size and a maximum size. These sizes can be retrieved - using the minimum() and the maximum() functions, and set using the - setMinimum() and setMaximum() slots. Alternatively, the range can - be defined in one go using the setRange() slot. - - In addition, QtSizePropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes, and the rangeChanged() signal which is emitted whenever - such a property changes its range of valid sizes. - - \sa QtAbstractPropertyManager, QtIntPropertyManager, QtSizeFPropertyManager -*/ - -/*! - \fn void QtSizePropertyManager::valueChanged(QtProperty *property, const QSize &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtSizePropertyManager::rangeChanged(QtProperty *property, const QSize &minimum, const QSize &maximum) - - This signal is emitted whenever a property created by this manager - changes its range of valid sizes, passing a pointer to the \a - property and the new \a minimum and \a maximum sizes. - - \sa setRange() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtSizePropertyManager::QtSizePropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtSizePropertyManagerPrivate; - d_ptr->q_ptr = this; - - d_ptr->m_intPropertyManager = new QtIntPropertyManager(this); - connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotIntChanged(QtProperty *, int))); - connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtSizePropertyManager::~QtSizePropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the manager that creates the nested \e width and \e height - subproperties. - - In order to provide editing widgets for the \e width and \e height - properties in a property browser widget, this manager must be - associated with an editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtIntPropertyManager *QtSizePropertyManager::subIntPropertyManager() const -{ - return d_ptr->m_intPropertyManager; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns an invalid size - - \sa setValue() -*/ -QSize QtSizePropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property); -} - -/*! - Returns the given \a property's minimum size value. - - \sa setMinimum(), maximum(), setRange() -*/ -QSize QtSizePropertyManager::minimum(const QtProperty *property) const -{ - return getMinimum(d_ptr->m_values, property); -} - -/*! - Returns the given \a property's maximum size value. - - \sa setMaximum(), minimum(), setRange() -*/ -QSize QtSizePropertyManager::maximum(const QtProperty *property) const -{ - return getMaximum(d_ptr->m_values, property); -} - -/*! - \reimp -*/ -QString QtSizePropertyManager::valueText(const QtProperty *property) const -{ - const QtSizePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - const QSize v = it.value().val; - return QString(tr("%1 x %2").arg(QString::number(v.width())) - .arg(QString::number(v.height()))); -} - -/*! - \fn void QtSizePropertyManager::setValue(QtProperty *property, const QSize &value) - - Sets the value of the given \a property to \a value. - - If the specified \a value is not valid according to the given \a - property's size range, the \a value is adjusted to the nearest - valid value within the size range. - - \sa value(), setRange(), valueChanged() -*/ -void QtSizePropertyManager::setValue(QtProperty *property, const QSize &val) -{ - setValueInRange(this, d_ptr, - &QtSizePropertyManager::propertyChanged, - &QtSizePropertyManager::valueChanged, - property, val, &QtSizePropertyManagerPrivate::setValue); -} - -/*! - Sets the minimum size value for the given \a property to \a minVal. - - When setting the minimum size value, the maximum and current - values are adjusted if necessary (ensuring that the size range - remains valid and that the current value is within the range). - - \sa minimum(), setRange(), rangeChanged() -*/ -void QtSizePropertyManager::setMinimum(QtProperty *property, const QSize &minVal) -{ - setBorderValue(this, d_ptr, - &QtSizePropertyManager::propertyChanged, - &QtSizePropertyManager::valueChanged, - &QtSizePropertyManager::rangeChanged, - property, - &QtSizePropertyManagerPrivate::Data::minimumValue, - &QtSizePropertyManagerPrivate::Data::setMinimumValue, - minVal, &QtSizePropertyManagerPrivate::setRange); -} - -/*! - Sets the maximum size value for the given \a property to \a maxVal. - - When setting the maximum size value, the minimum and current - values are adjusted if necessary (ensuring that the size range - remains valid and that the current value is within the range). - - \sa maximum(), setRange(), rangeChanged() -*/ -void QtSizePropertyManager::setMaximum(QtProperty *property, const QSize &maxVal) -{ - setBorderValue(this, d_ptr, - &QtSizePropertyManager::propertyChanged, - &QtSizePropertyManager::valueChanged, - &QtSizePropertyManager::rangeChanged, - property, - &QtSizePropertyManagerPrivate::Data::maximumValue, - &QtSizePropertyManagerPrivate::Data::setMaximumValue, - maxVal, &QtSizePropertyManagerPrivate::setRange); -} - -/*! - \fn void QtSizePropertyManager::setRange(QtProperty *property, const QSize &minimum, const QSize &maximum) - - Sets the range of valid values. - - This is a convenience function defining the range of valid values - in one go; setting the \a minimum and \a maximum values for the - given \a property with a single function call. - - When setting a new range, the current value is adjusted if - necessary (ensuring that the value remains within the range). - - \sa setMinimum(), setMaximum(), rangeChanged() -*/ -void QtSizePropertyManager::setRange(QtProperty *property, const QSize &minVal, const QSize &maxVal) -{ - setBorderValues(this, d_ptr, - &QtSizePropertyManager::propertyChanged, - &QtSizePropertyManager::valueChanged, - &QtSizePropertyManager::rangeChanged, - property, minVal, maxVal, &QtSizePropertyManagerPrivate::setRange); -} - -/*! - \reimp -*/ -void QtSizePropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtSizePropertyManagerPrivate::Data(); - - QtProperty *wProp = d_ptr->m_intPropertyManager->addProperty(); - wProp->setPropertyName(tr("Width")); - d_ptr->m_intPropertyManager->setValue(wProp, 0); - d_ptr->m_intPropertyManager->setMinimum(wProp, 0); - d_ptr->m_propertyToW[property] = wProp; - d_ptr->m_wToProperty[wProp] = property; - property->addSubProperty(wProp); - - QtProperty *hProp = d_ptr->m_intPropertyManager->addProperty(); - hProp->setPropertyName(tr("Height")); - d_ptr->m_intPropertyManager->setValue(hProp, 0); - d_ptr->m_intPropertyManager->setMinimum(hProp, 0); - d_ptr->m_propertyToH[property] = hProp; - d_ptr->m_hToProperty[hProp] = property; - property->addSubProperty(hProp); -} - -/*! - \reimp -*/ -void QtSizePropertyManager::uninitializeProperty(QtProperty *property) -{ - QtProperty *wProp = d_ptr->m_propertyToW[property]; - if (wProp) { - d_ptr->m_wToProperty.remove(wProp); - delete wProp; - } - d_ptr->m_propertyToW.remove(property); - - QtProperty *hProp = d_ptr->m_propertyToH[property]; - if (hProp) { - d_ptr->m_hToProperty.remove(hProp); - delete hProp; - } - d_ptr->m_propertyToH.remove(property); - - d_ptr->m_values.remove(property); -} - -// QtSizeFPropertyManager - -class QtSizeFPropertyManagerPrivate -{ - QtSizeFPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtSizeFPropertyManager) -public: - - void slotDoubleChanged(QtProperty *property, double value); - void slotPropertyDestroyed(QtProperty *property); - void setValue(QtProperty *property, const QSizeF &val); - void setRange(QtProperty *property, - const QSizeF &minVal, const QSizeF &maxVal, const QSizeF &val); - - struct Data - { - Data() : val(QSizeF(0, 0)), minVal(QSizeF(0, 0)), maxVal(QSizeF(INT_MAX, INT_MAX)), decimals(2) {} - QSizeF val; - QSizeF minVal; - QSizeF maxVal; - int decimals; - QSizeF minimumValue() const { return minVal; } - QSizeF maximumValue() const { return maxVal; } - void setMinimumValue(const QSizeF &newMinVal) { setSizeMinimumData(this, newMinVal); } - void setMaximumValue(const QSizeF &newMaxVal) { setSizeMaximumData(this, newMaxVal); } - }; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - QtDoublePropertyManager *m_doublePropertyManager; - - QMap m_propertyToW; - QMap m_propertyToH; - - QMap m_wToProperty; - QMap m_hToProperty; -}; - -void QtSizeFPropertyManagerPrivate::slotDoubleChanged(QtProperty *property, double value) -{ - if (QtProperty *prop = m_wToProperty.value(property, 0)) { - QSizeF s = m_values[prop].val; - s.setWidth(value); - q_ptr->setValue(prop, s); - } else if (QtProperty *prop = m_hToProperty.value(property, 0)) { - QSizeF s = m_values[prop].val; - s.setHeight(value); - q_ptr->setValue(prop, s); - } -} - -void QtSizeFPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) -{ - if (QtProperty *pointProp = m_wToProperty.value(property, 0)) { - m_propertyToW[pointProp] = 0; - m_wToProperty.remove(property); - } else if (QtProperty *pointProp = m_hToProperty.value(property, 0)) { - m_propertyToH[pointProp] = 0; - m_hToProperty.remove(property); - } -} - -void QtSizeFPropertyManagerPrivate::setValue(QtProperty *property, const QSizeF &val) -{ - m_doublePropertyManager->setValue(m_propertyToW.value(property), val.width()); - m_doublePropertyManager->setValue(m_propertyToH.value(property), val.height()); -} - -void QtSizeFPropertyManagerPrivate::setRange(QtProperty *property, - const QSizeF &minVal, const QSizeF &maxVal, const QSizeF &val) -{ - m_doublePropertyManager->setRange(m_propertyToW[property], minVal.width(), maxVal.width()); - m_doublePropertyManager->setValue(m_propertyToW[property], val.width()); - m_doublePropertyManager->setRange(m_propertyToH[property], minVal.height(), maxVal.height()); - m_doublePropertyManager->setValue(m_propertyToH[property], val.height()); -} - -/*! - \class QtSizeFPropertyManager - - \brief The QtSizeFPropertyManager provides and manages QSizeF properties. - - A size property has nested \e width and \e height - subproperties. The top-level property's value can be retrieved - using the value() function, and set using the setValue() slot. - - The subproperties are created by a QtDoublePropertyManager object. This - manager can be retrieved using the subDoublePropertyManager() function. In - order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - A size property also has a range of valid values defined by a - minimum size and a maximum size. These sizes can be retrieved - using the minimum() and the maximum() functions, and set using the - setMinimum() and setMaximum() slots. Alternatively, the range can - be defined in one go using the setRange() slot. - - In addition, QtSizeFPropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes, and the rangeChanged() signal which is emitted whenever - such a property changes its range of valid sizes. - - \sa QtAbstractPropertyManager, QtDoublePropertyManager, QtSizePropertyManager -*/ - -/*! - \fn void QtSizeFPropertyManager::valueChanged(QtProperty *property, const QSizeF &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtSizeFPropertyManager::rangeChanged(QtProperty *property, const QSizeF &minimum, const QSizeF &maximum) - - This signal is emitted whenever a property created by this manager - changes its range of valid sizes, passing a pointer to the \a - property and the new \a minimum and \a maximum sizes. - - \sa setRange() -*/ - -/*! - \fn void QtSizeFPropertyManager::decimalsChanged(QtProperty *property, int prec) - - This signal is emitted whenever a property created by this manager - changes its precision of value, passing a pointer to the - \a property and the new \a prec value - - \sa setDecimals() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtSizeFPropertyManager::QtSizeFPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtSizeFPropertyManagerPrivate; - d_ptr->q_ptr = this; - - d_ptr->m_doublePropertyManager = new QtDoublePropertyManager(this); - connect(d_ptr->m_doublePropertyManager, SIGNAL(valueChanged(QtProperty *, double)), - this, SLOT(slotDoubleChanged(QtProperty *, double))); - connect(d_ptr->m_doublePropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtSizeFPropertyManager::~QtSizeFPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the manager that creates the nested \e width and \e height - subproperties. - - In order to provide editing widgets for the \e width and \e height - properties in a property browser widget, this manager must be - associated with an editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtDoublePropertyManager *QtSizeFPropertyManager::subDoublePropertyManager() const -{ - return d_ptr->m_doublePropertyManager; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns an invalid size - - \sa setValue() -*/ -QSizeF QtSizeFPropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property); -} - -/*! - Returns the given \a property's precision, in decimals. - - \sa setDecimals() -*/ -int QtSizeFPropertyManager::decimals(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtSizeFPropertyManagerPrivate::Data::decimals, property, 0); -} - -/*! - Returns the given \a property's minimum size value. - - \sa setMinimum(), maximum(), setRange() -*/ -QSizeF QtSizeFPropertyManager::minimum(const QtProperty *property) const -{ - return getMinimum(d_ptr->m_values, property); -} - -/*! - Returns the given \a property's maximum size value. - - \sa setMaximum(), minimum(), setRange() -*/ -QSizeF QtSizeFPropertyManager::maximum(const QtProperty *property) const -{ - return getMaximum(d_ptr->m_values, property); -} - -/*! - \reimp -*/ -QString QtSizeFPropertyManager::valueText(const QtProperty *property) const -{ - const QtSizeFPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - const QSizeF v = it.value().val; - const int dec = it.value().decimals; - return QString(tr("%1 x %2").arg(QString::number(v.width(), 'f', dec)) - .arg(QString::number(v.height(), 'f', dec))); -} - -/*! - \fn void QtSizeFPropertyManager::setValue(QtProperty *property, const QSizeF &value) - - Sets the value of the given \a property to \a value. - - If the specified \a value is not valid according to the given \a - property's size range, the \a value is adjusted to the nearest - valid value within the size range. - - \sa value(), setRange(), valueChanged() -*/ -void QtSizeFPropertyManager::setValue(QtProperty *property, const QSizeF &val) -{ - setValueInRange(this, d_ptr, - &QtSizeFPropertyManager::propertyChanged, - &QtSizeFPropertyManager::valueChanged, - property, val, &QtSizeFPropertyManagerPrivate::setValue); -} - -/*! - \fn void QtSizeFPropertyManager::setDecimals(QtProperty *property, int prec) - - Sets the precision of the given \a property to \a prec. - - The valid decimal range is 0-13. The default is 2. - - \sa decimals() -*/ -void QtSizeFPropertyManager::setDecimals(QtProperty *property, int prec) -{ - const QtSizeFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtSizeFPropertyManagerPrivate::Data data = it.value(); - - if (prec > 13) - prec = 13; - else if (prec < 0) - prec = 0; - - if (data.decimals == prec) - return; - - data.decimals = prec; - d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToW[property], prec); - d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToH[property], prec); - - it.value() = data; - - emit decimalsChanged(property, data.decimals); -} - -/*! - Sets the minimum size value for the given \a property to \a minVal. - - When setting the minimum size value, the maximum and current - values are adjusted if necessary (ensuring that the size range - remains valid and that the current value is within the range). - - \sa minimum(), setRange(), rangeChanged() -*/ -void QtSizeFPropertyManager::setMinimum(QtProperty *property, const QSizeF &minVal) -{ - setBorderValue(this, d_ptr, - &QtSizeFPropertyManager::propertyChanged, - &QtSizeFPropertyManager::valueChanged, - &QtSizeFPropertyManager::rangeChanged, - property, - &QtSizeFPropertyManagerPrivate::Data::minimumValue, - &QtSizeFPropertyManagerPrivate::Data::setMinimumValue, - minVal, &QtSizeFPropertyManagerPrivate::setRange); -} - -/*! - Sets the maximum size value for the given \a property to \a maxVal. - - When setting the maximum size value, the minimum and current - values are adjusted if necessary (ensuring that the size range - remains valid and that the current value is within the range). - - \sa maximum(), setRange(), rangeChanged() -*/ -void QtSizeFPropertyManager::setMaximum(QtProperty *property, const QSizeF &maxVal) -{ - setBorderValue(this, d_ptr, - &QtSizeFPropertyManager::propertyChanged, - &QtSizeFPropertyManager::valueChanged, - &QtSizeFPropertyManager::rangeChanged, - property, - &QtSizeFPropertyManagerPrivate::Data::maximumValue, - &QtSizeFPropertyManagerPrivate::Data::setMaximumValue, - maxVal, &QtSizeFPropertyManagerPrivate::setRange); -} - -/*! - \fn void QtSizeFPropertyManager::setRange(QtProperty *property, const QSizeF &minimum, const QSizeF &maximum) - - Sets the range of valid values. - - This is a convenience function defining the range of valid values - in one go; setting the \a minimum and \a maximum values for the - given \a property with a single function call. - - When setting a new range, the current value is adjusted if - necessary (ensuring that the value remains within the range). - - \sa setMinimum(), setMaximum(), rangeChanged() -*/ -void QtSizeFPropertyManager::setRange(QtProperty *property, const QSizeF &minVal, const QSizeF &maxVal) -{ - setBorderValues(this, d_ptr, - &QtSizeFPropertyManager::propertyChanged, - &QtSizeFPropertyManager::valueChanged, - &QtSizeFPropertyManager::rangeChanged, - property, minVal, maxVal, &QtSizeFPropertyManagerPrivate::setRange); -} - -/*! - \reimp -*/ -void QtSizeFPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtSizeFPropertyManagerPrivate::Data(); - - QtProperty *wProp = d_ptr->m_doublePropertyManager->addProperty(); - wProp->setPropertyName(tr("Width")); - d_ptr->m_doublePropertyManager->setDecimals(wProp, decimals(property)); - d_ptr->m_doublePropertyManager->setValue(wProp, 0); - d_ptr->m_doublePropertyManager->setMinimum(wProp, 0); - d_ptr->m_propertyToW[property] = wProp; - d_ptr->m_wToProperty[wProp] = property; - property->addSubProperty(wProp); - - QtProperty *hProp = d_ptr->m_doublePropertyManager->addProperty(); - hProp->setPropertyName(tr("Height")); - d_ptr->m_doublePropertyManager->setDecimals(hProp, decimals(property)); - d_ptr->m_doublePropertyManager->setValue(hProp, 0); - d_ptr->m_doublePropertyManager->setMinimum(hProp, 0); - d_ptr->m_propertyToH[property] = hProp; - d_ptr->m_hToProperty[hProp] = property; - property->addSubProperty(hProp); -} - -/*! - \reimp -*/ -void QtSizeFPropertyManager::uninitializeProperty(QtProperty *property) -{ - QtProperty *wProp = d_ptr->m_propertyToW[property]; - if (wProp) { - d_ptr->m_wToProperty.remove(wProp); - delete wProp; - } - d_ptr->m_propertyToW.remove(property); - - QtProperty *hProp = d_ptr->m_propertyToH[property]; - if (hProp) { - d_ptr->m_hToProperty.remove(hProp); - delete hProp; - } - d_ptr->m_propertyToH.remove(property); - - d_ptr->m_values.remove(property); -} - -// QtRectPropertyManager - -class QtRectPropertyManagerPrivate -{ - QtRectPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtRectPropertyManager) -public: - - void slotIntChanged(QtProperty *property, int value); - void slotPropertyDestroyed(QtProperty *property); - void setConstraint(QtProperty *property, const QRect &constraint, const QRect &val); - - struct Data - { - Data() : val(0, 0, 0, 0) {} - QRect val; - QRect constraint; - }; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - QtIntPropertyManager *m_intPropertyManager; - - QMap m_propertyToX; - QMap m_propertyToY; - QMap m_propertyToW; - QMap m_propertyToH; - - QMap m_xToProperty; - QMap m_yToProperty; - QMap m_wToProperty; - QMap m_hToProperty; -}; - -void QtRectPropertyManagerPrivate::slotIntChanged(QtProperty *property, int value) -{ - if (QtProperty *prop = m_xToProperty.value(property, 0)) { - QRect r = m_values[prop].val; - r.moveLeft(value); - q_ptr->setValue(prop, r); - } else if (QtProperty *prop = m_yToProperty.value(property)) { - QRect r = m_values[prop].val; - r.moveTop(value); - q_ptr->setValue(prop, r); - } else if (QtProperty *prop = m_wToProperty.value(property, 0)) { - Data data = m_values[prop]; - QRect r = data.val; - r.setWidth(value); - if (!data.constraint.isNull() && data.constraint.x() + data.constraint.width() < r.x() + r.width()) { - r.moveLeft(data.constraint.left() + data.constraint.width() - r.width()); - } - q_ptr->setValue(prop, r); - } else if (QtProperty *prop = m_hToProperty.value(property, 0)) { - Data data = m_values[prop]; - QRect r = data.val; - r.setHeight(value); - if (!data.constraint.isNull() && data.constraint.y() + data.constraint.height() < r.y() + r.height()) { - r.moveTop(data.constraint.top() + data.constraint.height() - r.height()); - } - q_ptr->setValue(prop, r); - } -} - -void QtRectPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) -{ - if (QtProperty *pointProp = m_xToProperty.value(property, 0)) { - m_propertyToX[pointProp] = 0; - m_xToProperty.remove(property); - } else if (QtProperty *pointProp = m_yToProperty.value(property, 0)) { - m_propertyToY[pointProp] = 0; - m_yToProperty.remove(property); - } else if (QtProperty *pointProp = m_wToProperty.value(property, 0)) { - m_propertyToW[pointProp] = 0; - m_wToProperty.remove(property); - } else if (QtProperty *pointProp = m_hToProperty.value(property, 0)) { - m_propertyToH[pointProp] = 0; - m_hToProperty.remove(property); - } -} - -void QtRectPropertyManagerPrivate::setConstraint(QtProperty *property, - const QRect &constraint, const QRect &val) -{ - const bool isNull = constraint.isNull(); - const int left = isNull ? INT_MIN : constraint.left(); - const int right = isNull ? INT_MAX : constraint.left() + constraint.width(); - const int top = isNull ? INT_MIN : constraint.top(); - const int bottom = isNull ? INT_MAX : constraint.top() + constraint.height(); - const int width = isNull ? INT_MAX : constraint.width(); - const int height = isNull ? INT_MAX : constraint.height(); - - m_intPropertyManager->setRange(m_propertyToX[property], left, right); - m_intPropertyManager->setRange(m_propertyToY[property], top, bottom); - m_intPropertyManager->setRange(m_propertyToW[property], 0, width); - m_intPropertyManager->setRange(m_propertyToH[property], 0, height); - - m_intPropertyManager->setValue(m_propertyToX[property], val.x()); - m_intPropertyManager->setValue(m_propertyToY[property], val.y()); - m_intPropertyManager->setValue(m_propertyToW[property], val.width()); - m_intPropertyManager->setValue(m_propertyToH[property], val.height()); -} - -/*! - \class QtRectPropertyManager - - \brief The QtRectPropertyManager provides and manages QRect properties. - - A rectangle property has nested \e x, \e y, \e width and \e height - subproperties. The top-level property's value can be retrieved - using the value() function, and set using the setValue() slot. - - The subproperties are created by a QtIntPropertyManager object. This - manager can be retrieved using the subIntPropertyManager() function. In - order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - A rectangle property also has a constraint rectangle which can be - retrieved using the constraint() function, and set using the - setConstraint() slot. - - In addition, QtRectPropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes, and the constraintChanged() signal which is emitted - whenever such a property changes its constraint rectangle. - - \sa QtAbstractPropertyManager, QtIntPropertyManager, QtRectFPropertyManager -*/ - -/*! - \fn void QtRectPropertyManager::valueChanged(QtProperty *property, const QRect &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtRectPropertyManager::constraintChanged(QtProperty *property, const QRect &constraint) - - This signal is emitted whenever property changes its constraint - rectangle, passing a pointer to the \a property and the new \a - constraint rectangle as parameters. - - \sa setConstraint() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtRectPropertyManager::QtRectPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtRectPropertyManagerPrivate; - d_ptr->q_ptr = this; - - d_ptr->m_intPropertyManager = new QtIntPropertyManager(this); - connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotIntChanged(QtProperty *, int))); - connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtRectPropertyManager::~QtRectPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the manager that creates the nested \e x, \e y, \e width - and \e height subproperties. - - In order to provide editing widgets for the mentioned - subproperties in a property browser widget, this manager must be - associated with an editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtIntPropertyManager *QtRectPropertyManager::subIntPropertyManager() const -{ - return d_ptr->m_intPropertyManager; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns an invalid rectangle. - - \sa setValue(), constraint() -*/ -QRect QtRectPropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property); -} - -/*! - Returns the given \a property's constraining rectangle. If returned value is null QRect it means there is no constraint applied. - - \sa value(), setConstraint() -*/ -QRect QtRectPropertyManager::constraint(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtRectPropertyManagerPrivate::Data::constraint, property, QRect()); -} - -/*! - \reimp -*/ -QString QtRectPropertyManager::valueText(const QtProperty *property) const -{ - const QtRectPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - const QRect v = it.value().val; - return QString(tr("[(%1, %2), %3 x %4]").arg(QString::number(v.x())) - .arg(QString::number(v.y())) - .arg(QString::number(v.width())) - .arg(QString::number(v.height()))); -} - -/*! - \fn void QtRectPropertyManager::setValue(QtProperty *property, const QRect &value) - - Sets the value of the given \a property to \a value. Nested - properties are updated automatically. - - If the specified \a value is not inside the given \a property's - constraining rectangle, the value is adjusted accordingly to fit - within the constraint. - - \sa value(), setConstraint(), valueChanged() -*/ -void QtRectPropertyManager::setValue(QtProperty *property, const QRect &val) -{ - const QtRectPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtRectPropertyManagerPrivate::Data data = it.value(); - - QRect newRect = val.normalized(); - if (!data.constraint.isNull() && !data.constraint.contains(newRect)) { - const QRect r1 = data.constraint; - const QRect r2 = newRect; - newRect.setLeft(qMax(r1.left(), r2.left())); - newRect.setRight(qMin(r1.right(), r2.right())); - newRect.setTop(qMax(r1.top(), r2.top())); - newRect.setBottom(qMin(r1.bottom(), r2.bottom())); - if (newRect.width() < 0 || newRect.height() < 0) - return; - } - - if (data.val == newRect) - return; - - data.val = newRect; - - it.value() = data; - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToX[property], newRect.x()); - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToY[property], newRect.y()); - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToW[property], newRect.width()); - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToH[property], newRect.height()); - - emit propertyChanged(property); - emit valueChanged(property, data.val); -} - -/*! - Sets the given \a property's constraining rectangle to \a - constraint. - - When setting the constraint, the current value is adjusted if - necessary (ensuring that the current rectangle value is inside the - constraint). In order to reset the constraint pass a null QRect value. - - \sa setValue(), constraint(), constraintChanged() -*/ -void QtRectPropertyManager::setConstraint(QtProperty *property, const QRect &constraint) -{ - const QtRectPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtRectPropertyManagerPrivate::Data data = it.value(); - - QRect newConstraint = constraint.normalized(); - if (data.constraint == newConstraint) - return; - - const QRect oldVal = data.val; - - data.constraint = newConstraint; - - if (!data.constraint.isNull() && !data.constraint.contains(oldVal)) { - QRect r1 = data.constraint; - QRect r2 = data.val; - - if (r2.width() > r1.width()) - r2.setWidth(r1.width()); - if (r2.height() > r1.height()) - r2.setHeight(r1.height()); - if (r2.left() < r1.left()) - r2.moveLeft(r1.left()); - else if (r2.right() > r1.right()) - r2.moveRight(r1.right()); - if (r2.top() < r1.top()) - r2.moveTop(r1.top()); - else if (r2.bottom() > r1.bottom()) - r2.moveBottom(r1.bottom()); - - data.val = r2; - } - - it.value() = data; - - emit constraintChanged(property, data.constraint); - - d_ptr->setConstraint(property, data.constraint, data.val); - - if (data.val == oldVal) - return; - - emit propertyChanged(property); - emit valueChanged(property, data.val); -} - -/*! - \reimp -*/ -void QtRectPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtRectPropertyManagerPrivate::Data(); - - QtProperty *xProp = d_ptr->m_intPropertyManager->addProperty(); - xProp->setPropertyName(tr("X")); - d_ptr->m_intPropertyManager->setValue(xProp, 0); - d_ptr->m_propertyToX[property] = xProp; - d_ptr->m_xToProperty[xProp] = property; - property->addSubProperty(xProp); - - QtProperty *yProp = d_ptr->m_intPropertyManager->addProperty(); - yProp->setPropertyName(tr("Y")); - d_ptr->m_intPropertyManager->setValue(yProp, 0); - d_ptr->m_propertyToY[property] = yProp; - d_ptr->m_yToProperty[yProp] = property; - property->addSubProperty(yProp); - - QtProperty *wProp = d_ptr->m_intPropertyManager->addProperty(); - wProp->setPropertyName(tr("Width")); - d_ptr->m_intPropertyManager->setValue(wProp, 0); - d_ptr->m_intPropertyManager->setMinimum(wProp, 0); - d_ptr->m_propertyToW[property] = wProp; - d_ptr->m_wToProperty[wProp] = property; - property->addSubProperty(wProp); - - QtProperty *hProp = d_ptr->m_intPropertyManager->addProperty(); - hProp->setPropertyName(tr("Height")); - d_ptr->m_intPropertyManager->setValue(hProp, 0); - d_ptr->m_intPropertyManager->setMinimum(hProp, 0); - d_ptr->m_propertyToH[property] = hProp; - d_ptr->m_hToProperty[hProp] = property; - property->addSubProperty(hProp); -} - -/*! - \reimp -*/ -void QtRectPropertyManager::uninitializeProperty(QtProperty *property) -{ - QtProperty *xProp = d_ptr->m_propertyToX[property]; - if (xProp) { - d_ptr->m_xToProperty.remove(xProp); - delete xProp; - } - d_ptr->m_propertyToX.remove(property); - - QtProperty *yProp = d_ptr->m_propertyToY[property]; - if (yProp) { - d_ptr->m_yToProperty.remove(yProp); - delete yProp; - } - d_ptr->m_propertyToY.remove(property); - - QtProperty *wProp = d_ptr->m_propertyToW[property]; - if (wProp) { - d_ptr->m_wToProperty.remove(wProp); - delete wProp; - } - d_ptr->m_propertyToW.remove(property); - - QtProperty *hProp = d_ptr->m_propertyToH[property]; - if (hProp) { - d_ptr->m_hToProperty.remove(hProp); - delete hProp; - } - d_ptr->m_propertyToH.remove(property); - - d_ptr->m_values.remove(property); -} - -// QtRectFPropertyManager - -class QtRectFPropertyManagerPrivate -{ - QtRectFPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtRectFPropertyManager) -public: - - void slotDoubleChanged(QtProperty *property, double value); - void slotPropertyDestroyed(QtProperty *property); - void setConstraint(QtProperty *property, const QRectF &constraint, const QRectF &val); - - struct Data - { - Data() : val(0, 0, 0, 0), decimals(2) {} - QRectF val; - QRectF constraint; - int decimals; - }; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - QtDoublePropertyManager *m_doublePropertyManager; - - QMap m_propertyToX; - QMap m_propertyToY; - QMap m_propertyToW; - QMap m_propertyToH; - - QMap m_xToProperty; - QMap m_yToProperty; - QMap m_wToProperty; - QMap m_hToProperty; -}; - -void QtRectFPropertyManagerPrivate::slotDoubleChanged(QtProperty *property, double value) -{ - if (QtProperty *prop = m_xToProperty.value(property, 0)) { - QRectF r = m_values[prop].val; - r.moveLeft(value); - q_ptr->setValue(prop, r); - } else if (QtProperty *prop = m_yToProperty.value(property, 0)) { - QRectF r = m_values[prop].val; - r.moveTop(value); - q_ptr->setValue(prop, r); - } else if (QtProperty *prop = m_wToProperty.value(property, 0)) { - Data data = m_values[prop]; - QRectF r = data.val; - r.setWidth(value); - if (!data.constraint.isNull() && data.constraint.x() + data.constraint.width() < r.x() + r.width()) { - r.moveLeft(data.constraint.left() + data.constraint.width() - r.width()); - } - q_ptr->setValue(prop, r); - } else if (QtProperty *prop = m_hToProperty.value(property, 0)) { - Data data = m_values[prop]; - QRectF r = data.val; - r.setHeight(value); - if (!data.constraint.isNull() && data.constraint.y() + data.constraint.height() < r.y() + r.height()) { - r.moveTop(data.constraint.top() + data.constraint.height() - r.height()); - } - q_ptr->setValue(prop, r); - } -} - -void QtRectFPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) -{ - if (QtProperty *pointProp = m_xToProperty.value(property, 0)) { - m_propertyToX[pointProp] = 0; - m_xToProperty.remove(property); - } else if (QtProperty *pointProp = m_yToProperty.value(property, 0)) { - m_propertyToY[pointProp] = 0; - m_yToProperty.remove(property); - } else if (QtProperty *pointProp = m_wToProperty.value(property, 0)) { - m_propertyToW[pointProp] = 0; - m_wToProperty.remove(property); - } else if (QtProperty *pointProp = m_hToProperty.value(property, 0)) { - m_propertyToH[pointProp] = 0; - m_hToProperty.remove(property); - } -} - -void QtRectFPropertyManagerPrivate::setConstraint(QtProperty *property, - const QRectF &constraint, const QRectF &val) -{ - const bool isNull = constraint.isNull(); - const float left = isNull ? FLT_MIN : constraint.left(); - const float right = isNull ? FLT_MAX : constraint.left() + constraint.width(); - const float top = isNull ? FLT_MIN : constraint.top(); - const float bottom = isNull ? FLT_MAX : constraint.top() + constraint.height(); - const float width = isNull ? FLT_MAX : constraint.width(); - const float height = isNull ? FLT_MAX : constraint.height(); - - m_doublePropertyManager->setRange(m_propertyToX[property], left, right); - m_doublePropertyManager->setRange(m_propertyToY[property], top, bottom); - m_doublePropertyManager->setRange(m_propertyToW[property], 0, width); - m_doublePropertyManager->setRange(m_propertyToH[property], 0, height); - - m_doublePropertyManager->setValue(m_propertyToX[property], val.x()); - m_doublePropertyManager->setValue(m_propertyToY[property], val.y()); - m_doublePropertyManager->setValue(m_propertyToW[property], val.width()); - m_doublePropertyManager->setValue(m_propertyToH[property], val.height()); -} - -/*! - \class QtRectFPropertyManager - - \brief The QtRectFPropertyManager provides and manages QRectF properties. - - A rectangle property has nested \e x, \e y, \e width and \e height - subproperties. The top-level property's value can be retrieved - using the value() function, and set using the setValue() slot. - - The subproperties are created by a QtDoublePropertyManager object. This - manager can be retrieved using the subDoublePropertyManager() function. In - order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - A rectangle property also has a constraint rectangle which can be - retrieved using the constraint() function, and set using the - setConstraint() slot. - - In addition, QtRectFPropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes, and the constraintChanged() signal which is emitted - whenever such a property changes its constraint rectangle. - - \sa QtAbstractPropertyManager, QtDoublePropertyManager, QtRectPropertyManager -*/ - -/*! - \fn void QtRectFPropertyManager::valueChanged(QtProperty *property, const QRectF &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtRectFPropertyManager::constraintChanged(QtProperty *property, const QRectF &constraint) - - This signal is emitted whenever property changes its constraint - rectangle, passing a pointer to the \a property and the new \a - constraint rectangle as parameters. - - \sa setConstraint() -*/ - -/*! - \fn void QtRectFPropertyManager::decimalsChanged(QtProperty *property, int prec) - - This signal is emitted whenever a property created by this manager - changes its precision of value, passing a pointer to the - \a property and the new \a prec value - - \sa setDecimals() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtRectFPropertyManager::QtRectFPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtRectFPropertyManagerPrivate; - d_ptr->q_ptr = this; - - d_ptr->m_doublePropertyManager = new QtDoublePropertyManager(this); - connect(d_ptr->m_doublePropertyManager, SIGNAL(valueChanged(QtProperty *, double)), - this, SLOT(slotDoubleChanged(QtProperty *, double))); - connect(d_ptr->m_doublePropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtRectFPropertyManager::~QtRectFPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the manager that creates the nested \e x, \e y, \e width - and \e height subproperties. - - In order to provide editing widgets for the mentioned - subproperties in a property browser widget, this manager must be - associated with an editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtDoublePropertyManager *QtRectFPropertyManager::subDoublePropertyManager() const -{ - return d_ptr->m_doublePropertyManager; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns an invalid rectangle. - - \sa setValue(), constraint() -*/ -QRectF QtRectFPropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property); -} - -/*! - Returns the given \a property's precision, in decimals. - - \sa setDecimals() -*/ -int QtRectFPropertyManager::decimals(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtRectFPropertyManagerPrivate::Data::decimals, property, 0); -} - -/*! - Returns the given \a property's constraining rectangle. If returned value is null QRectF it means there is no constraint applied. - - \sa value(), setConstraint() -*/ -QRectF QtRectFPropertyManager::constraint(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtRectFPropertyManagerPrivate::Data::constraint, property, QRect()); -} - -/*! - \reimp -*/ -QString QtRectFPropertyManager::valueText(const QtProperty *property) const -{ - const QtRectFPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - const QRectF v = it.value().val; - const int dec = it.value().decimals; - return QString(tr("[(%1, %2), %3 x %4]").arg(QString::number(v.x(), 'f', dec)) - .arg(QString::number(v.y(), 'f', dec)) - .arg(QString::number(v.width(), 'f', dec)) - .arg(QString::number(v.height(), 'f', dec))); -} - -/*! - \fn void QtRectFPropertyManager::setValue(QtProperty *property, const QRectF &value) - - Sets the value of the given \a property to \a value. Nested - properties are updated automatically. - - If the specified \a value is not inside the given \a property's - constraining rectangle, the value is adjusted accordingly to fit - within the constraint. - - \sa value(), setConstraint(), valueChanged() -*/ -void QtRectFPropertyManager::setValue(QtProperty *property, const QRectF &val) -{ - const QtRectFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtRectFPropertyManagerPrivate::Data data = it.value(); - - QRectF newRect = val.normalized(); - if (!data.constraint.isNull() && !data.constraint.contains(newRect)) { - const QRectF r1 = data.constraint; - const QRectF r2 = newRect; - newRect.setLeft(qMax(r1.left(), r2.left())); - newRect.setRight(qMin(r1.right(), r2.right())); - newRect.setTop(qMax(r1.top(), r2.top())); - newRect.setBottom(qMin(r1.bottom(), r2.bottom())); - if (newRect.width() < 0 || newRect.height() < 0) - return; - } - - if (data.val == newRect) - return; - - data.val = newRect; - - it.value() = data; - d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToX[property], newRect.x()); - d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToY[property], newRect.y()); - d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToW[property], newRect.width()); - d_ptr->m_doublePropertyManager->setValue(d_ptr->m_propertyToH[property], newRect.height()); - - emit propertyChanged(property); - emit valueChanged(property, data.val); -} - -/*! - Sets the given \a property's constraining rectangle to \a - constraint. - - When setting the constraint, the current value is adjusted if - necessary (ensuring that the current rectangle value is inside the - constraint). In order to reset the constraint pass a null QRectF value. - - \sa setValue(), constraint(), constraintChanged() -*/ -void QtRectFPropertyManager::setConstraint(QtProperty *property, const QRectF &constraint) -{ - const QtRectFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtRectFPropertyManagerPrivate::Data data = it.value(); - - QRectF newConstraint = constraint.normalized(); - if (data.constraint == newConstraint) - return; - - const QRectF oldVal = data.val; - - data.constraint = newConstraint; - - if (!data.constraint.isNull() && !data.constraint.contains(oldVal)) { - QRectF r1 = data.constraint; - QRectF r2 = data.val; - - if (r2.width() > r1.width()) - r2.setWidth(r1.width()); - if (r2.height() > r1.height()) - r2.setHeight(r1.height()); - if (r2.left() < r1.left()) - r2.moveLeft(r1.left()); - else if (r2.right() > r1.right()) - r2.moveRight(r1.right()); - if (r2.top() < r1.top()) - r2.moveTop(r1.top()); - else if (r2.bottom() > r1.bottom()) - r2.moveBottom(r1.bottom()); - - data.val = r2; - } - - it.value() = data; - - emit constraintChanged(property, data.constraint); - - d_ptr->setConstraint(property, data.constraint, data.val); - - if (data.val == oldVal) - return; - - emit propertyChanged(property); - emit valueChanged(property, data.val); -} - -/*! - \fn void QtRectFPropertyManager::setDecimals(QtProperty *property, int prec) - - Sets the precision of the given \a property to \a prec. - - The valid decimal range is 0-13. The default is 2. - - \sa decimals() -*/ -void QtRectFPropertyManager::setDecimals(QtProperty *property, int prec) -{ - const QtRectFPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtRectFPropertyManagerPrivate::Data data = it.value(); - - if (prec > 13) - prec = 13; - else if (prec < 0) - prec = 0; - - if (data.decimals == prec) - return; - - data.decimals = prec; - d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToX[property], prec); - d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToY[property], prec); - d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToW[property], prec); - d_ptr->m_doublePropertyManager->setDecimals(d_ptr->m_propertyToH[property], prec); - - it.value() = data; - - emit decimalsChanged(property, data.decimals); -} - -/*! - \reimp -*/ -void QtRectFPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtRectFPropertyManagerPrivate::Data(); - - QtProperty *xProp = d_ptr->m_doublePropertyManager->addProperty(); - xProp->setPropertyName(tr("X")); - d_ptr->m_doublePropertyManager->setDecimals(xProp, decimals(property)); - d_ptr->m_doublePropertyManager->setValue(xProp, 0); - d_ptr->m_propertyToX[property] = xProp; - d_ptr->m_xToProperty[xProp] = property; - property->addSubProperty(xProp); - - QtProperty *yProp = d_ptr->m_doublePropertyManager->addProperty(); - yProp->setPropertyName(tr("Y")); - d_ptr->m_doublePropertyManager->setDecimals(yProp, decimals(property)); - d_ptr->m_doublePropertyManager->setValue(yProp, 0); - d_ptr->m_propertyToY[property] = yProp; - d_ptr->m_yToProperty[yProp] = property; - property->addSubProperty(yProp); - - QtProperty *wProp = d_ptr->m_doublePropertyManager->addProperty(); - wProp->setPropertyName(tr("Width")); - d_ptr->m_doublePropertyManager->setDecimals(wProp, decimals(property)); - d_ptr->m_doublePropertyManager->setValue(wProp, 0); - d_ptr->m_doublePropertyManager->setMinimum(wProp, 0); - d_ptr->m_propertyToW[property] = wProp; - d_ptr->m_wToProperty[wProp] = property; - property->addSubProperty(wProp); - - QtProperty *hProp = d_ptr->m_doublePropertyManager->addProperty(); - hProp->setPropertyName(tr("Height")); - d_ptr->m_doublePropertyManager->setDecimals(hProp, decimals(property)); - d_ptr->m_doublePropertyManager->setValue(hProp, 0); - d_ptr->m_doublePropertyManager->setMinimum(hProp, 0); - d_ptr->m_propertyToH[property] = hProp; - d_ptr->m_hToProperty[hProp] = property; - property->addSubProperty(hProp); -} - -/*! - \reimp -*/ -void QtRectFPropertyManager::uninitializeProperty(QtProperty *property) -{ - QtProperty *xProp = d_ptr->m_propertyToX[property]; - if (xProp) { - d_ptr->m_xToProperty.remove(xProp); - delete xProp; - } - d_ptr->m_propertyToX.remove(property); - - QtProperty *yProp = d_ptr->m_propertyToY[property]; - if (yProp) { - d_ptr->m_yToProperty.remove(yProp); - delete yProp; - } - d_ptr->m_propertyToY.remove(property); - - QtProperty *wProp = d_ptr->m_propertyToW[property]; - if (wProp) { - d_ptr->m_wToProperty.remove(wProp); - delete wProp; - } - d_ptr->m_propertyToW.remove(property); - - QtProperty *hProp = d_ptr->m_propertyToH[property]; - if (hProp) { - d_ptr->m_hToProperty.remove(hProp); - delete hProp; - } - d_ptr->m_propertyToH.remove(property); - - d_ptr->m_values.remove(property); -} - -// QtEnumPropertyManager - -class QtEnumPropertyManagerPrivate -{ - QtEnumPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtEnumPropertyManager) -public: - - struct Data - { - Data() : val(-1) {} - int val; - QStringList enumNames; - QMap enumIcons; - }; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; -}; - -/*! - \class QtEnumPropertyManager - - \brief The QtEnumPropertyManager provides and manages enum properties. - - Each enum property has an associated list of enum names which can - be retrieved using the enumNames() function, and set using the - corresponding setEnumNames() function. An enum property's value is - represented by an index in this list, and can be retrieved and set - using the value() and setValue() slots respectively. - - Each enum value can also have an associated icon. The mapping from - values to icons can be set using the setEnumIcons() function and - queried with the enumIcons() function. - - In addition, QtEnumPropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes. The enumNamesChanged() or enumIconsChanged() signal is emitted - whenever the list of enum names or icons is altered. - - \sa QtAbstractPropertyManager, QtEnumEditorFactory -*/ - -/*! - \fn void QtEnumPropertyManager::valueChanged(QtProperty *property, int value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtEnumPropertyManager::enumNamesChanged(QtProperty *property, const QStringList &names) - - This signal is emitted whenever a property created by this manager - changes its enum names, passing a pointer to the \a property and - the new \a names as parameters. - - \sa setEnumNames() -*/ - -/*! - \fn void QtEnumPropertyManager::enumIconsChanged(QtProperty *property, const QMap &icons) - - This signal is emitted whenever a property created by this manager - changes its enum icons, passing a pointer to the \a property and - the new mapping of values to \a icons as parameters. - - \sa setEnumIcons() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtEnumPropertyManager::QtEnumPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtEnumPropertyManagerPrivate; - d_ptr->q_ptr = this; -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtEnumPropertyManager::~QtEnumPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value which is an index in the - list returned by enumNames() - - If the given property is not managed by this manager, this - function returns -1. - - \sa enumNames(), setValue() -*/ -int QtEnumPropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property, -1); -} - -/*! - Returns the given \a property's list of enum names. - - \sa value(), setEnumNames() -*/ -QStringList QtEnumPropertyManager::enumNames(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtEnumPropertyManagerPrivate::Data::enumNames, property, QStringList()); -} - -/*! - Returns the given \a property's map of enum values to their icons. - - \sa value(), setEnumIcons() -*/ -QMap QtEnumPropertyManager::enumIcons(const QtProperty *property) const -{ - return getData >(d_ptr->m_values, &QtEnumPropertyManagerPrivate::Data::enumIcons, property, QMap()); -} - -/*! - \reimp -*/ -QString QtEnumPropertyManager::valueText(const QtProperty *property) const -{ - const QtEnumPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - - const QtEnumPropertyManagerPrivate::Data &data = it.value(); - - const int v = data.val; - if (v >= 0 && v < data.enumNames.count()) - return data.enumNames.at(v); - return QString(); -} - -/*! - \reimp -*/ -QIcon QtEnumPropertyManager::valueIcon(const QtProperty *property) const -{ - const QtEnumPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QIcon(); - - const QtEnumPropertyManagerPrivate::Data &data = it.value(); - - const int v = data.val; - return data.enumIcons.value(v); -} - -/*! - \fn void QtEnumPropertyManager::setValue(QtProperty *property, int value) - - Sets the value of the given \a property to \a value. - - The specified \a value must be less than the size of the given \a - property's enumNames() list, and larger than (or equal to) 0. - - \sa value(), valueChanged() -*/ -void QtEnumPropertyManager::setValue(QtProperty *property, int val) -{ - const QtEnumPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtEnumPropertyManagerPrivate::Data data = it.value(); - - if (val >= data.enumNames.count()) - return; - - if (val < 0 && data.enumNames.count() > 0) - return; - - if (val < 0) - val = -1; - - if (data.val == val) - return; - - data.val = val; - - it.value() = data; - - emit propertyChanged(property); - emit valueChanged(property, data.val); -} - -/*! - Sets the given \a property's list of enum names to \a - enumNames. The \a property's current value is bound to a valid index. - - If the specified \a enumNames list is empty, the \a property's - current value is set to -1. - - \sa enumNames(), enumNamesChanged() -*/ -void QtEnumPropertyManager::setEnumNames(QtProperty *property, const QStringList &enumNames) -{ - const QtEnumPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtEnumPropertyManagerPrivate::Data data = it.value(); - - if (data.enumNames == enumNames) - return; - - data.enumNames = enumNames; - data.val = qBound(-1, data.val, enumNames.count() - 1); - - it.value() = data; - - emit enumNamesChanged(property, data.enumNames); - - emit propertyChanged(property); - emit valueChanged(property, data.val); -} - -/*! - Sets the given \a property's map of enum values to their icons to \a - enumIcons. - - Each enum value can have associated icon. This association is represented with passed \a enumIcons map. - - \sa enumNames(), enumNamesChanged() -*/ -void QtEnumPropertyManager::setEnumIcons(QtProperty *property, const QMap &enumIcons) -{ - const QtEnumPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - it.value().enumIcons = enumIcons; - - emit enumIconsChanged(property, it.value().enumIcons); - - emit propertyChanged(property); -} - -/*! - \reimp -*/ -void QtEnumPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtEnumPropertyManagerPrivate::Data(); -} - -/*! - \reimp -*/ -void QtEnumPropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -// QtFlagPropertyManager - -class QtFlagPropertyManagerPrivate -{ - QtFlagPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtFlagPropertyManager) -public: - - void slotBoolChanged(QtProperty *property, bool value); - void slotPropertyDestroyed(QtProperty *property); - - struct Data - { - Data() : val(-1) {} - int val; - QStringList flagNames; - }; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - QtBoolPropertyManager *m_boolPropertyManager; - - QMap > m_propertyToFlags; - - QMap m_flagToProperty; -}; - -void QtFlagPropertyManagerPrivate::slotBoolChanged(QtProperty *property, bool value) -{ - QtProperty *prop = m_flagToProperty.value(property, 0); - if (prop == 0) - return; - - QListIterator itProp(m_propertyToFlags[prop]); - int level = 0; - while (itProp.hasNext()) { - QtProperty *p = itProp.next(); - if (p == property) { - int v = m_values[prop].val; - if (value) { - v |= (1 << level); - } else { - v &= ~(1 << level); - } - q_ptr->setValue(prop, v); - return; - } - level++; - } -} - -void QtFlagPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) -{ - QtProperty *flagProperty = m_flagToProperty.value(property, 0); - if (flagProperty == 0) - return; - - m_propertyToFlags[flagProperty].replace(m_propertyToFlags[flagProperty].indexOf(property), 0); - m_flagToProperty.remove(property); -} - -/*! - \class QtFlagPropertyManager - - \brief The QtFlagPropertyManager provides and manages flag properties. - - Each flag property has an associated list of flag names which can - be retrieved using the flagNames() function, and set using the - corresponding setFlagNames() function. - - The flag manager provides properties with nested boolean - subproperties representing each flag, i.e. a flag property's value - is the binary combination of the subproperties' values. A - property's value can be retrieved and set using the value() and - setValue() slots respectively. The combination of flags is represented - by single int value - that's why it's possible to store up to - 32 independent flags in one flag property. - - The subproperties are created by a QtBoolPropertyManager object. This - manager can be retrieved using the subBoolPropertyManager() function. In - order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - In addition, QtFlagPropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes, and the flagNamesChanged() signal which is emitted - whenever the list of flag names is altered. - - \sa QtAbstractPropertyManager, QtBoolPropertyManager -*/ - -/*! - \fn void QtFlagPropertyManager::valueChanged(QtProperty *property, int value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtFlagPropertyManager::flagNamesChanged(QtProperty *property, const QStringList &names) - - This signal is emitted whenever a property created by this manager - changes its flag names, passing a pointer to the \a property and the - new \a names as parameters. - - \sa setFlagNames() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtFlagPropertyManager::QtFlagPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtFlagPropertyManagerPrivate; - d_ptr->q_ptr = this; - - d_ptr->m_boolPropertyManager = new QtBoolPropertyManager(this); - connect(d_ptr->m_boolPropertyManager, SIGNAL(valueChanged(QtProperty *, bool)), - this, SLOT(slotBoolChanged(QtProperty *, bool))); - connect(d_ptr->m_boolPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtFlagPropertyManager::~QtFlagPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the manager that produces the nested boolean subproperties - representing each flag. - - In order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtBoolPropertyManager *QtFlagPropertyManager::subBoolPropertyManager() const -{ - return d_ptr->m_boolPropertyManager; -} - -/*! - Returns the given \a property's value. - - If the given property is not managed by this manager, this - function returns 0. - - \sa flagNames(), setValue() -*/ -int QtFlagPropertyManager::value(const QtProperty *property) const -{ - return getValue(d_ptr->m_values, property, 0); -} - -/*! - Returns the given \a property's list of flag names. - - \sa value(), setFlagNames() -*/ -QStringList QtFlagPropertyManager::flagNames(const QtProperty *property) const -{ - return getData(d_ptr->m_values, &QtFlagPropertyManagerPrivate::Data::flagNames, property, QStringList()); -} - -/*! - \reimp -*/ -QString QtFlagPropertyManager::valueText(const QtProperty *property) const -{ - const QtFlagPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - - const QtFlagPropertyManagerPrivate::Data &data = it.value(); - - QString str; - int level = 0; - const QChar bar = QLatin1Char('|'); - const QStringList::const_iterator fncend = data.flagNames.constEnd(); - for (QStringList::const_iterator it = data.flagNames.constBegin(); it != fncend; ++it) { - if (data.val & (1 << level)) { - if (!str.isEmpty()) - str += bar; - str += *it; - } - - level++; - } - return str; -} - -/*! - \fn void QtFlagPropertyManager::setValue(QtProperty *property, int value) - - Sets the value of the given \a property to \a value. Nested - properties are updated automatically. - - The specified \a value must be less than the binary combination of - the property's flagNames() list size (i.e. less than 2\sup n, - where \c n is the size of the list) and larger than (or equal to) - 0. - - \sa value(), valueChanged() -*/ -void QtFlagPropertyManager::setValue(QtProperty *property, int val) -{ - const QtFlagPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtFlagPropertyManagerPrivate::Data data = it.value(); - - if (data.val == val) - return; - - if (val < 0) - return; - - if (static_cast(val) >= (1u << data.flagNames.count())) - return; - - data.val = val; - - it.value() = data; - - QListIterator itProp(d_ptr->m_propertyToFlags[property]); - int level = 0; - while (itProp.hasNext()) { - QtProperty *prop = itProp.next(); - if (prop) - d_ptr->m_boolPropertyManager->setValue(prop, val & (1 << level)); - level++; - } - - emit propertyChanged(property); - emit valueChanged(property, data.val); -} - -/*! - Sets the given \a property's list of flag names to \a flagNames. The - property's current value is cleared of any flags for which no name is - provided. - - \sa flagNames(), flagNamesChanged() -*/ -void QtFlagPropertyManager::setFlagNames(QtProperty *property, const QStringList &flagNames) -{ - const QtFlagPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - QtFlagPropertyManagerPrivate::Data data = it.value(); - - if (data.flagNames == flagNames) - return; - - data.flagNames = flagNames; - data.val &= ((1 << data.flagNames.count()) - 1); - - it.value() = data; - - QListIterator itProp(d_ptr->m_propertyToFlags[property]); - while (itProp.hasNext()) { - QtProperty *prop = itProp.next(); - if (prop) { - d_ptr->m_flagToProperty.remove(prop); - delete prop; - } - } - d_ptr->m_propertyToFlags[property].clear(); - - QStringListIterator itFlag(flagNames); - int level = 0; - while (itFlag.hasNext()) { - const QString flagName = itFlag.next(); - QtProperty *prop = d_ptr->m_boolPropertyManager->addProperty(flagName); - d_ptr->m_boolPropertyManager->setValue(prop, data.val & (1 << level)); - property->addSubProperty(prop); - d_ptr->m_propertyToFlags[property].append(prop); - d_ptr->m_flagToProperty[prop] = property; - level++; - } - - emit flagNamesChanged(property, data.flagNames); - - emit propertyChanged(property); - emit valueChanged(property, data.val); -} - -/*! - \reimp -*/ -void QtFlagPropertyManager::initializeProperty(QtProperty *property) -{ - d_ptr->m_values[property] = QtFlagPropertyManagerPrivate::Data(); - - d_ptr->m_propertyToFlags[property] = QList(); -} - -/*! - \reimp -*/ -void QtFlagPropertyManager::uninitializeProperty(QtProperty *property) -{ - QListIterator itProp(d_ptr->m_propertyToFlags[property]); - while (itProp.hasNext()) { - QtProperty *prop = itProp.next(); - if (prop) { - d_ptr->m_flagToProperty.remove(prop); - delete prop; - } - } - d_ptr->m_propertyToFlags.remove(property); - - d_ptr->m_values.remove(property); -} - - -// QtFontPropertyManager: -// QtFontPropertyManagerPrivate has a mechanism for reacting -// to QApplication::fontDatabaseChanged() [4.5], which is emitted -// when someone loads an application font. The signals are compressed -// using a timer with interval 0, which then causes the family -// enumeration manager to re-set its strings and index values -// for each property. - -Q_GLOBAL_STATIC(QFontDatabase, fontDatabase) - -class QtFontPropertyManagerPrivate -{ - QtFontPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtFontPropertyManager) -public: - - QtFontPropertyManagerPrivate(); - - void slotIntChanged(QtProperty *property, int value); - void slotEnumChanged(QtProperty *property, int value); - void slotBoolChanged(QtProperty *property, bool value); - void slotPropertyDestroyed(QtProperty *property); - void slotFontDatabaseChanged(); - void slotFontDatabaseDelayedChange(); - - QStringList m_familyNames; - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - QtIntPropertyManager *m_intPropertyManager; - QtEnumPropertyManager *m_enumPropertyManager; - QtBoolPropertyManager *m_boolPropertyManager; - - QMap m_propertyToFamily; - QMap m_propertyToPixelSize; - QMap m_propertyToBold; - QMap m_propertyToItalic; - QMap m_propertyToUnderline; - QMap m_propertyToStrikeOut; - QMap m_propertyToKerning; - - QMap m_familyToProperty; - QMap m_pixelSizeToProperty; - QMap m_boldToProperty; - QMap m_italicToProperty; - QMap m_underlineToProperty; - QMap m_strikeOutToProperty; - QMap m_kerningToProperty; - - bool m_settingValue; - QTimer *m_fontDatabaseChangeTimer; -}; - -QtFontPropertyManagerPrivate::QtFontPropertyManagerPrivate() : - m_settingValue(false), - m_fontDatabaseChangeTimer(0) -{ -} - -void QtFontPropertyManagerPrivate::slotIntChanged(QtProperty *property, int value) -{ - if (m_settingValue) - return; - if (QtProperty *prop = m_pixelSizeToProperty.value(property, 0)) { - QFont f = m_values[prop]; - f.setPixelSize(value); - q_ptr->setValue(prop, f); - } -} - -void QtFontPropertyManagerPrivate::slotEnumChanged(QtProperty *property, int value) -{ - if (m_settingValue) - return; - if (QtProperty *prop = m_familyToProperty.value(property, 0)) { - QFont f = m_values[prop]; - f.setFamily(m_familyNames.at(value)); - q_ptr->setValue(prop, f); - } -} - -void QtFontPropertyManagerPrivate::slotBoolChanged(QtProperty *property, bool value) -{ - if (m_settingValue) - return; - if (QtProperty *prop = m_boldToProperty.value(property, 0)) { - QFont f = m_values[prop]; - f.setBold(value); - q_ptr->setValue(prop, f); - } else if (QtProperty *prop = m_italicToProperty.value(property, 0)) { - QFont f = m_values[prop]; - f.setItalic(value); - q_ptr->setValue(prop, f); - } else if (QtProperty *prop = m_underlineToProperty.value(property, 0)) { - QFont f = m_values[prop]; - f.setUnderline(value); - q_ptr->setValue(prop, f); - } else if (QtProperty *prop = m_strikeOutToProperty.value(property, 0)) { - QFont f = m_values[prop]; - f.setStrikeOut(value); - q_ptr->setValue(prop, f); - } else if (QtProperty *prop = m_kerningToProperty.value(property, 0)) { - QFont f = m_values[prop]; - f.setKerning(value); - q_ptr->setValue(prop, f); - } -} - -void QtFontPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) -{ - if (QtProperty *pixelProp = m_pixelSizeToProperty.value(property, 0)) { - m_propertyToPixelSize[pixelProp] = 0; - m_pixelSizeToProperty.remove(property); - } else if (QtProperty *pointProp = m_familyToProperty.value(property, 0)) { - m_propertyToFamily[pointProp] = 0; - m_familyToProperty.remove(property); - } else if (QtProperty *pointProp = m_boldToProperty.value(property, 0)) { - m_propertyToBold[pointProp] = 0; - m_boldToProperty.remove(property); - } else if (QtProperty *pointProp = m_italicToProperty.value(property, 0)) { - m_propertyToItalic[pointProp] = 0; - m_italicToProperty.remove(property); - } else if (QtProperty *pointProp = m_underlineToProperty.value(property, 0)) { - m_propertyToUnderline[pointProp] = 0; - m_underlineToProperty.remove(property); - } else if (QtProperty *pointProp = m_strikeOutToProperty.value(property, 0)) { - m_propertyToStrikeOut[pointProp] = 0; - m_strikeOutToProperty.remove(property); - } else if (QtProperty *pointProp = m_kerningToProperty.value(property, 0)) { - m_propertyToKerning[pointProp] = 0; - m_kerningToProperty.remove(property); - } -} - -void QtFontPropertyManagerPrivate::slotFontDatabaseChanged() -{ - if (!m_fontDatabaseChangeTimer) { - m_fontDatabaseChangeTimer = new QTimer(q_ptr); - m_fontDatabaseChangeTimer->setInterval(0); - m_fontDatabaseChangeTimer->setSingleShot(true); - QObject::connect(m_fontDatabaseChangeTimer, SIGNAL(timeout()), q_ptr, SLOT(slotFontDatabaseDelayedChange())); - } - if (!m_fontDatabaseChangeTimer->isActive()) - m_fontDatabaseChangeTimer->start(); -} - -void QtFontPropertyManagerPrivate::slotFontDatabaseDelayedChange() -{ - typedef QMap PropertyPropertyMap; - // rescan available font names - const QStringList oldFamilies = m_familyNames; - m_familyNames = fontDatabase()->families(); - - // Adapt all existing properties - if (!m_propertyToFamily.empty()) { - PropertyPropertyMap::const_iterator cend = m_propertyToFamily.constEnd(); - for (PropertyPropertyMap::const_iterator it = m_propertyToFamily.constBegin(); it != cend; ++it) { - QtProperty *familyProp = it.value(); - const int oldIdx = m_enumPropertyManager->value(familyProp); - int newIdx = m_familyNames.indexOf(oldFamilies.at(oldIdx)); - if (newIdx < 0) - newIdx = 0; - m_enumPropertyManager->setEnumNames(familyProp, m_familyNames); - m_enumPropertyManager->setValue(familyProp, newIdx); - } - } -} - -/*! - \class QtFontPropertyManager - - \brief The QtFontPropertyManager provides and manages QFont properties. - - A font property has nested \e family, \e pointSize, \e bold, \e - italic, \e underline, \e strikeOut and \e kerning subproperties. The top-level - property's value can be retrieved using the value() function, and - set using the setValue() slot. - - The subproperties are created by QtIntPropertyManager, QtEnumPropertyManager and - QtBoolPropertyManager objects. These managers can be retrieved using the - corresponding subIntPropertyManager(), subEnumPropertyManager() and - subBoolPropertyManager() functions. In order to provide editing widgets - for the subproperties in a property browser widget, these managers - must be associated with editor factories. - - In addition, QtFontPropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes. - - \sa QtAbstractPropertyManager, QtEnumPropertyManager, QtIntPropertyManager, QtBoolPropertyManager -*/ - -/*! - \fn void QtFontPropertyManager::valueChanged(QtProperty *property, const QFont &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the - new \a value as parameters. - - \sa setValue() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtFontPropertyManager::QtFontPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtFontPropertyManagerPrivate; - d_ptr->q_ptr = this; -#if QT_VERSION >= 0x040500 - QObject::connect(qApp, SIGNAL(fontDatabaseChanged()), this, SLOT(slotFontDatabaseChanged())); -#endif - - d_ptr->m_intPropertyManager = new QtIntPropertyManager(this); - connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotIntChanged(QtProperty *, int))); - d_ptr->m_enumPropertyManager = new QtEnumPropertyManager(this); - connect(d_ptr->m_enumPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotEnumChanged(QtProperty *, int))); - d_ptr->m_boolPropertyManager = new QtBoolPropertyManager(this); - connect(d_ptr->m_boolPropertyManager, SIGNAL(valueChanged(QtProperty *, bool)), - this, SLOT(slotBoolChanged(QtProperty *, bool))); - - connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); - connect(d_ptr->m_enumPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); - connect(d_ptr->m_boolPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtFontPropertyManager::~QtFontPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the manager that creates the \e pointSize subproperty. - - In order to provide editing widgets for the \e pointSize property - in a property browser widget, this manager must be associated - with an editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtIntPropertyManager *QtFontPropertyManager::subIntPropertyManager() const -{ - return d_ptr->m_intPropertyManager; -} - -/*! - Returns the manager that create the \e family subproperty. - - In order to provide editing widgets for the \e family property - in a property browser widget, this manager must be associated - with an editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtEnumPropertyManager *QtFontPropertyManager::subEnumPropertyManager() const -{ - return d_ptr->m_enumPropertyManager; -} - -/*! - Returns the manager that creates the \e bold, \e italic, \e underline, - \e strikeOut and \e kerning subproperties. - - In order to provide editing widgets for the mentioned properties - in a property browser widget, this manager must be associated with - an editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtBoolPropertyManager *QtFontPropertyManager::subBoolPropertyManager() const -{ - return d_ptr->m_boolPropertyManager; -} - -/*! - Returns the given \a property's value. - - If the given property is not managed by this manager, this - function returns a font object that uses the application's default - font. - - \sa setValue() -*/ -QFont QtFontPropertyManager::value(const QtProperty *property) const -{ - return d_ptr->m_values.value(property, QFont()); -} - -/*! - \reimp -*/ -QString QtFontPropertyManager::valueText(const QtProperty *property) const -{ - const QtFontPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - - return QtPropertyBrowserUtils::fontValueText(it.value()); -} - -/*! - \reimp -*/ -QIcon QtFontPropertyManager::valueIcon(const QtProperty *property) const -{ - const QtFontPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QIcon(); - - return QtPropertyBrowserUtils::fontValueIcon(it.value()); -} - -/*! - \fn void QtFontPropertyManager::setValue(QtProperty *property, const QFont &value) - - Sets the value of the given \a property to \a value. Nested - properties are updated automatically. - - \sa value(), valueChanged() -*/ -void QtFontPropertyManager::setValue(QtProperty *property, const QFont &val) -{ - const QtFontPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - const QFont oldVal = it.value(); -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) - if (oldVal == val && oldVal.resolve() == val.resolve()) -#else - if (oldVal == val && oldVal.resolveMask() == val.resolveMask()) -#endif - return; - - it.value() = val; - - int idx = d_ptr->m_familyNames.indexOf(val.family()); - if (idx == -1) - idx = 0; - bool settingValue = d_ptr->m_settingValue; - d_ptr->m_settingValue = true; - d_ptr->m_enumPropertyManager->setValue(d_ptr->m_propertyToFamily[property], idx); - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToPixelSize[property], val.pixelSize()); - d_ptr->m_boolPropertyManager->setValue(d_ptr->m_propertyToBold[property], val.bold()); - d_ptr->m_boolPropertyManager->setValue(d_ptr->m_propertyToItalic[property], val.italic()); - d_ptr->m_boolPropertyManager->setValue(d_ptr->m_propertyToUnderline[property], val.underline()); - d_ptr->m_boolPropertyManager->setValue(d_ptr->m_propertyToStrikeOut[property], val.strikeOut()); - d_ptr->m_boolPropertyManager->setValue(d_ptr->m_propertyToKerning[property], val.kerning()); - d_ptr->m_settingValue = settingValue; - - emit propertyChanged(property); - emit valueChanged(property, val); -} - -/*! - \reimp -*/ -void QtFontPropertyManager::initializeProperty(QtProperty *property) -{ - QFont val; - d_ptr->m_values[property] = val; - - QtProperty *familyProp = d_ptr->m_enumPropertyManager->addProperty(); - familyProp->setPropertyName(tr("Family")); - if (d_ptr->m_familyNames.empty()) - d_ptr->m_familyNames = fontDatabase()->families(); - d_ptr->m_enumPropertyManager->setEnumNames(familyProp, d_ptr->m_familyNames); - int idx = d_ptr->m_familyNames.indexOf(val.family()); - if (idx == -1) - idx = 0; - d_ptr->m_enumPropertyManager->setValue(familyProp, idx); - d_ptr->m_propertyToFamily[property] = familyProp; - d_ptr->m_familyToProperty[familyProp] = property; - property->addSubProperty(familyProp); - - QtProperty *pixelSizeProp = d_ptr->m_intPropertyManager->addProperty(); - pixelSizeProp->setPropertyName(tr("Pixel Size")); - d_ptr->m_intPropertyManager->setValue(pixelSizeProp, val.pointSize()); - d_ptr->m_intPropertyManager->setMinimum(pixelSizeProp, 1); - d_ptr->m_propertyToPixelSize[property] = pixelSizeProp; - d_ptr->m_pixelSizeToProperty[pixelSizeProp] = property; - property->addSubProperty(pixelSizeProp); - - QtProperty *boldProp = d_ptr->m_boolPropertyManager->addProperty(); - boldProp->setPropertyName(tr("Bold")); - d_ptr->m_boolPropertyManager->setValue(boldProp, val.bold()); - d_ptr->m_propertyToBold[property] = boldProp; - d_ptr->m_boldToProperty[boldProp] = property; - property->addSubProperty(boldProp); - - QtProperty *italicProp = d_ptr->m_boolPropertyManager->addProperty(); - italicProp->setPropertyName(tr("Italic")); - d_ptr->m_boolPropertyManager->setValue(italicProp, val.italic()); - d_ptr->m_propertyToItalic[property] = italicProp; - d_ptr->m_italicToProperty[italicProp] = property; - property->addSubProperty(italicProp); - - QtProperty *underlineProp = d_ptr->m_boolPropertyManager->addProperty(); - underlineProp->setPropertyName(tr("Underline")); - d_ptr->m_boolPropertyManager->setValue(underlineProp, val.underline()); - d_ptr->m_propertyToUnderline[property] = underlineProp; - d_ptr->m_underlineToProperty[underlineProp] = property; - property->addSubProperty(underlineProp); - - QtProperty *strikeOutProp = d_ptr->m_boolPropertyManager->addProperty(); - strikeOutProp->setPropertyName(tr("Strikeout")); - d_ptr->m_boolPropertyManager->setValue(strikeOutProp, val.strikeOut()); - d_ptr->m_propertyToStrikeOut[property] = strikeOutProp; - d_ptr->m_strikeOutToProperty[strikeOutProp] = property; - property->addSubProperty(strikeOutProp); - - QtProperty *kerningProp = d_ptr->m_boolPropertyManager->addProperty(); - kerningProp->setPropertyName(tr("Kerning")); - d_ptr->m_boolPropertyManager->setValue(kerningProp, val.kerning()); - d_ptr->m_propertyToKerning[property] = kerningProp; - d_ptr->m_kerningToProperty[kerningProp] = property; - property->addSubProperty(kerningProp); -} - -/*! - \reimp -*/ -void QtFontPropertyManager::uninitializeProperty(QtProperty *property) -{ - QtProperty *familyProp = d_ptr->m_propertyToFamily[property]; - if (familyProp) { - d_ptr->m_familyToProperty.remove(familyProp); - delete familyProp; - } - d_ptr->m_propertyToFamily.remove(property); - - QtProperty *pixelSizeProp = d_ptr->m_propertyToPixelSize[property]; - if (pixelSizeProp) { - d_ptr->m_pixelSizeToProperty.remove(pixelSizeProp); - delete pixelSizeProp; - } - d_ptr->m_propertyToPixelSize.remove(property); - - QtProperty *boldProp = d_ptr->m_propertyToBold[property]; - if (boldProp) { - d_ptr->m_boldToProperty.remove(boldProp); - delete boldProp; - } - d_ptr->m_propertyToBold.remove(property); - - QtProperty *italicProp = d_ptr->m_propertyToItalic[property]; - if (italicProp) { - d_ptr->m_italicToProperty.remove(italicProp); - delete italicProp; - } - d_ptr->m_propertyToItalic.remove(property); - - QtProperty *underlineProp = d_ptr->m_propertyToUnderline[property]; - if (underlineProp) { - d_ptr->m_underlineToProperty.remove(underlineProp); - delete underlineProp; - } - d_ptr->m_propertyToUnderline.remove(property); - - QtProperty *strikeOutProp = d_ptr->m_propertyToStrikeOut[property]; - if (strikeOutProp) { - d_ptr->m_strikeOutToProperty.remove(strikeOutProp); - delete strikeOutProp; - } - d_ptr->m_propertyToStrikeOut.remove(property); - - QtProperty *kerningProp = d_ptr->m_propertyToKerning[property]; - if (kerningProp) { - d_ptr->m_kerningToProperty.remove(kerningProp); - delete kerningProp; - } - d_ptr->m_propertyToKerning.remove(property); - - d_ptr->m_values.remove(property); -} - -// QtColorPropertyManager - -class QtColorPropertyManagerPrivate -{ - QtColorPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtColorPropertyManager) -public: - - void slotIntChanged(QtProperty *property, int value); - void slotPropertyDestroyed(QtProperty *property); - - typedef QMap PropertyValueMap; - PropertyValueMap m_values; - - QtIntPropertyManager *m_intPropertyManager; - bool m_applyingValueChange; - - QMap m_propertyToR; - QMap m_propertyToG; - QMap m_propertyToB; - QMap m_propertyToA; - - QMap m_rToProperty; - QMap m_gToProperty; - QMap m_bToProperty; - QMap m_aToProperty; -}; - -void QtColorPropertyManagerPrivate::slotIntChanged(QtProperty *property, int value) -{ - if (m_applyingValueChange) - return; - - if (QtProperty *prop = m_rToProperty.value(property, 0)) { - QColor c = m_values[prop]; - c.setRed(value); - q_ptr->setValue(prop, c); - } else if (QtProperty *prop = m_gToProperty.value(property, 0)) { - QColor c = m_values[prop]; - c.setGreen(value); - q_ptr->setValue(prop, c); - } else if (QtProperty *prop = m_bToProperty.value(property, 0)) { - QColor c = m_values[prop]; - c.setBlue(value); - q_ptr->setValue(prop, c); - } else if (QtProperty *prop = m_aToProperty.value(property, 0)) { - QColor c = m_values[prop]; - c.setAlpha(value); - q_ptr->setValue(prop, c); - } -} - -void QtColorPropertyManagerPrivate::slotPropertyDestroyed(QtProperty *property) -{ - if (QtProperty *pointProp = m_rToProperty.value(property, 0)) { - m_propertyToR[pointProp] = 0; - m_rToProperty.remove(property); - } else if (QtProperty *pointProp = m_gToProperty.value(property, 0)) { - m_propertyToG[pointProp] = 0; - m_gToProperty.remove(property); - } else if (QtProperty *pointProp = m_bToProperty.value(property, 0)) { - m_propertyToB[pointProp] = 0; - m_bToProperty.remove(property); - } else if (QtProperty *pointProp = m_aToProperty.value(property, 0)) { - m_propertyToA[pointProp] = 0; - m_aToProperty.remove(property); - } -} - -/*! - \class QtColorPropertyManager - - \brief The QtColorPropertyManager provides and manages QColor properties. - - A color property has nested \e red, \e green and \e blue - subproperties. The top-level property's value can be retrieved - using the value() function, and set using the setValue() slot. - - The subproperties are created by a QtIntPropertyManager object. This - manager can be retrieved using the subIntPropertyManager() function. In - order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - In addition, QtColorPropertyManager provides the valueChanged() signal - which is emitted whenever a property created by this manager - changes. - - \sa QtAbstractPropertyManager, QtAbstractPropertyBrowser, QtIntPropertyManager -*/ - -/*! - \fn void QtColorPropertyManager::valueChanged(QtProperty *property, const QColor &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtColorPropertyManager::QtColorPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtColorPropertyManagerPrivate; - d_ptr->q_ptr = this; - - d_ptr->m_intPropertyManager = new QtIntPropertyManager(this); - d_ptr->m_applyingValueChange = false; - - connect(d_ptr->m_intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotIntChanged(QtProperty *, int))); - - connect(d_ptr->m_intPropertyManager, SIGNAL(propertyDestroyed(QtProperty *)), - this, SLOT(slotPropertyDestroyed(QtProperty *))); -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtColorPropertyManager::~QtColorPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the manager that produces the nested \e red, \e green and - \e blue subproperties. - - In order to provide editing widgets for the subproperties in a - property browser widget, this manager must be associated with an - editor factory. - - \sa QtAbstractPropertyBrowser::setFactoryForManager() -*/ -QtIntPropertyManager *QtColorPropertyManager::subIntPropertyManager() const -{ - return d_ptr->m_intPropertyManager; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by \e this manager, this - function returns an invalid color. - - \sa setValue() -*/ -QColor QtColorPropertyManager::value(const QtProperty *property) const -{ - return d_ptr->m_values.value(property, QColor()); -} - -/*! - \reimp -*/ - -QString QtColorPropertyManager::valueText(const QtProperty *property) const -{ - const QtColorPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - - return QtPropertyBrowserUtils::colorValueText(it.value()); -} - -/*! - \reimp -*/ - -QIcon QtColorPropertyManager::valueIcon(const QtProperty *property) const -{ - const QtColorPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QIcon(); - if (!it.value().isValid()) - return QIcon(); - return QtPropertyBrowserUtils::brushValueIcon(QBrush(it.value())); -} - -/*! - \fn void QtColorPropertyManager::setValue(QtProperty *property, const QColor &value) - - Sets the value of the given \a property to \a value. Nested - properties are updated automatically. - - \sa value(), valueChanged() -*/ -void QtColorPropertyManager::setValue(QtProperty *property, const QColor &val) -{ - const QtColorPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - if (it.value() == val) - return; - - it.value() = val; - - d_ptr->m_applyingValueChange = true; - - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToR[property], val.red()); - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToG[property], val.green()); - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToB[property], val.blue()); - d_ptr->m_intPropertyManager->setValue(d_ptr->m_propertyToA[property], val.alpha()); - - d_ptr->m_applyingValueChange = false; - - emit propertyChanged(property); - emit valueChanged(property, val); -} - -/*! - \reimp -*/ -void QtColorPropertyManager::initializeProperty(QtProperty *property) -{ - QColor val; - d_ptr->m_values[property] = val; - - QtProperty *rProp = d_ptr->m_intPropertyManager->addProperty(); - rProp->setPropertyName(tr("Red")); - d_ptr->m_intPropertyManager->setValue(rProp, val.red()); - d_ptr->m_intPropertyManager->setRange(rProp, 0, 0xFF); - d_ptr->m_propertyToR[property] = rProp; - d_ptr->m_rToProperty[rProp] = property; - property->addSubProperty(rProp); - - QtProperty *gProp = d_ptr->m_intPropertyManager->addProperty(); - gProp->setPropertyName(tr("Green")); - d_ptr->m_intPropertyManager->setValue(gProp, val.green()); - d_ptr->m_intPropertyManager->setRange(gProp, 0, 0xFF); - d_ptr->m_propertyToG[property] = gProp; - d_ptr->m_gToProperty[gProp] = property; - property->addSubProperty(gProp); - - QtProperty *bProp = d_ptr->m_intPropertyManager->addProperty(); - bProp->setPropertyName(tr("Blue")); - d_ptr->m_intPropertyManager->setValue(bProp, val.blue()); - d_ptr->m_intPropertyManager->setRange(bProp, 0, 0xFF); - d_ptr->m_propertyToB[property] = bProp; - d_ptr->m_bToProperty[bProp] = property; - property->addSubProperty(bProp); - - QtProperty *aProp = d_ptr->m_intPropertyManager->addProperty(); - aProp->setPropertyName(tr("Alpha")); - d_ptr->m_intPropertyManager->setValue(aProp, val.alpha()); - d_ptr->m_intPropertyManager->setRange(aProp, 0, 0xFF); - d_ptr->m_propertyToA[property] = aProp; - d_ptr->m_aToProperty[aProp] = property; - property->addSubProperty(aProp); -} - -/*! - \reimp -*/ -void QtColorPropertyManager::uninitializeProperty(QtProperty *property) -{ - QtProperty *rProp = d_ptr->m_propertyToR[property]; - if (rProp) { - d_ptr->m_rToProperty.remove(rProp); - delete rProp; - } - d_ptr->m_propertyToR.remove(property); - - QtProperty *gProp = d_ptr->m_propertyToG[property]; - if (gProp) { - d_ptr->m_gToProperty.remove(gProp); - delete gProp; - } - d_ptr->m_propertyToG.remove(property); - - QtProperty *bProp = d_ptr->m_propertyToB[property]; - if (bProp) { - d_ptr->m_bToProperty.remove(bProp); - delete bProp; - } - d_ptr->m_propertyToB.remove(property); - - QtProperty *aProp = d_ptr->m_propertyToA[property]; - if (aProp) { - d_ptr->m_aToProperty.remove(aProp); - delete aProp; - } - d_ptr->m_propertyToA.remove(property); - - d_ptr->m_values.remove(property); -} - -// QtCursorPropertyManager - -// Make sure icons are removed as soon as QApplication is destroyed, otherwise, -// handles are leaked on X11. -static void clearCursorDatabase(); -namespace { -struct CursorDatabase : public QtCursorDatabase -{ - CursorDatabase() - { - qAddPostRoutine(clearCursorDatabase); - } -}; -} -Q_GLOBAL_STATIC(QtCursorDatabase, cursorDatabase) - -static void clearCursorDatabase() -{ - cursorDatabase()->clear(); -} - -class QtCursorPropertyManagerPrivate -{ - QtCursorPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtCursorPropertyManager) -public: - typedef QMap PropertyValueMap; - PropertyValueMap m_values; -}; - -/*! - \class QtCursorPropertyManager - - \brief The QtCursorPropertyManager provides and manages QCursor properties. - - A cursor property has a current value which can be - retrieved using the value() function, and set using the setValue() - slot. In addition, QtCursorPropertyManager provides the - valueChanged() signal which is emitted whenever a property created - by this manager changes. - - \sa QtAbstractPropertyManager -*/ - -/*! - \fn void QtCursorPropertyManager::valueChanged(QtProperty *property, const QCursor &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the new - \a value as parameters. - - \sa setValue() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtCursorPropertyManager::QtCursorPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtCursorPropertyManagerPrivate; - d_ptr->q_ptr = this; -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtCursorPropertyManager::~QtCursorPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns a default QCursor object. - - \sa setValue() -*/ -#ifndef QT_NO_CURSOR -QCursor QtCursorPropertyManager::value(const QtProperty *property) const -{ - return d_ptr->m_values.value(property, QCursor()); -} -#endif - -/*! - \reimp -*/ -QString QtCursorPropertyManager::valueText(const QtProperty *property) const -{ - const QtCursorPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QString(); - - return cursorDatabase()->cursorToShapeName(it.value()); -} - -/*! - \reimp -*/ -QIcon QtCursorPropertyManager::valueIcon(const QtProperty *property) const -{ - const QtCursorPropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); - if (it == d_ptr->m_values.constEnd()) - return QIcon(); - - return cursorDatabase()->cursorToShapeIcon(it.value()); -} - -/*! - \fn void QtCursorPropertyManager::setValue(QtProperty *property, const QCursor &value) - - Sets the value of the given \a property to \a value. - - \sa value(), valueChanged() -*/ -void QtCursorPropertyManager::setValue(QtProperty *property, const QCursor &value) -{ -#ifndef QT_NO_CURSOR - const QtCursorPropertyManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); - if (it == d_ptr->m_values.end()) - return; - - if (it.value().shape() == value.shape() && value.shape() != Qt::BitmapCursor) - return; - - it.value() = value; - - emit propertyChanged(property); - emit valueChanged(property, value); -#endif -} - -/*! - \reimp -*/ -void QtCursorPropertyManager::initializeProperty(QtProperty *property) -{ -#ifndef QT_NO_CURSOR - d_ptr->m_values[property] = QCursor(); -#endif -} - -/*! - \reimp -*/ -void QtCursorPropertyManager::uninitializeProperty(QtProperty *property) -{ - d_ptr->m_values.remove(property); -} - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#include "moc_qtpropertymanager.cpp" -#include "qtpropertymanager.moc" diff --git a/src/qtpropertybrowser/src/qtpropertymanager.h b/src/qtpropertybrowser/src/qtpropertymanager.h deleted file mode 100644 index f2fa06089d..0000000000 --- a/src/qtpropertybrowser/src/qtpropertymanager.h +++ /dev/null @@ -1,714 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QTPROPERTYMANAGER_H -#define QTPROPERTYMANAGER_H - -#include "qtpropertybrowser.h" -#include -#include - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QDate; -class QTime; -class QDateTime; -class QLocale; - -class QT_QTPROPERTYBROWSER_EXPORT QtGroupPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtGroupPropertyManager(QObject *parent = 0); - ~QtGroupPropertyManager(); - -protected: - virtual bool hasValue(const QtProperty *property) const; - - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -}; - -class QtIntPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtIntPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtIntPropertyManager(QObject *parent = 0); - ~QtIntPropertyManager(); - - int value(const QtProperty *property) const; - int minimum(const QtProperty *property) const; - int maximum(const QtProperty *property) const; - int singleStep(const QtProperty *property) const; - bool isReadOnly(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, int val); - void setMinimum(QtProperty *property, int minVal); - void setMaximum(QtProperty *property, int maxVal); - void setRange(QtProperty *property, int minVal, int maxVal); - void setSingleStep(QtProperty *property, int step); - void setReadOnly(QtProperty *property, bool readOnly); -Q_SIGNALS: - void valueChanged(QtProperty *property, int val); - void rangeChanged(QtProperty *property, int minVal, int maxVal); - void singleStepChanged(QtProperty *property, int step); - void readOnlyChanged(QtProperty *property, bool readOnly); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtIntPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtIntPropertyManager) - Q_DISABLE_COPY(QtIntPropertyManager) -}; - -class QtBoolPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtBoolPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtBoolPropertyManager(QObject *parent = 0); - ~QtBoolPropertyManager(); - - bool value(const QtProperty *property) const; - bool textVisible(const QtProperty *property) const; - - static void resetIcons(); - -public Q_SLOTS: - void setValue(QtProperty *property, bool val); - void setTextVisible(QtProperty *property, bool textVisible); -Q_SIGNALS: - void valueChanged(QtProperty *property, bool val); - void textVisibleChanged(QtProperty *property, bool); -protected: - QString valueText(const QtProperty *property) const; - QIcon valueIcon(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtBoolPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtBoolPropertyManager) - Q_DISABLE_COPY(QtBoolPropertyManager) -}; - -class QtDoublePropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtDoublePropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtDoublePropertyManager(QObject *parent = 0); - ~QtDoublePropertyManager(); - - double value(const QtProperty *property) const; - double minimum(const QtProperty *property) const; - double maximum(const QtProperty *property) const; - double singleStep(const QtProperty *property) const; - int decimals(const QtProperty *property) const; - bool isReadOnly(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, double val); - void setMinimum(QtProperty *property, double minVal); - void setMaximum(QtProperty *property, double maxVal); - void setRange(QtProperty *property, double minVal, double maxVal); - void setSingleStep(QtProperty *property, double step); - void setDecimals(QtProperty *property, int prec); - void setReadOnly(QtProperty *property, bool readOnly); -Q_SIGNALS: - void valueChanged(QtProperty *property, double val); - void rangeChanged(QtProperty *property, double minVal, double maxVal); - void singleStepChanged(QtProperty *property, double step); - void decimalsChanged(QtProperty *property, int prec); - void readOnlyChanged(QtProperty *property, bool readOnly); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtDoublePropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtDoublePropertyManager) - Q_DISABLE_COPY(QtDoublePropertyManager) -}; - -class QtStringPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtStringPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtStringPropertyManager(QObject *parent = 0); - ~QtStringPropertyManager(); - - QString value(const QtProperty *property) const; - QRegularExpression regExp(const QtProperty *property) const; - EchoMode echoMode(const QtProperty *property) const; - bool isReadOnly(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QString &val); - void setRegExp(QtProperty *property, const QRegularExpression ®Exp); - void setEchoMode(QtProperty *property, EchoMode echoMode); - void setReadOnly(QtProperty *property, bool readOnly); - -Q_SIGNALS: - void valueChanged(QtProperty *property, const QString &val); - void regExpChanged(QtProperty *property, const QRegularExpression ®Exp); - void echoModeChanged(QtProperty *property, const int); - void readOnlyChanged(QtProperty *property, bool); - -protected: - QString valueText(const QtProperty *property) const; - QString displayText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtStringPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtStringPropertyManager) - Q_DISABLE_COPY(QtStringPropertyManager) -}; - -class QtDatePropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtDatePropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtDatePropertyManager(QObject *parent = 0); - ~QtDatePropertyManager(); - - QDate value(const QtProperty *property) const; - QDate minimum(const QtProperty *property) const; - QDate maximum(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QDate &val); - void setMinimum(QtProperty *property, const QDate &minVal); - void setMaximum(QtProperty *property, const QDate &maxVal); - void setRange(QtProperty *property, const QDate &minVal, const QDate &maxVal); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QDate &val); - void rangeChanged(QtProperty *property, const QDate &minVal, const QDate &maxVal); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtDatePropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtDatePropertyManager) - Q_DISABLE_COPY(QtDatePropertyManager) -}; - -class QtTimePropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtTimePropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtTimePropertyManager(QObject *parent = 0); - ~QtTimePropertyManager(); - - QTime value(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QTime &val); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QTime &val); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtTimePropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtTimePropertyManager) - Q_DISABLE_COPY(QtTimePropertyManager) -}; - -class QtDateTimePropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtDateTimePropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtDateTimePropertyManager(QObject *parent = 0); - ~QtDateTimePropertyManager(); - - QDateTime value(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QDateTime &val); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QDateTime &val); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtDateTimePropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtDateTimePropertyManager) - Q_DISABLE_COPY(QtDateTimePropertyManager) -}; - -class QtKeySequencePropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtKeySequencePropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtKeySequencePropertyManager(QObject *parent = 0); - ~QtKeySequencePropertyManager(); - - QKeySequence value(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QKeySequence &val); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QKeySequence &val); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtKeySequencePropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtKeySequencePropertyManager) - Q_DISABLE_COPY(QtKeySequencePropertyManager) -}; - -class QtCharPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtCharPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtCharPropertyManager(QObject *parent = 0); - ~QtCharPropertyManager(); - - QChar value(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QChar &val); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QChar &val); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtCharPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtCharPropertyManager) - Q_DISABLE_COPY(QtCharPropertyManager) -}; - -class QtPointPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtPointPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtPointPropertyManager(QObject *parent = 0); - ~QtPointPropertyManager(); - - QtIntPropertyManager *subIntPropertyManager() const; - - QPoint value(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QPoint &val); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QPoint &val); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtPointPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtPointPropertyManager) - Q_DISABLE_COPY(QtPointPropertyManager) - Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) -}; - -class QtPointFPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtPointFPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtPointFPropertyManager(QObject *parent = 0); - ~QtPointFPropertyManager(); - - QtDoublePropertyManager *subDoublePropertyManager() const; - - QPointF value(const QtProperty *property) const; - double singleStep(const QtProperty *property) const; - int decimals(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QPointF &val); - void setSingleStep(QtProperty *property, double step); - void setDecimals(QtProperty *property, int prec); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QPointF &val); - void singleStepChanged(QtProperty *property, double step); - void decimalsChanged(QtProperty *property, int prec); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtPointFPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtPointFPropertyManager) - Q_DISABLE_COPY(QtPointFPropertyManager) - Q_PRIVATE_SLOT(d_func(), void slotDoubleChanged(QtProperty *, double)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) -}; - -class QtSizePropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtSizePropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtSizePropertyManager(QObject *parent = 0); - ~QtSizePropertyManager(); - - QtIntPropertyManager *subIntPropertyManager() const; - - QSize value(const QtProperty *property) const; - QSize minimum(const QtProperty *property) const; - QSize maximum(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QSize &val); - void setMinimum(QtProperty *property, const QSize &minVal); - void setMaximum(QtProperty *property, const QSize &maxVal); - void setRange(QtProperty *property, const QSize &minVal, const QSize &maxVal); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QSize &val); - void rangeChanged(QtProperty *property, const QSize &minVal, const QSize &maxVal); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtSizePropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtSizePropertyManager) - Q_DISABLE_COPY(QtSizePropertyManager) - Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) -}; - -class QtSizeFPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtSizeFPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtSizeFPropertyManager(QObject *parent = 0); - ~QtSizeFPropertyManager(); - - QtDoublePropertyManager *subDoublePropertyManager() const; - - QSizeF value(const QtProperty *property) const; - QSizeF minimum(const QtProperty *property) const; - QSizeF maximum(const QtProperty *property) const; - int decimals(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QSizeF &val); - void setMinimum(QtProperty *property, const QSizeF &minVal); - void setMaximum(QtProperty *property, const QSizeF &maxVal); - void setRange(QtProperty *property, const QSizeF &minVal, const QSizeF &maxVal); - void setDecimals(QtProperty *property, int prec); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QSizeF &val); - void rangeChanged(QtProperty *property, const QSizeF &minVal, const QSizeF &maxVal); - void decimalsChanged(QtProperty *property, int prec); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtSizeFPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtSizeFPropertyManager) - Q_DISABLE_COPY(QtSizeFPropertyManager) - Q_PRIVATE_SLOT(d_func(), void slotDoubleChanged(QtProperty *, double)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) -}; - -class QtRectPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtRectPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtRectPropertyManager(QObject *parent = 0); - ~QtRectPropertyManager(); - - QtIntPropertyManager *subIntPropertyManager() const; - - QRect value(const QtProperty *property) const; - QRect constraint(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QRect &val); - void setConstraint(QtProperty *property, const QRect &constraint); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QRect &val); - void constraintChanged(QtProperty *property, const QRect &constraint); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtRectPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtRectPropertyManager) - Q_DISABLE_COPY(QtRectPropertyManager) - Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) -}; - -class QtRectFPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtRectFPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtRectFPropertyManager(QObject *parent = 0); - ~QtRectFPropertyManager(); - - QtDoublePropertyManager *subDoublePropertyManager() const; - - QRectF value(const QtProperty *property) const; - QRectF constraint(const QtProperty *property) const; - int decimals(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QRectF &val); - void setConstraint(QtProperty *property, const QRectF &constraint); - void setDecimals(QtProperty *property, int prec); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QRectF &val); - void constraintChanged(QtProperty *property, const QRectF &constraint); - void decimalsChanged(QtProperty *property, int prec); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtRectFPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtRectFPropertyManager) - Q_DISABLE_COPY(QtRectFPropertyManager) - Q_PRIVATE_SLOT(d_func(), void slotDoubleChanged(QtProperty *, double)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) -}; - -class QtEnumPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtEnumPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtEnumPropertyManager(QObject *parent = 0); - ~QtEnumPropertyManager(); - - int value(const QtProperty *property) const; - QStringList enumNames(const QtProperty *property) const; - QMap enumIcons(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, int val); - void setEnumNames(QtProperty *property, const QStringList &names); - void setEnumIcons(QtProperty *property, const QMap &icons); -Q_SIGNALS: - void valueChanged(QtProperty *property, int val); - void enumNamesChanged(QtProperty *property, const QStringList &names); - void enumIconsChanged(QtProperty *property, const QMap &icons); -protected: - QString valueText(const QtProperty *property) const; - QIcon valueIcon(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtEnumPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtEnumPropertyManager) - Q_DISABLE_COPY(QtEnumPropertyManager) -}; - -class QtFlagPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtFlagPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtFlagPropertyManager(QObject *parent = 0); - ~QtFlagPropertyManager(); - - QtBoolPropertyManager *subBoolPropertyManager() const; - - int value(const QtProperty *property) const; - QStringList flagNames(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, int val); - void setFlagNames(QtProperty *property, const QStringList &names); -Q_SIGNALS: - void valueChanged(QtProperty *property, int val); - void flagNamesChanged(QtProperty *property, const QStringList &names); -protected: - QString valueText(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtFlagPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtFlagPropertyManager) - Q_DISABLE_COPY(QtFlagPropertyManager) - Q_PRIVATE_SLOT(d_func(), void slotBoolChanged(QtProperty *, bool)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) -}; - -class QtFontPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtFontPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtFontPropertyManager(QObject *parent = 0); - ~QtFontPropertyManager(); - - QtIntPropertyManager *subIntPropertyManager() const; - QtEnumPropertyManager *subEnumPropertyManager() const; - QtBoolPropertyManager *subBoolPropertyManager() const; - - QFont value(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QFont &val); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QFont &val); -protected: - QString valueText(const QtProperty *property) const; - QIcon valueIcon(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtFontPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtFontPropertyManager) - Q_DISABLE_COPY(QtFontPropertyManager) - Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotEnumChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotBoolChanged(QtProperty *, bool)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) - Q_PRIVATE_SLOT(d_func(), void slotFontDatabaseChanged()) - Q_PRIVATE_SLOT(d_func(), void slotFontDatabaseDelayedChange()) -}; - -class QtColorPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtColorPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtColorPropertyManager(QObject *parent = 0); - ~QtColorPropertyManager(); - - QtIntPropertyManager *subIntPropertyManager() const; - - QColor value(const QtProperty *property) const; - -public Q_SLOTS: - void setValue(QtProperty *property, const QColor &val); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QColor &val); -protected: - QString valueText(const QtProperty *property) const; - QIcon valueIcon(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtColorPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtColorPropertyManager) - Q_DISABLE_COPY(QtColorPropertyManager) - Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty *)) -}; - -class QtCursorPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtCursorPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtCursorPropertyManager(QObject *parent = 0); - ~QtCursorPropertyManager(); - -#ifndef QT_NO_CURSOR - QCursor value(const QtProperty *property) const; -#endif - -public Q_SLOTS: - void setValue(QtProperty *property, const QCursor &val); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QCursor &val); -protected: - QString valueText(const QtProperty *property) const; - QIcon valueIcon(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); -private: - QtCursorPropertyManagerPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtCursorPropertyManager) - Q_DISABLE_COPY(QtCursorPropertyManager) -}; - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#endif diff --git a/src/qtpropertybrowser/src/qttreepropertybrowser.cpp b/src/qtpropertybrowser/src/qttreepropertybrowser.cpp deleted file mode 100644 index bb928c6510..0000000000 --- a/src/qtpropertybrowser/src/qttreepropertybrowser.cpp +++ /dev/null @@ -1,1200 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qttreepropertybrowser.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef Q_OS_MAC -static qreal defaultDpiScale() -{ - if (const QScreen *screen = QGuiApplication::primaryScreen()) - return screen->logicalDotsPerInchX() / 96.0; - return 1.0; -} -#endif - -static qreal dpiScaled(qreal value) -{ -#ifdef Q_OS_MAC - // On mac the DPI is always 72 so we should not scale it - return value; -#else - static const qreal scale = defaultDpiScale(); - return value * scale; -#endif -} - -static QSize dpiScaled(QSize value) -{ - return QSize(qRound(dpiScaled(value.width())), - qRound(dpiScaled(value.height()))); -} - - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QtPropertyEditorView; - -class QtTreePropertyBrowserPrivate -{ - QtTreePropertyBrowser *q_ptr; - Q_DECLARE_PUBLIC(QtTreePropertyBrowser) - -public: - QtTreePropertyBrowserPrivate(); - void init(QWidget *parent); - - void propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex); - void propertyRemoved(QtBrowserItem *index); - void propertyChanged(QtBrowserItem *index); - QWidget *createEditor(QtProperty *property, QWidget *parent) const - { return q_ptr->createEditor(property, parent); } - QtProperty *indexToProperty(const QModelIndex &index) const; - QTreeWidgetItem *indexToItem(const QModelIndex &index) const; - QtBrowserItem *indexToBrowserItem(const QModelIndex &index) const; - bool lastColumn(int column) const; - void disableItem(QTreeWidgetItem *item) const; - void enableItem(QTreeWidgetItem *item) const; - bool hasValue(QTreeWidgetItem *item) const; - - void slotCollapsed(const QModelIndex &index); - void slotExpanded(const QModelIndex &index); - - QColor calculatedBackgroundColor(QtBrowserItem *item) const; - - QtPropertyEditorView *treeWidget() const { return m_treeWidget; } - bool markPropertiesWithoutValue() const { return m_markPropertiesWithoutValue; } - - QtBrowserItem *currentItem() const; - void setCurrentItem(QtBrowserItem *browserItem, bool block); - void editItem(QtBrowserItem *browserItem); - - QList selectedItems() const; - - void slotCurrentBrowserItemChanged(QtBrowserItem *item); - void slotCurrentTreeItemChanged(QTreeWidgetItem *newItem, QTreeWidgetItem *); - void slotItemSelectionChanged(); - - QTreeWidgetItem *editedItem() const; - QtBrowserItem *editedBrowserItem() const; - -private: - void updateItem(QTreeWidgetItem *item); - - QMap m_indexToItem; - QMap m_itemToIndex; - - QMap m_indexToBackgroundColor; - - QtPropertyEditorView *m_treeWidget; - - bool m_headerVisible; - bool m_allowMultiSelection; - QtTreePropertyBrowser::ResizeMode m_resizeMode; - class QtPropertyEditorDelegate *m_delegate; - bool m_markPropertiesWithoutValue; - bool m_browserChangedBlocked; - QIcon m_expandIcon; -}; - -// ------------ QtPropertyEditorView -class QtPropertyEditorView : public QTreeWidget -{ - Q_OBJECT -public: - explicit QtPropertyEditorView(QWidget *parent = 0); - - void setEditorPrivate(QtTreePropertyBrowserPrivate *editorPrivate) - { m_editorPrivate = editorPrivate; } - - QTreeWidgetItem *indexToItem(const QModelIndex &index) const - { return itemFromIndex(index); } - -protected: - void keyPressEvent(QKeyEvent *event); - void mousePressEvent(QMouseEvent *event); - void drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; - -private: - QtTreePropertyBrowserPrivate *m_editorPrivate; -}; - -QtPropertyEditorView::QtPropertyEditorView(QWidget *parent) : - QTreeWidget(parent), - m_editorPrivate(0) -{ - setUniformRowHeights(true); - connect(header(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(resizeColumnToContents(int))); -} - -void QtPropertyEditorView::drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const -{ - QStyleOptionViewItem opt = option; - bool hasValue = true; - if (m_editorPrivate) { - QtProperty *property = m_editorPrivate->indexToProperty(index); - if (property) - hasValue = property->hasValue(); - } - if (!hasValue && m_editorPrivate->markPropertiesWithoutValue()) { - const QColor c = option.palette.color(QPalette::Dark); - painter->fillRect(option.rect, c); - opt.palette.setColor(QPalette::AlternateBase, c); - } else { - const QColor c = m_editorPrivate->calculatedBackgroundColor(m_editorPrivate->indexToBrowserItem(index)); - if (c.isValid()) { - painter->fillRect(option.rect, c); - opt.palette.setColor(QPalette::AlternateBase, c.lighter(112)); - } - } - QTreeWidget::drawRow(painter, opt, index); - QColor color = static_cast(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &opt)); - painter->save(); - painter->setPen(QPen(color)); - painter->drawLine(opt.rect.x(), opt.rect.bottom(), opt.rect.right(), opt.rect.bottom()); - painter->restore(); -} - -void QtPropertyEditorView::keyPressEvent(QKeyEvent *event) -{ - switch (event->key()) { - case Qt::Key_Return: - case Qt::Key_Enter: - case Qt::Key_Space: // Trigger Edit - if (!m_editorPrivate->editedItem()) - if (const QTreeWidgetItem *item = currentItem()) - if (item->columnCount() >= 2 && ((item->flags() & (Qt::ItemIsEditable | Qt::ItemIsEnabled)) == (Qt::ItemIsEditable | Qt::ItemIsEnabled))) { - event->accept(); - // If the current position is at column 0, move to 1. - QModelIndex index = currentIndex(); - if (index.column() == 0) { - index = index.sibling(index.row(), 1); - setCurrentIndex(index); - } - edit(index); - return; - } - break; - default: - break; - } - QTreeWidget::keyPressEvent(event); -} - -void QtPropertyEditorView::mousePressEvent(QMouseEvent *event) -{ - QTreeWidget::mousePressEvent(event); - QTreeWidgetItem *item = itemAt(event->pos()); - - if (item) { - if ((item != m_editorPrivate->editedItem()) && (event->button() == Qt::LeftButton) - && (header()->logicalIndexAt(event->pos().x()) == 1) - && ((item->flags() & (Qt::ItemIsEditable | Qt::ItemIsEnabled)) == (Qt::ItemIsEditable | Qt::ItemIsEnabled))) { - editItem(item, 1); - } else if (!m_editorPrivate->hasValue(item) && m_editorPrivate->markPropertiesWithoutValue() && !rootIsDecorated()) { - if (event->pos().x() + header()->offset() < 20) - item->setExpanded(!item->isExpanded()); - } - } -} - -// ------------ QtPropertyEditorDelegate -class QtPropertyEditorDelegate : public QItemDelegate -{ - Q_OBJECT -public: - explicit QtPropertyEditorDelegate(QObject *parent = 0) - : QItemDelegate(parent), m_editorPrivate(0), m_editedItem(0), m_editedWidget(0), m_disablePainting(false) - {} - - void setEditorPrivate(QtTreePropertyBrowserPrivate *editorPrivate) - { m_editorPrivate = editorPrivate; } - - QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, - const QModelIndex &index) const; - - void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, - const QModelIndex &index) const; - - void paint(QPainter *painter, const QStyleOptionViewItem &option, - const QModelIndex &index) const; - - QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; - - void setModelData(QWidget *, QAbstractItemModel *, - const QModelIndex &) const {} - - void setEditorData(QWidget *, const QModelIndex &) const {} - - bool eventFilter(QObject *object, QEvent *event); - void closeEditor(QtProperty *property); - - QTreeWidgetItem *editedItem() const { return m_editedItem; } - -protected: - - void drawDecoration(QPainter *painter, const QStyleOptionViewItem &option, - const QRect &rect, const QPixmap &pixmap) const; - void drawDisplay(QPainter *painter, const QStyleOptionViewItem &option, - const QRect &rect, const QString &text) const; - -private slots: - void slotEditorDestroyed(QObject *object); - -private: - int indentation(const QModelIndex &index) const; - - typedef QMap EditorToPropertyMap; - mutable EditorToPropertyMap m_editorToProperty; - - typedef QMap PropertyToEditorMap; - mutable PropertyToEditorMap m_propertyToEditor; - QtTreePropertyBrowserPrivate *m_editorPrivate; - mutable QTreeWidgetItem *m_editedItem; - mutable QWidget *m_editedWidget; - mutable bool m_disablePainting; -}; - -int QtPropertyEditorDelegate::indentation(const QModelIndex &index) const -{ - if (!m_editorPrivate) - return 0; - - QTreeWidgetItem *item = m_editorPrivate->indexToItem(index); - int indent = 0; - while (item->parent()) { - item = item->parent(); - ++indent; - } - if (m_editorPrivate->treeWidget()->rootIsDecorated()) - ++indent; - return indent * m_editorPrivate->treeWidget()->indentation(); -} - -void QtPropertyEditorDelegate::slotEditorDestroyed(QObject *object) -{ - if (QWidget *w = qobject_cast(object)) { - const EditorToPropertyMap::iterator it = m_editorToProperty.find(w); - if (it != m_editorToProperty.end()) { - m_propertyToEditor.remove(it.value()); - m_editorToProperty.erase(it); - } - if (m_editedWidget == w) { - m_editedWidget = 0; - m_editedItem = 0; - } - } -} - -void QtPropertyEditorDelegate::closeEditor(QtProperty *property) -{ - if (QWidget *w = m_propertyToEditor.value(property, 0)) - w->deleteLater(); -} - -QWidget *QtPropertyEditorDelegate::createEditor(QWidget *parent, - const QStyleOptionViewItem &, const QModelIndex &index) const -{ - if (index.column() == 1 && m_editorPrivate) { - QtProperty *property = m_editorPrivate->indexToProperty(index); - QTreeWidgetItem *item = m_editorPrivate->indexToItem(index); - if (property && item && (item->flags() & Qt::ItemIsEnabled)) { - QWidget *editor = m_editorPrivate->createEditor(property, parent); - if (editor) { - editor->setAutoFillBackground(true); - editor->installEventFilter(const_cast(this)); - connect(editor, SIGNAL(destroyed(QObject *)), this, SLOT(slotEditorDestroyed(QObject *))); - m_propertyToEditor[property] = editor; - m_editorToProperty[editor] = property; - m_editedItem = item; - m_editedWidget = editor; - } - return editor; - } - } - return 0; -} - -void QtPropertyEditorDelegate::updateEditorGeometry(QWidget *editor, - const QStyleOptionViewItem &option, const QModelIndex &index) const -{ - Q_UNUSED(index) - editor->setGeometry(option.rect.adjusted(0, 0, 0, -1)); -} - -void QtPropertyEditorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, - const QModelIndex &index) const -{ - bool hasValue = true; - if (m_editorPrivate) { - QtProperty *property = m_editorPrivate->indexToProperty(index); - if (property) - hasValue = property->hasValue(); - } - QStyleOptionViewItem opt = option; - if ((m_editorPrivate && index.column() == 0) || !hasValue) { - QtProperty *property = m_editorPrivate->indexToProperty(index); - if (property && property->isModified()) { - opt.font.setBold(true); - opt.fontMetrics = QFontMetrics(opt.font); - } - } - QColor c; - if (!hasValue && m_editorPrivate->markPropertiesWithoutValue()) { - c = opt.palette.color(QPalette::Dark); - opt.palette.setColor(QPalette::Text, opt.palette.color(QPalette::BrightText)); - } else { - c = m_editorPrivate->calculatedBackgroundColor(m_editorPrivate->indexToBrowserItem(index)); - if (c.isValid() && (opt.features & QStyleOptionViewItem::Alternate)) - c = c.lighter(112); - } - if (c.isValid()) - painter->fillRect(option.rect, c); - opt.state &= ~QStyle::State_HasFocus; - if (index.column() == 1) { - QTreeWidgetItem *item = m_editorPrivate->indexToItem(index); - if (m_editedItem && m_editedItem == item) - m_disablePainting = true; - } - QItemDelegate::paint(painter, opt, index); - if (option.type) - m_disablePainting = false; - - opt.palette.setCurrentColorGroup(QPalette::Active); - QColor color = static_cast(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &opt)); - painter->save(); - painter->setPen(QPen(color)); - if (!m_editorPrivate || (!m_editorPrivate->lastColumn(index.column()) && hasValue)) { - int right = (option.direction == Qt::LeftToRight) ? option.rect.right() : option.rect.left(); - painter->drawLine(right, option.rect.y(), right, option.rect.bottom()); - } - painter->restore(); -} - -void QtPropertyEditorDelegate::drawDecoration(QPainter *painter, const QStyleOptionViewItem &option, - const QRect &rect, const QPixmap &pixmap) const -{ - if (m_disablePainting) - return; - - QItemDelegate::drawDecoration(painter, option, rect, pixmap); -} - -void QtPropertyEditorDelegate::drawDisplay(QPainter *painter, const QStyleOptionViewItem &option, - const QRect &rect, const QString &text) const -{ - if (m_disablePainting) - return; - - QItemDelegate::drawDisplay(painter, option, rect, text); -} - -QSize QtPropertyEditorDelegate::sizeHint(const QStyleOptionViewItem &option, - const QModelIndex &index) const -{ - return QItemDelegate::sizeHint(option, index) + dpiScaled(QSize(3, 4)); -} - -bool QtPropertyEditorDelegate::eventFilter(QObject *object, QEvent *event) -{ - if (event->type() == QEvent::FocusOut) { - QFocusEvent *fe = static_cast(event); - if (fe->reason() == Qt::ActiveWindowFocusReason) - return false; - } - return QItemDelegate::eventFilter(object, event); -} - -// -------- QtTreePropertyBrowserPrivate implementation -QtTreePropertyBrowserPrivate::QtTreePropertyBrowserPrivate() : - m_treeWidget(0), - m_headerVisible(true), - m_allowMultiSelection(false), - m_resizeMode(QtTreePropertyBrowser::Stretch), - m_delegate(0), - m_markPropertiesWithoutValue(false), - m_browserChangedBlocked(false) -{ -} - -// Draw an icon indicating opened/closing branches -static QIcon drawIndicatorIcon(const QPalette &palette, QStyle *style) -{ - QPixmap pix(14, 14); - pix.fill(Qt::transparent); - QStyleOption branchOption; - QRect r(QPoint(0, 0), pix.size()); - branchOption.rect = QRect(2, 2, 9, 9); // ### hardcoded in qcommonstyle.cpp - branchOption.palette = palette; - branchOption.state = QStyle::State_Children; - - QPainter p; - // Draw closed state - p.begin(&pix); - style->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, &p); - p.end(); - QIcon rc = pix; - rc.addPixmap(pix, QIcon::Selected, QIcon::Off); - // Draw opened state - branchOption.state |= QStyle::State_Open; - pix.fill(Qt::transparent); - p.begin(&pix); - style->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, &p); - p.end(); - - rc.addPixmap(pix, QIcon::Normal, QIcon::On); - rc.addPixmap(pix, QIcon::Selected, QIcon::On); - return rc; -} - -void QtTreePropertyBrowserPrivate::init(QWidget *parent) -{ - QHBoxLayout *layout = new QHBoxLayout(parent); - layout->setContentsMargins(0, 0, 0, 0); - m_treeWidget = new QtPropertyEditorView(parent); - m_treeWidget->setEditorPrivate(this); - m_treeWidget->setIconSize(QSize(18, 18)); - layout->addWidget(m_treeWidget); - parent->setFocusProxy(m_treeWidget); - - m_treeWidget->setColumnCount(2); - QStringList labels; - labels.append(QCoreApplication::translate("QtTreePropertyBrowser", "Property")); - labels.append(QCoreApplication::translate("QtTreePropertyBrowser", "Value")); - m_treeWidget->setHeaderLabels(labels); - m_treeWidget->setAlternatingRowColors(true); - m_treeWidget->setEditTriggers(QAbstractItemView::EditKeyPressed); - m_delegate = new QtPropertyEditorDelegate(parent); - m_delegate->setEditorPrivate(this); - m_treeWidget->setItemDelegate(m_delegate); -#if QT_VERSION >= 0x050000 - m_treeWidget->header()->setSectionsMovable(false); - m_treeWidget->header()->setSectionResizeMode(QHeaderView::Stretch); -#else - m_treeWidget->header()->setMovable(false); - m_treeWidget->header()->setResizeMode(QHeaderView::Stretch); -#endif - - m_expandIcon = drawIndicatorIcon(q_ptr->palette(), q_ptr->style()); - - QObject::connect(m_treeWidget, SIGNAL(collapsed(const QModelIndex &)), q_ptr, SLOT(slotCollapsed(const QModelIndex &))); - QObject::connect(m_treeWidget, SIGNAL(expanded(const QModelIndex &)), q_ptr, SLOT(slotExpanded(const QModelIndex &))); - QObject::connect(m_treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), q_ptr, SLOT(slotCurrentTreeItemChanged(QTreeWidgetItem*,QTreeWidgetItem*))); - QObject::connect(m_treeWidget, SIGNAL(itemSelectionChanged()), q_ptr, SLOT(slotItemSelectionChanged())); -} - -QtBrowserItem *QtTreePropertyBrowserPrivate::currentItem() const -{ - if (QTreeWidgetItem *treeItem = m_treeWidget->currentItem()) - return m_itemToIndex.value(treeItem); - return 0; -} - -void QtTreePropertyBrowserPrivate::setCurrentItem(QtBrowserItem *browserItem, bool block) -{ - const bool blocked = block ? m_treeWidget->blockSignals(true) : false; - if (browserItem == 0) - m_treeWidget->setCurrentItem(0); - else - m_treeWidget->setCurrentItem(m_indexToItem.value(browserItem)); - if (block) - m_treeWidget->blockSignals(blocked); -} - -QtProperty *QtTreePropertyBrowserPrivate::indexToProperty(const QModelIndex &index) const -{ - QTreeWidgetItem *item = m_treeWidget->indexToItem(index); - QtBrowserItem *idx = m_itemToIndex.value(item); - if (idx) - return idx->property(); - return 0; -} - -QtBrowserItem *QtTreePropertyBrowserPrivate::indexToBrowserItem(const QModelIndex &index) const -{ - QTreeWidgetItem *item = m_treeWidget->indexToItem(index); - return m_itemToIndex.value(item); -} - -QTreeWidgetItem *QtTreePropertyBrowserPrivate::indexToItem(const QModelIndex &index) const -{ - return m_treeWidget->indexToItem(index); -} - -bool QtTreePropertyBrowserPrivate::lastColumn(int column) const -{ - return m_treeWidget->header()->visualIndex(column) == m_treeWidget->columnCount() - 1; -} - -void QtTreePropertyBrowserPrivate::disableItem(QTreeWidgetItem *item) const -{ - Qt::ItemFlags flags = item->flags(); - if (flags & Qt::ItemIsEnabled) { - flags &= ~Qt::ItemIsEnabled; - item->setFlags(flags); - m_delegate->closeEditor(m_itemToIndex[item]->property()); - const int childCount = item->childCount(); - for (int i = 0; i < childCount; i++) { - QTreeWidgetItem *child = item->child(i); - disableItem(child); - } - } -} - -void QtTreePropertyBrowserPrivate::enableItem(QTreeWidgetItem *item) const -{ - Qt::ItemFlags flags = item->flags(); - flags |= Qt::ItemIsEnabled; - item->setFlags(flags); - const int childCount = item->childCount(); - for (int i = 0; i < childCount; i++) { - QTreeWidgetItem *child = item->child(i); - QtProperty *property = m_itemToIndex[child]->property(); - if (property->isEnabled()) { - enableItem(child); - } - } -} - -bool QtTreePropertyBrowserPrivate::hasValue(QTreeWidgetItem *item) const -{ - QtBrowserItem *browserItem = m_itemToIndex.value(item); - if (browserItem) - return browserItem->property()->hasValue(); - return false; -} - -void QtTreePropertyBrowserPrivate::propertyInserted(QtBrowserItem *index, QtBrowserItem *afterIndex) -{ - QTreeWidgetItem *afterItem = m_indexToItem.value(afterIndex); - QTreeWidgetItem *parentItem = m_indexToItem.value(index->parent()); - - QTreeWidgetItem *newItem = 0; - if (parentItem) { - newItem = new QTreeWidgetItem(parentItem, afterItem); - } else { - newItem = new QTreeWidgetItem(m_treeWidget, afterItem); - } - m_itemToIndex[newItem] = index; - m_indexToItem[index] = newItem; - - newItem->setFlags(newItem->flags() | Qt::ItemIsEditable); - newItem->setExpanded(true); - - updateItem(newItem); -} - -void QtTreePropertyBrowserPrivate::propertyRemoved(QtBrowserItem *index) -{ - QTreeWidgetItem *item = m_indexToItem.value(index); - - if (m_treeWidget->currentItem() == item) { - m_treeWidget->setCurrentItem(0); - } - - delete item; - - m_indexToItem.remove(index); - m_itemToIndex.remove(item); - m_indexToBackgroundColor.remove(index); -} - -void QtTreePropertyBrowserPrivate::propertyChanged(QtBrowserItem *index) -{ - QTreeWidgetItem *item = m_indexToItem.value(index); - - updateItem(item); -} - -void QtTreePropertyBrowserPrivate::updateItem(QTreeWidgetItem *item) -{ - QtProperty *property = m_itemToIndex[item]->property(); - - if (property->nameColor().isValid()) - item->setForeground(0, QBrush(property->nameColor())); - if (property->valueColor().isValid()) - item->setForeground(1, QBrush(property->valueColor())); - - QIcon expandIcon; - if (property->hasValue()) { - QString toolTip = property->toolTip(); - if (toolTip.isEmpty()) - toolTip = property->displayText(); - item->setToolTip(1, toolTip); - item->setIcon(1, property->valueIcon()); - property->displayText().isEmpty() ? item->setText(1, property->valueText()) : item->setText(1, property->displayText()); - } else if (markPropertiesWithoutValue() && !m_treeWidget->rootIsDecorated()) { - expandIcon = m_expandIcon; - } - item->setIcon(0, expandIcon); - item->setFirstColumnSpanned(!property->hasValue()); - item->setToolTip(0, property->propertyName()); - item->setStatusTip(0, property->statusTip()); - item->setWhatsThis(0, property->whatsThis()); - item->setText(0, property->propertyName()); - bool wasEnabled = item->flags() & Qt::ItemIsEnabled; - bool isEnabled = wasEnabled; - if (property->isEnabled()) { - QTreeWidgetItem *parent = item->parent(); - if (!parent || (parent->flags() & Qt::ItemIsEnabled)) - isEnabled = true; - else - isEnabled = false; - } else { - isEnabled = false; - } - if (wasEnabled != isEnabled) { - if (isEnabled) - enableItem(item); - else - disableItem(item); - } - m_treeWidget->viewport()->update(); -} - -QColor QtTreePropertyBrowserPrivate::calculatedBackgroundColor(QtBrowserItem *item) const -{ - QtBrowserItem *i = item; - const QMap::const_iterator itEnd = m_indexToBackgroundColor.constEnd(); - while (i) { - QMap::const_iterator it = m_indexToBackgroundColor.constFind(i); - if (it != itEnd) - return it.value(); - i = i->parent(); - } - return QColor(); -} - -void QtTreePropertyBrowserPrivate::slotCollapsed(const QModelIndex &index) -{ - QTreeWidgetItem *item = indexToItem(index); - QtBrowserItem *idx = m_itemToIndex.value(item); - if (item) - emit q_ptr->collapsed(idx); -} - -void QtTreePropertyBrowserPrivate::slotExpanded(const QModelIndex &index) -{ - QTreeWidgetItem *item = indexToItem(index); - QtBrowserItem *idx = m_itemToIndex.value(item); - if (item) - emit q_ptr->expanded(idx); -} - -void QtTreePropertyBrowserPrivate::slotCurrentBrowserItemChanged(QtBrowserItem *item) -{ - if (!m_browserChangedBlocked && item != currentItem()) - setCurrentItem(item, true); -} - -void QtTreePropertyBrowserPrivate::slotCurrentTreeItemChanged(QTreeWidgetItem *newItem, QTreeWidgetItem *) -{ - QtBrowserItem *browserItem = newItem ? m_itemToIndex.value(newItem) : 0; - m_browserChangedBlocked = true; - q_ptr->setCurrentItem(browserItem); - m_browserChangedBlocked = false; -} - -void QtTreePropertyBrowserPrivate::slotItemSelectionChanged() -{ - emit q_ptr->selectedItemsChanged(); -} - -QTreeWidgetItem *QtTreePropertyBrowserPrivate::editedItem() const -{ - return m_delegate->editedItem(); -} - -QtBrowserItem *QtTreePropertyBrowserPrivate::editedBrowserItem() const -{ - return m_itemToIndex.value(editedItem()); -} - -void QtTreePropertyBrowserPrivate::editItem(QtBrowserItem *browserItem) -{ - if (QTreeWidgetItem *treeItem = m_indexToItem.value(browserItem, 0)) { - m_treeWidget->setCurrentItem (treeItem, 1); - m_treeWidget->editItem(treeItem, 1); - } -} - -QList QtTreePropertyBrowserPrivate::selectedItems() const -{ - const QList selectedTreeItems = m_treeWidget->selectedItems(); - QList browserItems; - - for (QTreeWidgetItem *treeItem : selectedTreeItems) - if (QtBrowserItem *browserItem = m_itemToIndex.value(treeItem, 0)) - browserItems.append(browserItem); - - return browserItems; -} - -/*! - \class QtTreePropertyBrowser - - \brief The QtTreePropertyBrowser class provides QTreeWidget based - property browser. - - A property browser is a widget that enables the user to edit a - given set of properties. Each property is represented by a label - specifying the property's name, and an editing widget (e.g. a line - edit or a combobox) holding its value. A property can have zero or - more subproperties. - - QtTreePropertyBrowser provides a tree based view for all nested - properties, i.e. properties that have subproperties can be in an - expanded (subproperties are visible) or collapsed (subproperties - are hidden) state. For example: - - \image qttreepropertybrowser.png - - Use the QtAbstractPropertyBrowser API to add, insert and remove - properties from an instance of the QtTreePropertyBrowser class. - The properties themselves are created and managed by - implementations of the QtAbstractPropertyManager class. - - \sa QtGroupBoxPropertyBrowser, QtAbstractPropertyBrowser -*/ - -/*! - \fn void QtTreePropertyBrowser::collapsed(QtBrowserItem *item) - - This signal is emitted when the \a item is collapsed. - - \sa expanded(), setExpanded() -*/ - -/*! - \fn void QtTreePropertyBrowser::expanded(QtBrowserItem *item) - - This signal is emitted when the \a item is expanded. - - \sa collapsed(), setExpanded() -*/ - -/*! - Creates a property browser with the given \a parent. -*/ -QtTreePropertyBrowser::QtTreePropertyBrowser(QWidget *parent) - : QtAbstractPropertyBrowser(parent) -{ - d_ptr = new QtTreePropertyBrowserPrivate; - d_ptr->q_ptr = this; - - d_ptr->init(this); - connect(this, SIGNAL(currentItemChanged(QtBrowserItem*)), this, SLOT(slotCurrentBrowserItemChanged(QtBrowserItem*))); -} - -/*! - Destroys this property browser. - - Note that the properties that were inserted into this browser are - \e not destroyed since they may still be used in other - browsers. The properties are owned by the manager that created - them. - - \sa QtProperty, QtAbstractPropertyManager -*/ -QtTreePropertyBrowser::~QtTreePropertyBrowser() -{ - delete d_ptr; -} - -/*! - \property QtTreePropertyBrowser::indentation - \brief indentation of the items in the tree view. -*/ -int QtTreePropertyBrowser::indentation() const -{ - return d_ptr->m_treeWidget->indentation(); -} - -void QtTreePropertyBrowser::setIndentation(int i) -{ - d_ptr->m_treeWidget->setIndentation(i); -} - -/*! - \property QtTreePropertyBrowser::rootIsDecorated - \brief whether to show controls for expanding and collapsing root items. -*/ -bool QtTreePropertyBrowser::rootIsDecorated() const -{ - return d_ptr->m_treeWidget->rootIsDecorated(); -} - -void QtTreePropertyBrowser::setRootIsDecorated(bool show) -{ - d_ptr->m_treeWidget->setRootIsDecorated(show); - QMapIterator it(d_ptr->m_itemToIndex); - while (it.hasNext()) { - QtProperty *property = it.next().value()->property(); - if (!property->hasValue()) - d_ptr->updateItem(it.key()); - } -} - -/*! - \property QtTreePropertyBrowser::alternatingRowColors - \brief whether to draw the background using alternating colors. - By default this property is set to true. -*/ -bool QtTreePropertyBrowser::alternatingRowColors() const -{ - return d_ptr->m_treeWidget->alternatingRowColors(); -} - -void QtTreePropertyBrowser::setAlternatingRowColors(bool enable) -{ - d_ptr->m_treeWidget->setAlternatingRowColors(enable); - QMapIterator it(d_ptr->m_itemToIndex); -} - -/*! - \property QtTreePropertyBrowser::headerVisible - \brief whether to show the header. -*/ -bool QtTreePropertyBrowser::isHeaderVisible() const -{ - return d_ptr->m_headerVisible; -} - -void QtTreePropertyBrowser::setHeaderVisible(bool visible) -{ - if (d_ptr->m_headerVisible == visible) - return; - - d_ptr->m_headerVisible = visible; - d_ptr->m_treeWidget->header()->setVisible(visible); -} - -/*! - \property QtTreePropertyBrowser::allowMultiSelection - \brief whether to allow multiple selection items. -*/ -bool QtTreePropertyBrowser::allowMultiSelection() const -{ - return d_ptr->m_allowMultiSelection; -} - -void QtTreePropertyBrowser::setAllowMultiSelection(bool multiSelection) -{ - if (d_ptr->m_allowMultiSelection == multiSelection) - return; - - d_ptr->m_allowMultiSelection = multiSelection; - d_ptr->m_treeWidget->setSelectionMode(multiSelection ? QAbstractItemView::ExtendedSelection - : QAbstractItemView::SingleSelection); -} - -/*! - \enum QtTreePropertyBrowser::ResizeMode - - The resize mode specifies the behavior of the header sections. - - \value Interactive The user can resize the sections. - The sections can also be resized programmatically using setSplitterPosition(). - - \value Fixed The user cannot resize the section. - The section can only be resized programmatically using setSplitterPosition(). - - \value Stretch QHeaderView will automatically resize the section to fill the available space. - The size cannot be changed by the user or programmatically. - - \value ResizeToContents QHeaderView will automatically resize the section to its optimal - size based on the contents of the entire column. - The size cannot be changed by the user or programmatically. - - \sa setResizeMode() -*/ - -/*! - \property QtTreePropertyBrowser::resizeMode - \brief the resize mode of setions in the header. -*/ - -QtTreePropertyBrowser::ResizeMode QtTreePropertyBrowser::resizeMode() const -{ - return d_ptr->m_resizeMode; -} - -void QtTreePropertyBrowser::setResizeMode(QtTreePropertyBrowser::ResizeMode mode) -{ - if (d_ptr->m_resizeMode == mode) - return; - - d_ptr->m_resizeMode = mode; - QHeaderView::ResizeMode m = QHeaderView::Stretch; - switch (mode) { - case QtTreePropertyBrowser::Interactive: m = QHeaderView::Interactive; break; - case QtTreePropertyBrowser::Fixed: m = QHeaderView::Fixed; break; - case QtTreePropertyBrowser::ResizeToContents: m = QHeaderView::ResizeToContents; break; - case QtTreePropertyBrowser::Stretch: - default: m = QHeaderView::Stretch; break; - } -#if QT_VERSION >= 0x050000 - d_ptr->m_treeWidget->header()->setSectionResizeMode(m); -#else - d_ptr->m_treeWidget->header()->setResizeMode(m); -#endif -} - -/*! - \property QtTreePropertyBrowser::splitterPosition - \brief the position of the splitter between the colunms. -*/ - -int QtTreePropertyBrowser::splitterPosition() const -{ - return d_ptr->m_treeWidget->header()->sectionSize(0); -} - -void QtTreePropertyBrowser::setSplitterPosition(int position) -{ - d_ptr->m_treeWidget->header()->resizeSection(0, position); -} - -int QtTreePropertyBrowser::scrollPosition() const -{ - return d_ptr->m_treeWidget->verticalScrollBar()->value(); -} - -void QtTreePropertyBrowser::setScrollPosition(int value) -{ - d_ptr->m_treeWidget->verticalScrollBar()->setValue(value); -} - -/*! - Sets the \a item to either collapse or expanded, depending on the value of \a expanded. - - \sa isExpanded(), expanded(), collapsed() -*/ - -void QtTreePropertyBrowser::setExpanded(QtBrowserItem *item, bool expanded) -{ - QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item); - if (treeItem) - treeItem->setExpanded(expanded); -} - -/*! - Returns true if the \a item is expanded; otherwise returns false. - - \sa setExpanded() -*/ - -bool QtTreePropertyBrowser::isExpanded(QtBrowserItem *item) const -{ - QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item); - if (treeItem) - return treeItem->isExpanded(); - return false; -} - -/*! - Returns true if the \a item is visible; otherwise returns false. - - \sa setItemVisible() - \since 4.5 -*/ - -bool QtTreePropertyBrowser::isItemVisible(QtBrowserItem *item) const -{ - if (const QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item)) - return !treeItem->isHidden(); - return false; -} - -/*! - Sets the \a item to be visible, depending on the value of \a visible. - - \sa isItemVisible() - \since 4.5 -*/ - -void QtTreePropertyBrowser::setItemVisible(QtBrowserItem *item, bool visible) -{ - if (QTreeWidgetItem *treeItem = d_ptr->m_indexToItem.value(item)) - treeItem->setHidden(!visible); -} - -/*! - Sets the \a item's background color to \a color. Note that while item's background - is rendered every second row is being drawn with alternate color (which is a bit lighter than items \a color) - - \sa backgroundColor(), calculatedBackgroundColor() -*/ - -void QtTreePropertyBrowser::setBackgroundColor(QtBrowserItem *item, const QColor &color) -{ - if (!d_ptr->m_indexToItem.contains(item)) - return; - if (color.isValid()) - d_ptr->m_indexToBackgroundColor[item] = color; - else - d_ptr->m_indexToBackgroundColor.remove(item); - d_ptr->m_treeWidget->viewport()->update(); -} - -/*! - Returns the \a item's color. If there is no color set for item it returns invalid color. - - \sa calculatedBackgroundColor(), setBackgroundColor() -*/ - -QColor QtTreePropertyBrowser::backgroundColor(QtBrowserItem *item) const -{ - return d_ptr->m_indexToBackgroundColor.value(item); -} - -/*! - Returns the \a item's color. If there is no color set for item it returns parent \a item's - color (if there is no color set for parent it returns grandparent's color and so on). In case - the color is not set for \a item and it's top level item it returns invalid color. - - \sa backgroundColor(), setBackgroundColor() -*/ - -QColor QtTreePropertyBrowser::calculatedBackgroundColor(QtBrowserItem *item) const -{ - return d_ptr->calculatedBackgroundColor(item); -} - -/*! - \property QtTreePropertyBrowser::propertiesWithoutValueMarked - \brief whether to enable or disable marking properties without value. - - When marking is enabled the item's background is rendered in dark color and item's - foreground is rendered with light color. - - \sa propertiesWithoutValueMarked() -*/ -void QtTreePropertyBrowser::setPropertiesWithoutValueMarked(bool mark) -{ - if (d_ptr->m_markPropertiesWithoutValue == mark) - return; - - d_ptr->m_markPropertiesWithoutValue = mark; - QMapIterator it(d_ptr->m_itemToIndex); - while (it.hasNext()) { - QtProperty *property = it.next().value()->property(); - if (!property->hasValue()) - d_ptr->updateItem(it.key()); - } - d_ptr->m_treeWidget->viewport()->update(); -} - -bool QtTreePropertyBrowser::propertiesWithoutValueMarked() const -{ - return d_ptr->m_markPropertiesWithoutValue; -} - -/*! - \reimp -*/ -void QtTreePropertyBrowser::itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem) -{ - d_ptr->propertyInserted(item, afterItem); -} - -/*! - \reimp -*/ -void QtTreePropertyBrowser::itemRemoved(QtBrowserItem *item) -{ - d_ptr->propertyRemoved(item); -} - -/*! - \reimp -*/ -void QtTreePropertyBrowser::itemChanged(QtBrowserItem *item) -{ - d_ptr->propertyChanged(item); -} - -/*! - Sets the current item to \a item and opens the relevant editor for it. -*/ -void QtTreePropertyBrowser::editItem(QtBrowserItem *item) -{ - d_ptr->editItem(item); -} - -/*! - Returns the current item being edited, if any. -*/ -QtBrowserItem *QtTreePropertyBrowser::editedItem() const -{ - return d_ptr->editedBrowserItem(); -} - -/*! - Returns the selected items. - - \sa setAllowMultiSelection() -*/ -QList QtTreePropertyBrowser::selectedItems() const -{ - return d_ptr->selectedItems(); -} - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#include "moc_qttreepropertybrowser.cpp" -#include "qttreepropertybrowser.moc" diff --git a/src/qtpropertybrowser/src/qttreepropertybrowser.h b/src/qtpropertybrowser/src/qttreepropertybrowser.h deleted file mode 100644 index 6364a36ec9..0000000000 --- a/src/qtpropertybrowser/src/qttreepropertybrowser.h +++ /dev/null @@ -1,150 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QTTREEPROPERTYBROWSER_H -#define QTTREEPROPERTYBROWSER_H - -#include "qtpropertybrowser.h" - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QTreeWidgetItem; -class QtTreePropertyBrowserPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtTreePropertyBrowser : public QtAbstractPropertyBrowser -{ - Q_OBJECT - Q_ENUMS(ResizeMode) - Q_PROPERTY(int indentation READ indentation WRITE setIndentation) - Q_PROPERTY(bool rootIsDecorated READ rootIsDecorated WRITE setRootIsDecorated) - Q_PROPERTY(bool alternatingRowColors READ alternatingRowColors WRITE setAlternatingRowColors) - Q_PROPERTY(bool headerVisible READ isHeaderVisible WRITE setHeaderVisible) - Q_PROPERTY(ResizeMode resizeMode READ resizeMode WRITE setResizeMode) - Q_PROPERTY(int splitterPosition READ splitterPosition WRITE setSplitterPosition) - Q_PROPERTY(bool propertiesWithoutValueMarked READ propertiesWithoutValueMarked WRITE setPropertiesWithoutValueMarked) -public: - - enum ResizeMode - { - Interactive, - Stretch, - Fixed, - ResizeToContents - }; - - QtTreePropertyBrowser(QWidget *parent = 0); - ~QtTreePropertyBrowser(); - - int indentation() const; - void setIndentation(int i); - - bool rootIsDecorated() const; - void setRootIsDecorated(bool show); - - bool alternatingRowColors() const; - void setAlternatingRowColors(bool enable); - - bool isHeaderVisible() const; - void setHeaderVisible(bool visible); - - bool allowMultiSelection() const; - void setAllowMultiSelection(bool multiSelection); - - ResizeMode resizeMode() const; - void setResizeMode(ResizeMode mode); - - int splitterPosition() const; - void setSplitterPosition(int position); - - int scrollPosition() const; - void setScrollPosition(int value); - - void setExpanded(QtBrowserItem *item, bool expanded); - bool isExpanded(QtBrowserItem *item) const; - - bool isItemVisible(QtBrowserItem *item) const; - void setItemVisible(QtBrowserItem *item, bool visible); - - void setBackgroundColor(QtBrowserItem *item, const QColor &color); - QColor backgroundColor(QtBrowserItem *item) const; - QColor calculatedBackgroundColor(QtBrowserItem *item) const; - - void setPropertiesWithoutValueMarked(bool mark); - bool propertiesWithoutValueMarked() const; - - void editItem(QtBrowserItem *item); - QtBrowserItem *editedItem() const; - - QList selectedItems() const; - -Q_SIGNALS: - - void collapsed(QtBrowserItem *item); - void expanded(QtBrowserItem *item); - - void selectedItemsChanged(); - -protected: - virtual void itemInserted(QtBrowserItem *item, QtBrowserItem *afterItem); - virtual void itemRemoved(QtBrowserItem *item); - virtual void itemChanged(QtBrowserItem *item); - -private: - - QtTreePropertyBrowserPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtTreePropertyBrowser) - Q_DISABLE_COPY(QtTreePropertyBrowser) - - Q_PRIVATE_SLOT(d_func(), void slotCollapsed(const QModelIndex &)) - Q_PRIVATE_SLOT(d_func(), void slotExpanded(const QModelIndex &)) - Q_PRIVATE_SLOT(d_func(), void slotCurrentBrowserItemChanged(QtBrowserItem *)) - Q_PRIVATE_SLOT(d_func(), void slotCurrentTreeItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)) - Q_PRIVATE_SLOT(d_func(), void slotItemSelectionChanged()) - -}; - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#endif diff --git a/src/qtpropertybrowser/src/qtvariantproperty.cpp b/src/qtpropertybrowser/src/qtvariantproperty.cpp deleted file mode 100644 index b2b4c1de3c..0000000000 --- a/src/qtpropertybrowser/src/qtvariantproperty.cpp +++ /dev/null @@ -1,2291 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "qtvariantproperty.h" -#include "qtpropertymanager.h" -#include "qteditorfactory.h" -#include -#include -#include -#include - -#if defined(Q_CC_MSVC) -# pragma warning(disable: 4786) /* MS VS 6: truncating debug info after 255 characters */ -#endif - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -class QtEnumPropertyType -{ -}; - - -class QtFlagPropertyType -{ -}; - - -class QtGroupPropertyType -{ -}; - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -Q_DECLARE_METATYPE(QtEnumPropertyType) -Q_DECLARE_METATYPE(QtFlagPropertyType) -Q_DECLARE_METATYPE(QtGroupPropertyType) - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -/*! - Returns the type id for an enum property. - - Note that the property's value type can be retrieved using the - valueType() function (which is QVariant::Int for the enum property - type). - - \sa propertyType(), valueType() -*/ -int QtVariantPropertyManager::enumTypeId() -{ - return qMetaTypeId(); -} - -/*! - Returns the type id for a flag property. - - Note that the property's value type can be retrieved using the - valueType() function (which is QVariant::Int for the flag property - type). - - \sa propertyType(), valueType() -*/ -int QtVariantPropertyManager::flagTypeId() -{ - return qMetaTypeId(); -} - -/*! - Returns the type id for a group property. - - Note that the property's value type can be retrieved using the - valueType() function (which is QVariant::Invalid for the group - property type, since it doesn't provide any value). - - \sa propertyType(), valueType() -*/ -int QtVariantPropertyManager::groupTypeId() -{ - return qMetaTypeId(); -} - -/*! - Returns the type id for a icon map attribute. - - Note that the property's attribute type can be retrieved using the - attributeType() function. - - \sa attributeType(), QtEnumPropertyManager::enumIcons() -*/ -int QtVariantPropertyManager::iconMapTypeId() -{ - return qMetaTypeId(); -} - -typedef QMap PropertyMap; -Q_GLOBAL_STATIC(PropertyMap, propertyToWrappedProperty) - -static QtProperty *wrappedProperty(QtProperty *property) -{ - return propertyToWrappedProperty()->value(property, 0); -} - -class QtVariantPropertyPrivate -{ -public: - QtVariantPropertyPrivate(QtVariantPropertyManager *m) : manager(m) {} - - QtVariantPropertyManager *manager; -}; - -/*! - \class QtVariantProperty - - \brief The QtVariantProperty class is a convenience class handling - QVariant based properties. - - QtVariantProperty provides additional API: A property's type, - value type, attribute values and current value can easily be - retrieved using the propertyType(), valueType(), attributeValue() - and value() functions respectively. In addition, the attribute - values and the current value can be set using the corresponding - setValue() and setAttribute() functions. - - For example, instead of writing: - - \code - QtVariantPropertyManager *variantPropertyManager; - QtProperty *property; - - variantPropertyManager->setValue(property, 10); - \endcode - - you can write: - - \code - QtVariantPropertyManager *variantPropertyManager; - QtVariantProperty *property; - - property->setValue(10); - \endcode - - QtVariantProperty instances can only be created by the - QtVariantPropertyManager class. - - \sa QtProperty, QtVariantPropertyManager, QtVariantEditorFactory -*/ - -/*! - Creates a variant property using the given \a manager. - - Do not use this constructor to create variant property instances; - use the QtVariantPropertyManager::addProperty() function - instead. This constructor is used internally by the - QtVariantPropertyManager::createProperty() function. - - \sa QtVariantPropertyManager -*/ -QtVariantProperty::QtVariantProperty(QtVariantPropertyManager *manager) - : QtProperty(manager), d_ptr(new QtVariantPropertyPrivate(manager)) -{ - -} - -/*! - Destroys this property. - - \sa QtProperty::~QtProperty() -*/ -QtVariantProperty::~QtVariantProperty() -{ - delete d_ptr; -} - -/*! - Returns the property's current value. - - \sa valueType(), setValue() -*/ -QVariant QtVariantProperty::value() const -{ - return d_ptr->manager->value(this); -} - -/*! - Returns this property's value for the specified \a attribute. - - QtVariantPropertyManager provides a couple of related functions: - \l{QtVariantPropertyManager::attributes()}{attributes()} and - \l{QtVariantPropertyManager::attributeType()}{attributeType()}. - - \sa setAttribute() -*/ -QVariant QtVariantProperty::attributeValue(const QString &attribute) const -{ - return d_ptr->manager->attributeValue(this, attribute); -} - -/*! - Returns the type of this property's value. - - \sa propertyType() -*/ -int QtVariantProperty::valueType() const -{ - return d_ptr->manager->valueType(this); -} - -/*! - Returns this property's type. - - QtVariantPropertyManager provides several related functions: - \l{QtVariantPropertyManager::enumTypeId()}{enumTypeId()}, - \l{QtVariantPropertyManager::flagTypeId()}{flagTypeId()} and - \l{QtVariantPropertyManager::groupTypeId()}{groupTypeId()}. - - \sa valueType() -*/ -int QtVariantProperty::propertyType() const -{ - return d_ptr->manager->propertyType(this); -} - -/*! - Sets the value of this property to \a value. - - The specified \a value must be of the type returned by - valueType(), or of a type that can be converted to valueType() - using the QVariant::canConvert() function; otherwise this function - does nothing. - - \sa value() -*/ -void QtVariantProperty::setValue(const QVariant &value) -{ - d_ptr->manager->setValue(this, value); -} - -/*! - Sets the \a attribute of property to \a value. - - QtVariantPropertyManager provides the related - \l{QtVariantPropertyManager::setAttribute()}{setAttribute()} - function. - - \sa attributeValue() -*/ -void QtVariantProperty::setAttribute(const QString &attribute, const QVariant &value) -{ - d_ptr->manager->setAttribute(this, attribute, value); -} - -class QtVariantPropertyManagerPrivate -{ - QtVariantPropertyManager *q_ptr; - Q_DECLARE_PUBLIC(QtVariantPropertyManager) -public: - QtVariantPropertyManagerPrivate(); - - bool m_creatingProperty; - bool m_creatingSubProperties; - bool m_destroyingSubProperties; - int m_propertyType; - - void slotValueChanged(QtProperty *property, int val); - void slotRangeChanged(QtProperty *property, int min, int max); - void slotSingleStepChanged(QtProperty *property, int step); - void slotValueChanged(QtProperty *property, double val); - void slotRangeChanged(QtProperty *property, double min, double max); - void slotSingleStepChanged(QtProperty *property, double step); - void slotDecimalsChanged(QtProperty *property, int prec); - void slotValueChanged(QtProperty *property, bool val); - void slotValueChanged(QtProperty *property, const QString &val); - void slotRegExpChanged(QtProperty *property, const QRegularExpression ®Exp); - void slotEchoModeChanged(QtProperty *property, int); - void slotValueChanged(QtProperty *property, const QDate &val); - void slotRangeChanged(QtProperty *property, const QDate &min, const QDate &max); - void slotValueChanged(QtProperty *property, const QTime &val); - void slotValueChanged(QtProperty *property, const QDateTime &val); - void slotValueChanged(QtProperty *property, const QKeySequence &val); - void slotValueChanged(QtProperty *property, const QChar &val); - void slotValueChanged(QtProperty *property, const QLocale &val); - void slotValueChanged(QtProperty *property, const QPoint &val); - void slotValueChanged(QtProperty *property, const QPointF &val); - void slotValueChanged(QtProperty *property, const QSize &val); - void slotRangeChanged(QtProperty *property, const QSize &min, const QSize &max); - void slotValueChanged(QtProperty *property, const QSizeF &val); - void slotRangeChanged(QtProperty *property, const QSizeF &min, const QSizeF &max); - void slotValueChanged(QtProperty *property, const QRect &val); - void slotConstraintChanged(QtProperty *property, const QRect &val); - void slotValueChanged(QtProperty *property, const QRectF &val); - void slotConstraintChanged(QtProperty *property, const QRectF &val); - void slotValueChanged(QtProperty *property, const QColor &val); - void slotEnumChanged(QtProperty *property, int val); - void slotEnumNamesChanged(QtProperty *property, const QStringList &enumNames); - void slotEnumIconsChanged(QtProperty *property, const QMap &enumIcons); - void slotValueChanged(QtProperty *property, const QSizePolicy &val); - void slotValueChanged(QtProperty *property, const QFont &val); - void slotValueChanged(QtProperty *property, const QCursor &val); - void slotFlagChanged(QtProperty *property, int val); - void slotFlagNamesChanged(QtProperty *property, const QStringList &flagNames); - void slotReadOnlyChanged(QtProperty *property, bool readOnly); - void slotTextVisibleChanged(QtProperty *property, bool textVisible); - void slotPropertyInserted(QtProperty *property, QtProperty *parent, QtProperty *after); - void slotPropertyRemoved(QtProperty *property, QtProperty *parent); - - void valueChanged(QtProperty *property, const QVariant &val); - - int internalPropertyToType(QtProperty *property) const; - QtVariantProperty *createSubProperty(QtVariantProperty *parent, QtVariantProperty *after, - QtProperty *internal); - void removeSubProperty(QtVariantProperty *property); - - QMap m_typeToPropertyManager; - QMap > m_typeToAttributeToAttributeType; - - QMap > m_propertyToType; - - QMap m_typeToValueType; - - - QMap m_internalToProperty; - - const QString m_constraintAttribute; - const QString m_singleStepAttribute; - const QString m_decimalsAttribute; - const QString m_enumIconsAttribute; - const QString m_enumNamesAttribute; - const QString m_flagNamesAttribute; - const QString m_maximumAttribute; - const QString m_minimumAttribute; - const QString m_regExpAttribute; - const QString m_echoModeAttribute; - const QString m_readOnlyAttribute; - const QString m_textVisibleAttribute; -}; - -QtVariantPropertyManagerPrivate::QtVariantPropertyManagerPrivate() : - m_constraintAttribute(QLatin1String("constraint")), - m_singleStepAttribute(QLatin1String("singleStep")), - m_decimalsAttribute(QLatin1String("decimals")), - m_enumIconsAttribute(QLatin1String("enumIcons")), - m_enumNamesAttribute(QLatin1String("enumNames")), - m_flagNamesAttribute(QLatin1String("flagNames")), - m_maximumAttribute(QLatin1String("maximum")), - m_minimumAttribute(QLatin1String("minimum")), - m_regExpAttribute(QLatin1String("regExp")), - m_echoModeAttribute(QLatin1String("echoMode")), - m_readOnlyAttribute(QLatin1String("readOnly")), - m_textVisibleAttribute(QLatin1String("textVisible")) -{ -} - -int QtVariantPropertyManagerPrivate::internalPropertyToType(QtProperty *property) const -{ - int type = 0; - QtAbstractPropertyManager *internPropertyManager = property->propertyManager(); - if (qobject_cast(internPropertyManager)) - type = QVariant::Int; - else if (qobject_cast(internPropertyManager)) - type = QtVariantPropertyManager::enumTypeId(); - else if (qobject_cast(internPropertyManager)) - type = QVariant::Bool; - else if (qobject_cast(internPropertyManager)) - type = QVariant::Double; - return type; -} - -QtVariantProperty *QtVariantPropertyManagerPrivate::createSubProperty(QtVariantProperty *parent, - QtVariantProperty *after, QtProperty *internal) -{ - int type = internalPropertyToType(internal); - if (!type) - return 0; - - bool wasCreatingSubProperties = m_creatingSubProperties; - m_creatingSubProperties = true; - - QtVariantProperty *varChild = q_ptr->addProperty(type, internal->propertyName()); - - m_creatingSubProperties = wasCreatingSubProperties; - - varChild->setPropertyName(internal->propertyName()); - varChild->setToolTip(internal->toolTip()); - varChild->setStatusTip(internal->statusTip()); - varChild->setWhatsThis(internal->whatsThis()); - - m_internalToProperty[internal] = varChild; - propertyToWrappedProperty()->insert(varChild, internal); - - parent->insertSubProperty(varChild, after); - - return varChild; -} - -void QtVariantPropertyManagerPrivate::removeSubProperty(QtVariantProperty *property) -{ - QtProperty *internChild = wrappedProperty(property); - bool wasDestroyingSubProperties = m_destroyingSubProperties; - m_destroyingSubProperties = true; - delete property; - m_destroyingSubProperties = wasDestroyingSubProperties; - m_internalToProperty.remove(internChild); - propertyToWrappedProperty()->remove(property); -} - -void QtVariantPropertyManagerPrivate::slotPropertyInserted(QtProperty *property, - QtProperty *parent, QtProperty *after) -{ - if (m_creatingProperty) - return; - - QtVariantProperty *varParent = m_internalToProperty.value(parent, 0); - if (!varParent) - return; - - QtVariantProperty *varAfter = 0; - if (after) { - varAfter = m_internalToProperty.value(after, 0); - if (!varAfter) - return; - } - - createSubProperty(varParent, varAfter, property); -} - -void QtVariantPropertyManagerPrivate::slotPropertyRemoved(QtProperty *property, QtProperty *parent) -{ - Q_UNUSED(parent) - - QtVariantProperty *varProperty = m_internalToProperty.value(property, 0); - if (!varProperty) - return; - - removeSubProperty(varProperty); -} - -void QtVariantPropertyManagerPrivate::valueChanged(QtProperty *property, const QVariant &val) -{ - QtVariantProperty *varProp = m_internalToProperty.value(property, 0); - if (!varProp) - return; - emit q_ptr->valueChanged(varProp, val); - emit q_ptr->propertyChanged(varProp); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, int val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotRangeChanged(QtProperty *property, int min, int max) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) { - emit q_ptr->attributeChanged(varProp, m_minimumAttribute, QVariant(min)); - emit q_ptr->attributeChanged(varProp, m_maximumAttribute, QVariant(max)); - } -} - -void QtVariantPropertyManagerPrivate::slotSingleStepChanged(QtProperty *property, int step) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_singleStepAttribute, QVariant(step)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, double val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotRangeChanged(QtProperty *property, double min, double max) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) { - emit q_ptr->attributeChanged(varProp, m_minimumAttribute, QVariant(min)); - emit q_ptr->attributeChanged(varProp, m_maximumAttribute, QVariant(max)); - } -} - -void QtVariantPropertyManagerPrivate::slotSingleStepChanged(QtProperty *property, double step) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_singleStepAttribute, QVariant(step)); -} - -void QtVariantPropertyManagerPrivate::slotDecimalsChanged(QtProperty *property, int prec) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_decimalsAttribute, QVariant(prec)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, bool val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QString &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotRegExpChanged(QtProperty *property, const QRegularExpression ®Exp) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_regExpAttribute, QVariant(regExp)); -} - -void QtVariantPropertyManagerPrivate::slotEchoModeChanged(QtProperty *property, int mode) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_echoModeAttribute, QVariant(mode)); -} - -void QtVariantPropertyManagerPrivate::slotReadOnlyChanged(QtProperty *property, bool readOnly) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_readOnlyAttribute, QVariant(readOnly)); -} - -void QtVariantPropertyManagerPrivate::slotTextVisibleChanged(QtProperty *property, bool textVisible) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_textVisibleAttribute, QVariant(textVisible)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QDate &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotRangeChanged(QtProperty *property, const QDate &min, const QDate &max) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) { - emit q_ptr->attributeChanged(varProp, m_minimumAttribute, QVariant(min)); - emit q_ptr->attributeChanged(varProp, m_maximumAttribute, QVariant(max)); - } -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QTime &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QDateTime &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QKeySequence &val) -{ - valueChanged(property, QVariant::fromValue(val)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QChar &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QLocale &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QPoint &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QPointF &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QSize &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotRangeChanged(QtProperty *property, const QSize &min, const QSize &max) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) { - emit q_ptr->attributeChanged(varProp, m_minimumAttribute, QVariant(min)); - emit q_ptr->attributeChanged(varProp, m_maximumAttribute, QVariant(max)); - } -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QSizeF &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotRangeChanged(QtProperty *property, const QSizeF &min, const QSizeF &max) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) { - emit q_ptr->attributeChanged(varProp, m_minimumAttribute, QVariant(min)); - emit q_ptr->attributeChanged(varProp, m_maximumAttribute, QVariant(max)); - } -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QRect &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotConstraintChanged(QtProperty *property, const QRect &constraint) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_constraintAttribute, QVariant(constraint)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QRectF &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotConstraintChanged(QtProperty *property, const QRectF &constraint) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_constraintAttribute, QVariant(constraint)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QColor &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotEnumNamesChanged(QtProperty *property, const QStringList &enumNames) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_enumNamesAttribute, QVariant(enumNames)); -} - -void QtVariantPropertyManagerPrivate::slotEnumIconsChanged(QtProperty *property, const QMap &enumIcons) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_enumIconsAttribute, QVariant::fromValue(enumIcons)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QSizePolicy &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QFont &val) -{ - valueChanged(property, QVariant(val)); -} - -void QtVariantPropertyManagerPrivate::slotValueChanged(QtProperty *property, const QCursor &val) -{ -#ifndef QT_NO_CURSOR - valueChanged(property, QVariant(val)); -#endif -} - -void QtVariantPropertyManagerPrivate::slotFlagNamesChanged(QtProperty *property, const QStringList &flagNames) -{ - if (QtVariantProperty *varProp = m_internalToProperty.value(property, 0)) - emit q_ptr->attributeChanged(varProp, m_flagNamesAttribute, QVariant(flagNames)); -} - -/*! - \class QtVariantPropertyManager - - \brief The QtVariantPropertyManager class provides and manages QVariant based properties. - - QtVariantPropertyManager provides the addProperty() function which - creates QtVariantProperty objects. The QtVariantProperty class is - a convenience class handling QVariant based properties inheriting - QtProperty. A QtProperty object created by a - QtVariantPropertyManager instance can be converted into a - QtVariantProperty object using the variantProperty() function. - - The property's value can be retrieved using the value(), and set - using the setValue() slot. In addition the property's type, and - the type of its value, can be retrieved using the propertyType() - and valueType() functions respectively. - - A property's type is a QVariant::Type enumerator value, and - usually a property's type is the same as its value type. But for - some properties the types differ, for example for enums, flags and - group types in which case QtVariantPropertyManager provides the - enumTypeId(), flagTypeId() and groupTypeId() functions, - respectively, to identify their property type (the value types are - QVariant::Int for the enum and flag types, and QVariant::Invalid - for the group type). - - Use the isPropertyTypeSupported() function to check if a particular - property type is supported. The currently supported property types - are: - - \table - \header - \o Property Type - \o Property Type Id - \row - \o int - \o QVariant::Int - \row - \o double - \o QVariant::Double - \row - \o bool - \o QVariant::Bool - \row - \o QString - \o QVariant::String - \row - \o QDate - \o QVariant::Date - \row - \o QTime - \o QVariant::Time - \row - \o QDateTime - \o QVariant::DateTime - \row - \o QKeySequence - \o QVariant::KeySequence - \row - \o QChar - \o QVariant::Char - \row - \o QLocale - \o QVariant::Locale - \row - \o QPoint - \o QVariant::Point - \row - \o QPointF - \o QVariant::PointF - \row - \o QSize - \o QVariant::Size - \row - \o QSizeF - \o QVariant::SizeF - \row - \o QRect - \o QVariant::Rect - \row - \o QRectF - \o QVariant::RectF - \row - \o QColor - \o QVariant::Color - \row - \o QSizePolicy - \o QVariant::SizePolicy - \row - \o QFont - \o QVariant::Font - \row - \o QCursor - \o QVariant::Cursor - \row - \o enum - \o enumTypeId() - \row - \o flag - \o flagTypeId() - \row - \o group - \o groupTypeId() - \endtable - - Each property type can provide additional attributes, - e.g. QVariant::Int and QVariant::Double provides minimum and - maximum values. The currently supported attributes are: - - \table - \header - \o Property Type - \o Attribute Name - \o Attribute Type - \row - \o \c int - \o minimum - \o QVariant::Int - \row - \o - \o maximum - \o QVariant::Int - \row - \o - \o singleStep - \o QVariant::Int - \row - \o \c double - \o minimum - \o QVariant::Double - \row - \o - \o maximum - \o QVariant::Double - \row - \o - \o singleStep - \o QVariant::Double - \row - \o bool - \o textVisible - \o QVariant::Bool - \row - \o - \o decimals - \o QVariant::Int - \row - \o QString - \o regExp - \o QVariant::RegExp - \row - \o - \o echoMode - \o QVariant::Int - \row - \o QDate - \o minimum - \o QVariant::Date - \row - \o - \o maximum - \o QVariant::Date - \row - \o QPointF - \o decimals - \o QVariant::Int - \row - \o QSize - \o minimum - \o QVariant::Size - \row - \o - \o maximum - \o QVariant::Size - \row - \o QSizeF - \o minimum - \o QVariant::SizeF - \row - \o - \o maximum - \o QVariant::SizeF - \row - \o - \o decimals - \o QVariant::Int - \row - \o QRect - \o constraint - \o QVariant::Rect - \row - \o QRectF - \o constraint - \o QVariant::RectF - \row - \o - \o decimals - \o QVariant::Int - \row - \o \c enum - \o enumNames - \o QVariant::StringList - \row - \o - \o enumIcons - \o iconMapTypeId() - \row - \o \c flag - \o flagNames - \o QVariant::StringList - \endtable - - The attributes for a given property type can be retrieved using - the attributes() function. Each attribute has a value type which - can be retrieved using the attributeType() function, and a value - accessible through the attributeValue() function. In addition, the - value can be set using the setAttribute() slot. - - QtVariantManager also provides the valueChanged() signal which is - emitted whenever a property created by this manager change, and - the attributeChanged() signal which is emitted whenever an - attribute of such a property changes. - - \sa QtVariantProperty, QtVariantEditorFactory -*/ - -/*! - \fn void QtVariantPropertyManager::valueChanged(QtProperty *property, const QVariant &value) - - This signal is emitted whenever a property created by this manager - changes its value, passing a pointer to the \a property and the - new \a value as parameters. - - \sa setValue() -*/ - -/*! - \fn void QtVariantPropertyManager::attributeChanged(QtProperty *property, - const QString &attribute, const QVariant &value) - - This signal is emitted whenever an attribute of a property created - by this manager changes its value, passing a pointer to the \a - property, the \a attribute and the new \a value as parameters. - - \sa setAttribute() -*/ - -/*! - Creates a manager with the given \a parent. -*/ -QtVariantPropertyManager::QtVariantPropertyManager(QObject *parent) - : QtAbstractPropertyManager(parent) -{ - d_ptr = new QtVariantPropertyManagerPrivate; - d_ptr->q_ptr = this; - - d_ptr->m_creatingProperty = false; - d_ptr->m_creatingSubProperties = false; - d_ptr->m_destroyingSubProperties = false; - d_ptr->m_propertyType = 0; - - // IntPropertyManager - QtIntPropertyManager *intPropertyManager = new QtIntPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Int] = intPropertyManager; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Int][d_ptr->m_minimumAttribute] = QVariant::Int; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Int][d_ptr->m_maximumAttribute] = QVariant::Int; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Int][d_ptr->m_singleStepAttribute] = QVariant::Int; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Int][d_ptr->m_readOnlyAttribute] = QVariant::Bool; - d_ptr->m_typeToValueType[QVariant::Int] = QVariant::Int; - connect(intPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotValueChanged(QtProperty *, int))); - connect(intPropertyManager, SIGNAL(rangeChanged(QtProperty *, int, int)), - this, SLOT(slotRangeChanged(QtProperty *, int, int))); - connect(intPropertyManager, SIGNAL(singleStepChanged(QtProperty *, int)), - this, SLOT(slotSingleStepChanged(QtProperty *, int))); - // DoublePropertyManager - QtDoublePropertyManager *doublePropertyManager = new QtDoublePropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Double] = doublePropertyManager; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Double][d_ptr->m_minimumAttribute] = - QVariant::Double; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Double][d_ptr->m_maximumAttribute] = - QVariant::Double; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Double][d_ptr->m_singleStepAttribute] = - QVariant::Double; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Double][d_ptr->m_decimalsAttribute] = - QVariant::Int; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Double][d_ptr->m_readOnlyAttribute] = - QVariant::Bool; - d_ptr->m_typeToValueType[QVariant::Double] = QVariant::Double; - connect(doublePropertyManager, SIGNAL(valueChanged(QtProperty *, double)), - this, SLOT(slotValueChanged(QtProperty *, double))); - connect(doublePropertyManager, SIGNAL(rangeChanged(QtProperty *, double, double)), - this, SLOT(slotRangeChanged(QtProperty *, double, double))); - connect(doublePropertyManager, SIGNAL(singleStepChanged(QtProperty *, double)), - this, SLOT(slotSingleStepChanged(QtProperty *, double))); - connect(doublePropertyManager, SIGNAL(decimalsChanged(QtProperty *, int)), - this, SLOT(slotDecimalsChanged(QtProperty *, int))); - // BoolPropertyManager - QtBoolPropertyManager *boolPropertyManager = new QtBoolPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Bool] = boolPropertyManager; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Bool][d_ptr->m_textVisibleAttribute] = QVariant::Bool; - d_ptr->m_typeToValueType[QVariant::Bool] = QVariant::Bool; - connect(boolPropertyManager, SIGNAL(valueChanged(QtProperty *, bool)), - this, SLOT(slotValueChanged(QtProperty *, bool))); - connect(boolPropertyManager, SIGNAL(textVisibleChanged(QtProperty*, bool)), - this, SLOT(slotTextVisibleChanged(QtProperty*, bool))); - // StringPropertyManager - QtStringPropertyManager *stringPropertyManager = new QtStringPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::String] = stringPropertyManager; - d_ptr->m_typeToValueType[QVariant::String] = QVariant::String; - d_ptr->m_typeToAttributeToAttributeType[QVariant::String][d_ptr->m_regExpAttribute] = - QVariant::RegularExpression; - d_ptr->m_typeToAttributeToAttributeType[QVariant::String][d_ptr->m_echoModeAttribute] = - QVariant::Int; - d_ptr->m_typeToAttributeToAttributeType[QVariant::String][d_ptr->m_readOnlyAttribute] = - QVariant::Bool; - - connect(stringPropertyManager, SIGNAL(valueChanged(QtProperty *, const QString &)), - this, SLOT(slotValueChanged(QtProperty *, const QString &))); - connect(stringPropertyManager, SIGNAL(regExpChanged(QtProperty *, const QRegularExpression &)), - this, SLOT(slotRegExpChanged(QtProperty *, const QRegularExpression &))); - connect(stringPropertyManager, SIGNAL(echoModeChanged(QtProperty*,int)), - this, SLOT(slotEchoModeChanged(QtProperty*, int))); - connect(stringPropertyManager, SIGNAL(readOnlyChanged(QtProperty*, bool)), - this, SLOT(slotReadOnlyChanged(QtProperty*, bool))); - - // DatePropertyManager - QtDatePropertyManager *datePropertyManager = new QtDatePropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Date] = datePropertyManager; - d_ptr->m_typeToValueType[QVariant::Date] = QVariant::Date; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Date][d_ptr->m_minimumAttribute] = - QVariant::Date; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Date][d_ptr->m_maximumAttribute] = - QVariant::Date; - connect(datePropertyManager, SIGNAL(valueChanged(QtProperty *, const QDate &)), - this, SLOT(slotValueChanged(QtProperty *, const QDate &))); - connect(datePropertyManager, SIGNAL(rangeChanged(QtProperty *, const QDate &, const QDate &)), - this, SLOT(slotRangeChanged(QtProperty *, const QDate &, const QDate &))); - // TimePropertyManager - QtTimePropertyManager *timePropertyManager = new QtTimePropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Time] = timePropertyManager; - d_ptr->m_typeToValueType[QVariant::Time] = QVariant::Time; - connect(timePropertyManager, SIGNAL(valueChanged(QtProperty *, const QTime &)), - this, SLOT(slotValueChanged(QtProperty *, const QTime &))); - // DateTimePropertyManager - QtDateTimePropertyManager *dateTimePropertyManager = new QtDateTimePropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::DateTime] = dateTimePropertyManager; - d_ptr->m_typeToValueType[QVariant::DateTime] = QVariant::DateTime; - connect(dateTimePropertyManager, SIGNAL(valueChanged(QtProperty *, const QDateTime &)), - this, SLOT(slotValueChanged(QtProperty *, const QDateTime &))); - // KeySequencePropertyManager - QtKeySequencePropertyManager *keySequencePropertyManager = new QtKeySequencePropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::KeySequence] = keySequencePropertyManager; - d_ptr->m_typeToValueType[QVariant::KeySequence] = QVariant::KeySequence; - connect(keySequencePropertyManager, SIGNAL(valueChanged(QtProperty *, const QKeySequence &)), - this, SLOT(slotValueChanged(QtProperty *, const QKeySequence &))); - // CharPropertyManager - QtCharPropertyManager *charPropertyManager = new QtCharPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Char] = charPropertyManager; - d_ptr->m_typeToValueType[QVariant::Char] = QVariant::Char; - connect(charPropertyManager, SIGNAL(valueChanged(QtProperty *, const QChar &)), - this, SLOT(slotValueChanged(QtProperty *, const QChar &))); - // PointPropertyManager - QtPointPropertyManager *pointPropertyManager = new QtPointPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Point] = pointPropertyManager; - d_ptr->m_typeToValueType[QVariant::Point] = QVariant::Point; - connect(pointPropertyManager, SIGNAL(valueChanged(QtProperty *, const QPoint &)), - this, SLOT(slotValueChanged(QtProperty *, const QPoint &))); - connect(pointPropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotValueChanged(QtProperty *, int))); - connect(pointPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), - this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); - connect(pointPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), - this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - // PointFPropertyManager - QtPointFPropertyManager *pointFPropertyManager = new QtPointFPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::PointF] = pointFPropertyManager; - d_ptr->m_typeToValueType[QVariant::PointF] = QVariant::PointF; - d_ptr->m_typeToAttributeToAttributeType[QVariant::PointF][d_ptr->m_decimalsAttribute] = - QVariant::Int; - d_ptr->m_typeToAttributeToAttributeType[QVariant::PointF][d_ptr->m_singleStepAttribute] = - QVariant::Double; - connect(pointFPropertyManager, SIGNAL(valueChanged(QtProperty *, const QPointF &)), - this, SLOT(slotValueChanged(QtProperty *, const QPointF &))); - connect(pointFPropertyManager, SIGNAL(decimalsChanged(QtProperty *, int)), - this, SLOT(slotDecimalsChanged(QtProperty *, int))); - connect(pointFPropertyManager->subDoublePropertyManager(), SIGNAL(valueChanged(QtProperty *, double)), - this, SLOT(slotValueChanged(QtProperty *, double))); - connect(pointFPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), - this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); - connect(pointFPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), - this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - // SizePropertyManager - QtSizePropertyManager *sizePropertyManager = new QtSizePropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Size] = sizePropertyManager; - d_ptr->m_typeToValueType[QVariant::Size] = QVariant::Size; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Size][d_ptr->m_minimumAttribute] = - QVariant::Size; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Size][d_ptr->m_maximumAttribute] = - QVariant::Size; - connect(sizePropertyManager, SIGNAL(valueChanged(QtProperty *, const QSize &)), - this, SLOT(slotValueChanged(QtProperty *, const QSize &))); - connect(sizePropertyManager, SIGNAL(rangeChanged(QtProperty *, const QSize &, const QSize &)), - this, SLOT(slotRangeChanged(QtProperty *, const QSize &, const QSize &))); - connect(sizePropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotValueChanged(QtProperty *, int))); - connect(sizePropertyManager->subIntPropertyManager(), SIGNAL(rangeChanged(QtProperty *, int, int)), - this, SLOT(slotRangeChanged(QtProperty *, int, int))); - connect(sizePropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), - this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); - connect(sizePropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), - this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - // SizeFPropertyManager - QtSizeFPropertyManager *sizeFPropertyManager = new QtSizeFPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::SizeF] = sizeFPropertyManager; - d_ptr->m_typeToValueType[QVariant::SizeF] = QVariant::SizeF; - d_ptr->m_typeToAttributeToAttributeType[QVariant::SizeF][d_ptr->m_minimumAttribute] = - QVariant::SizeF; - d_ptr->m_typeToAttributeToAttributeType[QVariant::SizeF][d_ptr->m_maximumAttribute] = - QVariant::SizeF; - d_ptr->m_typeToAttributeToAttributeType[QVariant::SizeF][d_ptr->m_decimalsAttribute] = - QVariant::Int; - connect(sizeFPropertyManager, SIGNAL(valueChanged(QtProperty *, const QSizeF &)), - this, SLOT(slotValueChanged(QtProperty *, const QSizeF &))); - connect(sizeFPropertyManager, SIGNAL(rangeChanged(QtProperty *, const QSizeF &, const QSizeF &)), - this, SLOT(slotRangeChanged(QtProperty *, const QSizeF &, const QSizeF &))); - connect(sizeFPropertyManager, SIGNAL(decimalsChanged(QtProperty *, int)), - this, SLOT(slotDecimalsChanged(QtProperty *, int))); - connect(sizeFPropertyManager->subDoublePropertyManager(), SIGNAL(valueChanged(QtProperty *, double)), - this, SLOT(slotValueChanged(QtProperty *, double))); - connect(sizeFPropertyManager->subDoublePropertyManager(), SIGNAL(rangeChanged(QtProperty *, double, double)), - this, SLOT(slotRangeChanged(QtProperty *, double, double))); - connect(sizeFPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), - this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); - connect(sizeFPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), - this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - // RectPropertyManager - QtRectPropertyManager *rectPropertyManager = new QtRectPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Rect] = rectPropertyManager; - d_ptr->m_typeToValueType[QVariant::Rect] = QVariant::Rect; - d_ptr->m_typeToAttributeToAttributeType[QVariant::Rect][d_ptr->m_constraintAttribute] = - QVariant::Rect; - connect(rectPropertyManager, SIGNAL(valueChanged(QtProperty *, const QRect &)), - this, SLOT(slotValueChanged(QtProperty *, const QRect &))); - connect(rectPropertyManager, SIGNAL(constraintChanged(QtProperty *, const QRect &)), - this, SLOT(slotConstraintChanged(QtProperty *, const QRect &))); - connect(rectPropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotValueChanged(QtProperty *, int))); - connect(rectPropertyManager->subIntPropertyManager(), SIGNAL(rangeChanged(QtProperty *, int, int)), - this, SLOT(slotRangeChanged(QtProperty *, int, int))); - connect(rectPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), - this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); - connect(rectPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), - this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - // RectFPropertyManager - QtRectFPropertyManager *rectFPropertyManager = new QtRectFPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::RectF] = rectFPropertyManager; - d_ptr->m_typeToValueType[QVariant::RectF] = QVariant::RectF; - d_ptr->m_typeToAttributeToAttributeType[QVariant::RectF][d_ptr->m_constraintAttribute] = - QVariant::RectF; - d_ptr->m_typeToAttributeToAttributeType[QVariant::RectF][d_ptr->m_decimalsAttribute] = - QVariant::Int; - connect(rectFPropertyManager, SIGNAL(valueChanged(QtProperty *, const QRectF &)), - this, SLOT(slotValueChanged(QtProperty *, const QRectF &))); - connect(rectFPropertyManager, SIGNAL(constraintChanged(QtProperty *, const QRectF &)), - this, SLOT(slotConstraintChanged(QtProperty *, const QRectF &))); - connect(rectFPropertyManager, SIGNAL(decimalsChanged(QtProperty *, int)), - this, SLOT(slotDecimalsChanged(QtProperty *, int))); - connect(rectFPropertyManager->subDoublePropertyManager(), SIGNAL(valueChanged(QtProperty *, double)), - this, SLOT(slotValueChanged(QtProperty *, double))); - connect(rectFPropertyManager->subDoublePropertyManager(), SIGNAL(rangeChanged(QtProperty *, double, double)), - this, SLOT(slotRangeChanged(QtProperty *, double, double))); - connect(rectFPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), - this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); - connect(rectFPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), - this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - // ColorPropertyManager - QtColorPropertyManager *colorPropertyManager = new QtColorPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Color] = colorPropertyManager; - d_ptr->m_typeToValueType[QVariant::Color] = QVariant::Color; - connect(colorPropertyManager, SIGNAL(valueChanged(QtProperty *, const QColor &)), - this, SLOT(slotValueChanged(QtProperty *, const QColor &))); - connect(colorPropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotValueChanged(QtProperty *, int))); - connect(colorPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), - this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); - connect(colorPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), - this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - // EnumPropertyManager - int enumId = enumTypeId(); - QtEnumPropertyManager *enumPropertyManager = new QtEnumPropertyManager(this); - d_ptr->m_typeToPropertyManager[enumId] = enumPropertyManager; - d_ptr->m_typeToValueType[enumId] = QVariant::Int; - d_ptr->m_typeToAttributeToAttributeType[enumId][d_ptr->m_enumNamesAttribute] = - QVariant::StringList; - d_ptr->m_typeToAttributeToAttributeType[enumId][d_ptr->m_enumIconsAttribute] = - iconMapTypeId(); - connect(enumPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotValueChanged(QtProperty *, int))); - connect(enumPropertyManager, SIGNAL(enumNamesChanged(QtProperty *, const QStringList &)), - this, SLOT(slotEnumNamesChanged(QtProperty *, const QStringList &))); - connect(enumPropertyManager, SIGNAL(enumIconsChanged(QtProperty *, const QMap &)), - this, SLOT(slotEnumIconsChanged(QtProperty *, const QMap &))); - // FontPropertyManager - QtFontPropertyManager *fontPropertyManager = new QtFontPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Font] = fontPropertyManager; - d_ptr->m_typeToValueType[QVariant::Font] = QVariant::Font; - connect(fontPropertyManager, SIGNAL(valueChanged(QtProperty *, const QFont &)), - this, SLOT(slotValueChanged(QtProperty *, const QFont &))); - connect(fontPropertyManager->subIntPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotValueChanged(QtProperty *, int))); - connect(fontPropertyManager->subIntPropertyManager(), SIGNAL(rangeChanged(QtProperty *, int, int)), - this, SLOT(slotRangeChanged(QtProperty *, int, int))); - connect(fontPropertyManager->subEnumPropertyManager(), SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotValueChanged(QtProperty *, int))); - connect(fontPropertyManager->subEnumPropertyManager(), - SIGNAL(enumNamesChanged(QtProperty *, const QStringList &)), - this, SLOT(slotEnumNamesChanged(QtProperty *, const QStringList &))); - connect(fontPropertyManager->subBoolPropertyManager(), SIGNAL(valueChanged(QtProperty *, bool)), - this, SLOT(slotValueChanged(QtProperty *, bool))); - connect(fontPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), - this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); - connect(fontPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), - this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - // CursorPropertyManager - QtCursorPropertyManager *cursorPropertyManager = new QtCursorPropertyManager(this); - d_ptr->m_typeToPropertyManager[QVariant::Cursor] = cursorPropertyManager; - d_ptr->m_typeToValueType[QVariant::Cursor] = QVariant::Cursor; - connect(cursorPropertyManager, SIGNAL(valueChanged(QtProperty *, const QCursor &)), - this, SLOT(slotValueChanged(QtProperty *, const QCursor &))); - // FlagPropertyManager - int flagId = flagTypeId(); - QtFlagPropertyManager *flagPropertyManager = new QtFlagPropertyManager(this); - d_ptr->m_typeToPropertyManager[flagId] = flagPropertyManager; - d_ptr->m_typeToValueType[flagId] = QVariant::Int; - d_ptr->m_typeToAttributeToAttributeType[flagId][d_ptr->m_flagNamesAttribute] = - QVariant::StringList; - connect(flagPropertyManager, SIGNAL(valueChanged(QtProperty *, int)), - this, SLOT(slotValueChanged(QtProperty *, int))); - connect(flagPropertyManager, SIGNAL(flagNamesChanged(QtProperty *, const QStringList &)), - this, SLOT(slotFlagNamesChanged(QtProperty *, const QStringList &))); - connect(flagPropertyManager->subBoolPropertyManager(), SIGNAL(valueChanged(QtProperty *, bool)), - this, SLOT(slotValueChanged(QtProperty *, bool))); - connect(flagPropertyManager, SIGNAL(propertyInserted(QtProperty *, QtProperty *, QtProperty *)), - this, SLOT(slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *))); - connect(flagPropertyManager, SIGNAL(propertyRemoved(QtProperty *, QtProperty *)), - this, SLOT(slotPropertyRemoved(QtProperty *, QtProperty *))); - // FlagPropertyManager - int groupId = groupTypeId(); - QtGroupPropertyManager *groupPropertyManager = new QtGroupPropertyManager(this); - d_ptr->m_typeToPropertyManager[groupId] = groupPropertyManager; - d_ptr->m_typeToValueType[groupId] = QVariant::Invalid; -} - -/*! - Destroys this manager, and all the properties it has created. -*/ -QtVariantPropertyManager::~QtVariantPropertyManager() -{ - clear(); - delete d_ptr; -} - -/*! - Returns the given \a property converted into a QtVariantProperty. - - If the \a property was not created by this variant manager, the - function returns 0. - - \sa createProperty() -*/ -QtVariantProperty *QtVariantPropertyManager::variantProperty(const QtProperty *property) const -{ - const QMap >::const_iterator it = d_ptr->m_propertyToType.constFind(property); - if (it == d_ptr->m_propertyToType.constEnd()) - return 0; - return it.value().first; -} - -/*! - Returns true if the given \a propertyType is supported by this - variant manager; otherwise false. - - \sa propertyType() -*/ -bool QtVariantPropertyManager::isPropertyTypeSupported(int propertyType) const -{ - if (d_ptr->m_typeToValueType.contains(propertyType)) - return true; - return false; -} - -/*! - Creates and returns a variant property of the given \a propertyType - with the given \a name. - - If the specified \a propertyType is not supported by this variant - manager, this function returns 0. - - Do not use the inherited - QtAbstractPropertyManager::addProperty() function to create a - variant property (that function will always return 0 since it will - not be clear what type the property should have). - - \sa isPropertyTypeSupported() -*/ -QtVariantProperty *QtVariantPropertyManager::addProperty(int propertyType, const QString &name) -{ - if (!isPropertyTypeSupported(propertyType)) - return 0; - - bool wasCreating = d_ptr->m_creatingProperty; - d_ptr->m_creatingProperty = true; - d_ptr->m_propertyType = propertyType; - QtProperty *property = QtAbstractPropertyManager::addProperty(name); - d_ptr->m_creatingProperty = wasCreating; - d_ptr->m_propertyType = 0; - - if (!property) - return 0; - - return variantProperty(property); -} - -/*! - Returns the given \a property's value. - - If the given \a property is not managed by this manager, this - function returns an invalid variant. - - \sa setValue() -*/ -QVariant QtVariantPropertyManager::value(const QtProperty *property) const -{ - QtProperty *internProp = propertyToWrappedProperty()->value(property, 0); - if (internProp == 0) - return QVariant(); - - QtAbstractPropertyManager *manager = internProp->propertyManager(); - if (QtIntPropertyManager *intManager = qobject_cast(manager)) { - return intManager->value(internProp); - } else if (QtDoublePropertyManager *doubleManager = qobject_cast(manager)) { - return doubleManager->value(internProp); - } else if (QtBoolPropertyManager *boolManager = qobject_cast(manager)) { - return boolManager->value(internProp); - } else if (QtStringPropertyManager *stringManager = qobject_cast(manager)) { - return stringManager->value(internProp); - } else if (QtDatePropertyManager *dateManager = qobject_cast(manager)) { - return dateManager->value(internProp); - } else if (QtTimePropertyManager *timeManager = qobject_cast(manager)) { - return timeManager->value(internProp); - } else if (QtDateTimePropertyManager *dateTimeManager = qobject_cast(manager)) { - return dateTimeManager->value(internProp); - } else if (QtKeySequencePropertyManager *keySequenceManager = qobject_cast(manager)) { -#if QT_VERSION < 0x050000 - return keySequenceManager->value(internProp); -#else - return QVariant::fromValue(keySequenceManager->value(internProp)); -#endif - } else if (QtCharPropertyManager *charManager = qobject_cast(manager)) { - return charManager->value(internProp); - } else if (QtPointPropertyManager *pointManager = qobject_cast(manager)) { - return pointManager->value(internProp); - } else if (QtPointFPropertyManager *pointFManager = qobject_cast(manager)) { - return pointFManager->value(internProp); - } else if (QtSizePropertyManager *sizeManager = qobject_cast(manager)) { - return sizeManager->value(internProp); - } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast(manager)) { - return sizeFManager->value(internProp); - } else if (QtRectPropertyManager *rectManager = qobject_cast(manager)) { - return rectManager->value(internProp); - } else if (QtRectFPropertyManager *rectFManager = qobject_cast(manager)) { - return rectFManager->value(internProp); - } else if (QtColorPropertyManager *colorManager = qobject_cast(manager)) { - return colorManager->value(internProp); - } else if (QtEnumPropertyManager *enumManager = qobject_cast(manager)) { - return enumManager->value(internProp); - } else if (QtFontPropertyManager *fontManager = qobject_cast(manager)) { - return fontManager->value(internProp); -#ifndef QT_NO_CURSOR - } else if (QtCursorPropertyManager *cursorManager = qobject_cast(manager)) { - return cursorManager->value(internProp); -#endif - } else if (QtFlagPropertyManager *flagManager = qobject_cast(manager)) { - return flagManager->value(internProp); - } - return QVariant(); -} - -/*! - Returns the given \a property's value type. - - \sa propertyType() -*/ -int QtVariantPropertyManager::valueType(const QtProperty *property) const -{ - int propType = propertyType(property); - return valueType(propType); -} - -/*! - \overload - - Returns the value type associated with the given \a propertyType. -*/ -int QtVariantPropertyManager::valueType(int propertyType) const -{ - if (d_ptr->m_typeToValueType.contains(propertyType)) - return d_ptr->m_typeToValueType[propertyType]; - return 0; -} - -/*! - Returns the given \a property's type. - - \sa valueType() -*/ -int QtVariantPropertyManager::propertyType(const QtProperty *property) const -{ - const QMap >::const_iterator it = d_ptr->m_propertyToType.constFind(property); - if (it == d_ptr->m_propertyToType.constEnd()) - return 0; - return it.value().second; -} - -/*! - Returns the given \a property's value for the specified \a - attribute - - If the given \a property was not created by \e this manager, or if - the specified \a attribute does not exist, this function returns - an invalid variant. - - \sa attributes(), attributeType(), setAttribute() -*/ -QVariant QtVariantPropertyManager::attributeValue(const QtProperty *property, const QString &attribute) const -{ - int propType = propertyType(property); - if (!propType) - return QVariant(); - - QMap >::ConstIterator it = - d_ptr->m_typeToAttributeToAttributeType.find(propType); - if (it == d_ptr->m_typeToAttributeToAttributeType.constEnd()) - return QVariant(); - - QMap attributes = it.value(); - QMap::ConstIterator itAttr = attributes.find(attribute); - if (itAttr == attributes.constEnd()) - return QVariant(); - - QtProperty *internProp = propertyToWrappedProperty()->value(property, 0); - if (internProp == 0) - return QVariant(); - - QtAbstractPropertyManager *manager = internProp->propertyManager(); - if (QtIntPropertyManager *intManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_maximumAttribute) - return intManager->maximum(internProp); - if (attribute == d_ptr->m_minimumAttribute) - return intManager->minimum(internProp); - if (attribute == d_ptr->m_singleStepAttribute) - return intManager->singleStep(internProp); - if (attribute == d_ptr->m_readOnlyAttribute) - return intManager->isReadOnly(internProp); - return QVariant(); - } else if (QtDoublePropertyManager *doubleManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_maximumAttribute) - return doubleManager->maximum(internProp); - if (attribute == d_ptr->m_minimumAttribute) - return doubleManager->minimum(internProp); - if (attribute == d_ptr->m_singleStepAttribute) - return doubleManager->singleStep(internProp); - if (attribute == d_ptr->m_decimalsAttribute) - return doubleManager->decimals(internProp); - if (attribute == d_ptr->m_readOnlyAttribute) - return doubleManager->isReadOnly(internProp); - return QVariant(); - } else if (QtBoolPropertyManager *boolManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_textVisibleAttribute) - return boolManager->textVisible(internProp); - return QVariant(); - } else if (QtStringPropertyManager *stringManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_regExpAttribute) - return stringManager->regExp(internProp); - if (attribute == d_ptr->m_echoModeAttribute) - return stringManager->echoMode(internProp); - if (attribute == d_ptr->m_readOnlyAttribute) - return stringManager->isReadOnly(internProp); - return QVariant(); - } else if (QtDatePropertyManager *dateManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_maximumAttribute) - return dateManager->maximum(internProp); - if (attribute == d_ptr->m_minimumAttribute) - return dateManager->minimum(internProp); - return QVariant(); - } else if (QtPointFPropertyManager *pointFManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_singleStepAttribute) - return pointFManager->singleStep(internProp); - if (attribute == d_ptr->m_decimalsAttribute) - return pointFManager->decimals(internProp); - return QVariant(); - } else if (QtSizePropertyManager *sizeManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_maximumAttribute) - return sizeManager->maximum(internProp); - if (attribute == d_ptr->m_minimumAttribute) - return sizeManager->minimum(internProp); - return QVariant(); - } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_maximumAttribute) - return sizeFManager->maximum(internProp); - if (attribute == d_ptr->m_minimumAttribute) - return sizeFManager->minimum(internProp); - if (attribute == d_ptr->m_decimalsAttribute) - return sizeFManager->decimals(internProp); - return QVariant(); - } else if (QtRectPropertyManager *rectManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_constraintAttribute) - return rectManager->constraint(internProp); - return QVariant(); - } else if (QtRectFPropertyManager *rectFManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_constraintAttribute) - return rectFManager->constraint(internProp); - if (attribute == d_ptr->m_decimalsAttribute) - return rectFManager->decimals(internProp); - return QVariant(); - } else if (QtEnumPropertyManager *enumManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_enumNamesAttribute) - return enumManager->enumNames(internProp); - if (attribute == d_ptr->m_enumIconsAttribute) - return QVariant::fromValue(enumManager->enumIcons(internProp)); - return QVariant(); - } else if (QtFlagPropertyManager *flagManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_flagNamesAttribute) - return flagManager->flagNames(internProp); - return QVariant(); - } - return QVariant(); -} - -/*! - Returns a list of the given \a propertyType 's attributes. - - \sa attributeValue(), attributeType() -*/ -QStringList QtVariantPropertyManager::attributes(int propertyType) const -{ - QMap >::ConstIterator it = - d_ptr->m_typeToAttributeToAttributeType.find(propertyType); - if (it == d_ptr->m_typeToAttributeToAttributeType.constEnd()) - return QStringList(); - return it.value().keys(); -} - -/*! - Returns the type of the specified \a attribute of the given \a - propertyType. - - If the given \a propertyType is not supported by \e this manager, - or if the given \a propertyType does not possess the specified \a - attribute, this function returns QVariant::Invalid. - - \sa attributes(), valueType() -*/ -int QtVariantPropertyManager::attributeType(int propertyType, const QString &attribute) const -{ - QMap >::ConstIterator it = - d_ptr->m_typeToAttributeToAttributeType.find(propertyType); - if (it == d_ptr->m_typeToAttributeToAttributeType.constEnd()) - return 0; - - QMap attributes = it.value(); - QMap::ConstIterator itAttr = attributes.find(attribute); - if (itAttr == attributes.constEnd()) - return 0; - return itAttr.value(); -} - -/*! - \fn void QtVariantPropertyManager::setValue(QtProperty *property, const QVariant &value) - - Sets the value of the given \a property to \a value. - - The specified \a value must be of a type returned by valueType(), - or of type that can be converted to valueType() using the - QVariant::canConvert() function, otherwise this function does - nothing. - - \sa value(), QtVariantProperty::setValue(), valueChanged() -*/ -void QtVariantPropertyManager::setValue(QtProperty *property, const QVariant &val) -{ - int propType = val.userType(); - if (!propType) - return; - - int valType = valueType(property); - - if (propType != valType && !val.canConvert(static_cast(valType))) - return; - - QtProperty *internProp = propertyToWrappedProperty()->value(property, 0); - if (internProp == 0) - return; - - - QtAbstractPropertyManager *manager = internProp->propertyManager(); - if (QtIntPropertyManager *intManager = qobject_cast(manager)) { - intManager->setValue(internProp, val.value()); - return; - } else if (QtDoublePropertyManager *doubleManager = qobject_cast(manager)) { - doubleManager->setValue(internProp, val.value()); - return; - } else if (QtBoolPropertyManager *boolManager = qobject_cast(manager)) { - boolManager->setValue(internProp, val.value()); - return; - } else if (QtStringPropertyManager *stringManager = qobject_cast(manager)) { - stringManager->setValue(internProp, val.value()); - return; - } else if (QtDatePropertyManager *dateManager = qobject_cast(manager)) { - dateManager->setValue(internProp, val.value()); - return; - } else if (QtTimePropertyManager *timeManager = qobject_cast(manager)) { - timeManager->setValue(internProp, val.value()); - return; - } else if (QtDateTimePropertyManager *dateTimeManager = qobject_cast(manager)) { - dateTimeManager->setValue(internProp, val.value()); - return; - } else if (QtKeySequencePropertyManager *keySequenceManager = qobject_cast(manager)) { - keySequenceManager->setValue(internProp, val.value()); - return; - } else if (QtCharPropertyManager *charManager = qobject_cast(manager)) { - charManager->setValue(internProp, val.value()); - return; - } else if (QtPointPropertyManager *pointManager = qobject_cast(manager)) { - pointManager->setValue(internProp, val.value()); - return; - } else if (QtPointFPropertyManager *pointFManager = qobject_cast(manager)) { - pointFManager->setValue(internProp, val.value()); - return; - } else if (QtSizePropertyManager *sizeManager = qobject_cast(manager)) { - sizeManager->setValue(internProp, val.value()); - return; - } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast(manager)) { - sizeFManager->setValue(internProp, val.value()); - return; - } else if (QtRectPropertyManager *rectManager = qobject_cast(manager)) { - rectManager->setValue(internProp, val.value()); - return; - } else if (QtRectFPropertyManager *rectFManager = qobject_cast(manager)) { - rectFManager->setValue(internProp, val.value()); - return; - } else if (QtColorPropertyManager *colorManager = qobject_cast(manager)) { - colorManager->setValue(internProp, val.value()); - return; - } else if (QtEnumPropertyManager *enumManager = qobject_cast(manager)) { - enumManager->setValue(internProp, val.value()); - return; - } else if (QtFontPropertyManager *fontManager = qobject_cast(manager)) { - fontManager->setValue(internProp, val.value()); - return; -#ifndef QT_NO_CURSOR - } else if (QtCursorPropertyManager *cursorManager = qobject_cast(manager)) { - cursorManager->setValue(internProp, val.value()); - return; -#endif - } else if (QtFlagPropertyManager *flagManager = qobject_cast(manager)) { - flagManager->setValue(internProp, val.value()); - return; - } -} - -/*! - Sets the value of the specified \a attribute of the given \a - property, to \a value. - - The new \a value's type must be of the type returned by - attributeType(), or of a type that can be converted to - attributeType() using the QVariant::canConvert() function, - otherwise this function does nothing. - - \sa attributeValue(), QtVariantProperty::setAttribute(), attributeChanged() -*/ -void QtVariantPropertyManager::setAttribute(QtProperty *property, - const QString &attribute, const QVariant &value) -{ - QVariant oldAttr = attributeValue(property, attribute); - if (!oldAttr.isValid()) - return; - - int attrType = value.userType(); - if (!attrType) - return; - - if (attrType != attributeType(propertyType(property), attribute) && - !value.canConvert((QVariant::Type)attrType)) - return; - - QtProperty *internProp = propertyToWrappedProperty()->value(property, 0); - if (internProp == 0) - return; - - QtAbstractPropertyManager *manager = internProp->propertyManager(); - if (QtIntPropertyManager *intManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_maximumAttribute) - intManager->setMaximum(internProp, value.value()); - else if (attribute == d_ptr->m_minimumAttribute) - intManager->setMinimum(internProp, value.value()); - else if (attribute == d_ptr->m_singleStepAttribute) - intManager->setSingleStep(internProp, value.value()); - else if (attribute == d_ptr->m_readOnlyAttribute) - intManager->setReadOnly(internProp, value.value()); - return; - } else if (QtDoublePropertyManager *doubleManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_maximumAttribute) - doubleManager->setMaximum(internProp, value.value()); - if (attribute == d_ptr->m_minimumAttribute) - doubleManager->setMinimum(internProp, value.value()); - if (attribute == d_ptr->m_singleStepAttribute) - doubleManager->setSingleStep(internProp, value.value()); - if (attribute == d_ptr->m_decimalsAttribute) - doubleManager->setDecimals(internProp, value.value()); - if (attribute == d_ptr->m_readOnlyAttribute) - doubleManager->setReadOnly(internProp, value.value()); - return; - } else if (QtBoolPropertyManager *boolManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_textVisibleAttribute) - boolManager->setTextVisible(internProp, value.value()); - return; - } else if (QtStringPropertyManager *stringManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_regExpAttribute) - stringManager->setRegExp(internProp, value.value()); - if (attribute == d_ptr->m_echoModeAttribute) - stringManager->setEchoMode(internProp, (EchoMode)value.value()); - if (attribute == d_ptr->m_readOnlyAttribute) - stringManager->setReadOnly(internProp, (EchoMode)value.value()); - return; - } else if (QtDatePropertyManager *dateManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_maximumAttribute) - dateManager->setMaximum(internProp, value.value()); - if (attribute == d_ptr->m_minimumAttribute) - dateManager->setMinimum(internProp, value.value()); - return; - } else if (QtPointFPropertyManager *pointFManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_singleStepAttribute) - pointFManager->setSingleStep(internProp, value.value()); - if (attribute == d_ptr->m_decimalsAttribute) - pointFManager->setDecimals(internProp, value.value()); - return; - } else if (QtSizePropertyManager *sizeManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_maximumAttribute) - sizeManager->setMaximum(internProp, value.value()); - if (attribute == d_ptr->m_minimumAttribute) - sizeManager->setMinimum(internProp, value.value()); - return; - } else if (QtSizeFPropertyManager *sizeFManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_maximumAttribute) - sizeFManager->setMaximum(internProp, value.value()); - if (attribute == d_ptr->m_minimumAttribute) - sizeFManager->setMinimum(internProp, value.value()); - if (attribute == d_ptr->m_decimalsAttribute) - sizeFManager->setDecimals(internProp, value.value()); - return; - } else if (QtRectPropertyManager *rectManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_constraintAttribute) - rectManager->setConstraint(internProp, value.value()); - return; - } else if (QtRectFPropertyManager *rectFManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_constraintAttribute) - rectFManager->setConstraint(internProp, value.value()); - if (attribute == d_ptr->m_decimalsAttribute) - rectFManager->setDecimals(internProp, value.value()); - return; - } else if (QtEnumPropertyManager *enumManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_enumNamesAttribute) - enumManager->setEnumNames(internProp, value.value()); - if (attribute == d_ptr->m_enumIconsAttribute) - enumManager->setEnumIcons(internProp, value.value()); - return; - } else if (QtFlagPropertyManager *flagManager = qobject_cast(manager)) { - if (attribute == d_ptr->m_flagNamesAttribute) - flagManager->setFlagNames(internProp, value.value()); - return; - } -} - -/*! - \reimp -*/ -bool QtVariantPropertyManager::hasValue(const QtProperty *property) const -{ - if (propertyType(property) == groupTypeId()) - return false; - return true; -} - -/*! - \reimp -*/ -QString QtVariantPropertyManager::valueText(const QtProperty *property) const -{ - const QtProperty *internProp = propertyToWrappedProperty()->value(property, 0); - return internProp ? !internProp->displayText().isEmpty() ? internProp->displayText() : internProp->valueText() : QString(); -} - -/*! - \reimp -*/ -QIcon QtVariantPropertyManager::valueIcon(const QtProperty *property) const -{ - const QtProperty *internProp = propertyToWrappedProperty()->value(property, 0); - return internProp ? internProp->valueIcon() : QIcon(); -} - -/*! - \reimp -*/ -void QtVariantPropertyManager::initializeProperty(QtProperty *property) -{ - QtVariantProperty *varProp = variantProperty(property); - if (!varProp) - return; - - QMap::ConstIterator it = - d_ptr->m_typeToPropertyManager.find(d_ptr->m_propertyType); - if (it != d_ptr->m_typeToPropertyManager.constEnd()) { - QtProperty *internProp = 0; - if (!d_ptr->m_creatingSubProperties) { - QtAbstractPropertyManager *manager = it.value(); - internProp = manager->addProperty(); - d_ptr->m_internalToProperty[internProp] = varProp; - } - propertyToWrappedProperty()->insert(varProp, internProp); - if (internProp) { - QList children = internProp->subProperties(); - QListIterator itChild(children); - QtVariantProperty *lastProperty = 0; - while (itChild.hasNext()) { - QtVariantProperty *prop = d_ptr->createSubProperty(varProp, lastProperty, itChild.next()); - lastProperty = prop ? prop : lastProperty; - } - } - } -} - -/*! - \reimp -*/ -void QtVariantPropertyManager::uninitializeProperty(QtProperty *property) -{ - const QMap >::iterator type_it = d_ptr->m_propertyToType.find(property); - if (type_it == d_ptr->m_propertyToType.end()) - return; - - PropertyMap::iterator it = propertyToWrappedProperty()->find(property); - if (it != propertyToWrappedProperty()->end()) { - QtProperty *internProp = it.value(); - if (internProp) { - d_ptr->m_internalToProperty.remove(internProp); - if (!d_ptr->m_destroyingSubProperties) { - delete internProp; - } - } - propertyToWrappedProperty()->erase(it); - } - d_ptr->m_propertyToType.erase(type_it); -} - -/*! - \reimp -*/ -QtProperty *QtVariantPropertyManager::createProperty() -{ - if (!d_ptr->m_creatingProperty) - return 0; - - QtVariantProperty *property = new QtVariantProperty(this); - d_ptr->m_propertyToType.insert(property, qMakePair(property, d_ptr->m_propertyType)); - - return property; -} - -///////////////////////////// - -class QtVariantEditorFactoryPrivate -{ - QtVariantEditorFactory *q_ptr; - Q_DECLARE_PUBLIC(QtVariantEditorFactory) -public: - - QtSpinBoxFactory *m_spinBoxFactory; - QtDoubleSpinBoxFactory *m_doubleSpinBoxFactory; - QtCheckBoxFactory *m_checkBoxFactory; - QtLineEditFactory *m_lineEditFactory; - QtDateEditFactory *m_dateEditFactory; - QtTimeEditFactory *m_timeEditFactory; - QtDateTimeEditFactory *m_dateTimeEditFactory; - QtKeySequenceEditorFactory *m_keySequenceEditorFactory; - QtCharEditorFactory *m_charEditorFactory; - QtEnumEditorFactory *m_comboBoxFactory; - QtCursorEditorFactory *m_cursorEditorFactory; - QtColorEditorFactory *m_colorEditorFactory; - QtFontEditorFactory *m_fontEditorFactory; - - QMap m_factoryToType; - QMap m_typeToFactory; -}; - -/*! - \class QtVariantEditorFactory - - \brief The QtVariantEditorFactory class provides widgets for properties - created by QtVariantPropertyManager objects. - - The variant factory provides the following widgets for the - specified property types: - - \table - \header - \o Property Type - \o Widget - \row - \o \c int - \o QSpinBox - \row - \o \c double - \o QDoubleSpinBox - \row - \o \c bool - \o QCheckBox - \row - \o QString - \o QLineEdit - \row - \o QDate - \o QDateEdit - \row - \o QTime - \o QTimeEdit - \row - \o QDateTime - \o QDateTimeEdit - \row - \o QKeySequence - \o customized editor - \row - \o QChar - \o customized editor - \row - \o \c enum - \o QComboBox - \row - \o QCursor - \o QComboBox - \endtable - - Note that QtVariantPropertyManager supports several additional property - types for which the QtVariantEditorFactory class does not provide - editing widgets, e.g. QPoint and QSize. To provide widgets for other - types using the variant approach, derive from the QtVariantEditorFactory - class. - - \sa QtAbstractEditorFactory, QtVariantPropertyManager -*/ - -/*! - Creates a factory with the given \a parent. -*/ -QtVariantEditorFactory::QtVariantEditorFactory(QObject *parent) - : QtAbstractEditorFactory(parent) -{ - d_ptr = new QtVariantEditorFactoryPrivate(); - d_ptr->q_ptr = this; - - d_ptr->m_spinBoxFactory = new QtSpinBoxFactory(this); - d_ptr->m_factoryToType[d_ptr->m_spinBoxFactory] = QVariant::Int; - d_ptr->m_typeToFactory[QVariant::Int] = d_ptr->m_spinBoxFactory; - - d_ptr->m_doubleSpinBoxFactory = new QtDoubleSpinBoxFactory(this); - d_ptr->m_factoryToType[d_ptr->m_doubleSpinBoxFactory] = QVariant::Double; - d_ptr->m_typeToFactory[QVariant::Double] = d_ptr->m_doubleSpinBoxFactory; - - d_ptr->m_checkBoxFactory = new QtCheckBoxFactory(this); - d_ptr->m_factoryToType[d_ptr->m_checkBoxFactory] = QVariant::Bool; - d_ptr->m_typeToFactory[QVariant::Bool] = d_ptr->m_checkBoxFactory; - - d_ptr->m_lineEditFactory = new QtLineEditFactory(this); - d_ptr->m_factoryToType[d_ptr->m_lineEditFactory] = QVariant::String; - d_ptr->m_typeToFactory[QVariant::String] = d_ptr->m_lineEditFactory; - - d_ptr->m_dateEditFactory = new QtDateEditFactory(this); - d_ptr->m_factoryToType[d_ptr->m_dateEditFactory] = QVariant::Date; - d_ptr->m_typeToFactory[QVariant::Date] = d_ptr->m_dateEditFactory; - - d_ptr->m_timeEditFactory = new QtTimeEditFactory(this); - d_ptr->m_factoryToType[d_ptr->m_timeEditFactory] = QVariant::Time; - d_ptr->m_typeToFactory[QVariant::Time] = d_ptr->m_timeEditFactory; - - d_ptr->m_dateTimeEditFactory = new QtDateTimeEditFactory(this); - d_ptr->m_factoryToType[d_ptr->m_dateTimeEditFactory] = QVariant::DateTime; - d_ptr->m_typeToFactory[QVariant::DateTime] = d_ptr->m_dateTimeEditFactory; - - d_ptr->m_keySequenceEditorFactory = new QtKeySequenceEditorFactory(this); - d_ptr->m_factoryToType[d_ptr->m_keySequenceEditorFactory] = QVariant::KeySequence; - d_ptr->m_typeToFactory[QVariant::KeySequence] = d_ptr->m_keySequenceEditorFactory; - - d_ptr->m_charEditorFactory = new QtCharEditorFactory(this); - d_ptr->m_factoryToType[d_ptr->m_charEditorFactory] = QVariant::Char; - d_ptr->m_typeToFactory[QVariant::Char] = d_ptr->m_charEditorFactory; - - d_ptr->m_cursorEditorFactory = new QtCursorEditorFactory(this); - d_ptr->m_factoryToType[d_ptr->m_cursorEditorFactory] = QVariant::Cursor; - d_ptr->m_typeToFactory[QVariant::Cursor] = d_ptr->m_cursorEditorFactory; - - d_ptr->m_colorEditorFactory = new QtColorEditorFactory(this); - d_ptr->m_factoryToType[d_ptr->m_colorEditorFactory] = QVariant::Color; - d_ptr->m_typeToFactory[QVariant::Color] = d_ptr->m_colorEditorFactory; - - d_ptr->m_fontEditorFactory = new QtFontEditorFactory(this); - d_ptr->m_factoryToType[d_ptr->m_fontEditorFactory] = QVariant::Font; - d_ptr->m_typeToFactory[QVariant::Font] = d_ptr->m_fontEditorFactory; - - d_ptr->m_comboBoxFactory = new QtEnumEditorFactory(this); - const int enumId = QtVariantPropertyManager::enumTypeId(); - d_ptr->m_factoryToType[d_ptr->m_comboBoxFactory] = enumId; - d_ptr->m_typeToFactory[enumId] = d_ptr->m_comboBoxFactory; -} - -/*! - Destroys this factory, and all the widgets it has created. -*/ -QtVariantEditorFactory::~QtVariantEditorFactory() -{ - delete d_ptr; -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtVariantEditorFactory::connectPropertyManager(QtVariantPropertyManager *manager) -{ - QList intPropertyManagers = manager->findChildren(); - QListIterator itInt(intPropertyManagers); - while (itInt.hasNext()) - d_ptr->m_spinBoxFactory->addPropertyManager(itInt.next()); - - QList doublePropertyManagers = manager->findChildren(); - QListIterator itDouble(doublePropertyManagers); - while (itDouble.hasNext()) - d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itDouble.next()); - - QList boolPropertyManagers = manager->findChildren(); - QListIterator itBool(boolPropertyManagers); - while (itBool.hasNext()) - d_ptr->m_checkBoxFactory->addPropertyManager(itBool.next()); - - QList stringPropertyManagers = manager->findChildren(); - QListIterator itString(stringPropertyManagers); - while (itString.hasNext()) - d_ptr->m_lineEditFactory->addPropertyManager(itString.next()); - - QList datePropertyManagers = manager->findChildren(); - QListIterator itDate(datePropertyManagers); - while (itDate.hasNext()) - d_ptr->m_dateEditFactory->addPropertyManager(itDate.next()); - - QList timePropertyManagers = manager->findChildren(); - QListIterator itTime(timePropertyManagers); - while (itTime.hasNext()) - d_ptr->m_timeEditFactory->addPropertyManager(itTime.next()); - - QList dateTimePropertyManagers = manager->findChildren(); - QListIterator itDateTime(dateTimePropertyManagers); - while (itDateTime.hasNext()) - d_ptr->m_dateTimeEditFactory->addPropertyManager(itDateTime.next()); - - QList keySequencePropertyManagers = manager->findChildren(); - QListIterator itKeySequence(keySequencePropertyManagers); - while (itKeySequence.hasNext()) - d_ptr->m_keySequenceEditorFactory->addPropertyManager(itKeySequence.next()); - - QList charPropertyManagers = manager->findChildren(); - QListIterator itChar(charPropertyManagers); - while (itChar.hasNext()) - d_ptr->m_charEditorFactory->addPropertyManager(itChar.next()); - - QList pointPropertyManagers = manager->findChildren(); - QListIterator itPoint(pointPropertyManagers); - while (itPoint.hasNext()) - d_ptr->m_spinBoxFactory->addPropertyManager(itPoint.next()->subIntPropertyManager()); - - QList pointFPropertyManagers = manager->findChildren(); - QListIterator itPointF(pointFPropertyManagers); - while (itPointF.hasNext()) - d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itPointF.next()->subDoublePropertyManager()); - - QList sizePropertyManagers = manager->findChildren(); - QListIterator itSize(sizePropertyManagers); - while (itSize.hasNext()) - d_ptr->m_spinBoxFactory->addPropertyManager(itSize.next()->subIntPropertyManager()); - - QList sizeFPropertyManagers = manager->findChildren(); - QListIterator itSizeF(sizeFPropertyManagers); - while (itSizeF.hasNext()) - d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itSizeF.next()->subDoublePropertyManager()); - - QList rectPropertyManagers = manager->findChildren(); - QListIterator itRect(rectPropertyManagers); - while (itRect.hasNext()) - d_ptr->m_spinBoxFactory->addPropertyManager(itRect.next()->subIntPropertyManager()); - - QList rectFPropertyManagers = manager->findChildren(); - QListIterator itRectF(rectFPropertyManagers); - while (itRectF.hasNext()) - d_ptr->m_doubleSpinBoxFactory->addPropertyManager(itRectF.next()->subDoublePropertyManager()); - - QList colorPropertyManagers = manager->findChildren(); - QListIterator itColor(colorPropertyManagers); - while (itColor.hasNext()) { - QtColorPropertyManager *manager = itColor.next(); - d_ptr->m_colorEditorFactory->addPropertyManager(manager); - d_ptr->m_spinBoxFactory->addPropertyManager(manager->subIntPropertyManager()); - } - - QList enumPropertyManagers = manager->findChildren(); - QListIterator itEnum(enumPropertyManagers); - while (itEnum.hasNext()) - d_ptr->m_comboBoxFactory->addPropertyManager(itEnum.next()); - - QList fontPropertyManagers = manager->findChildren(); - QListIterator itFont(fontPropertyManagers); - while (itFont.hasNext()) { - QtFontPropertyManager *manager = itFont.next(); - d_ptr->m_fontEditorFactory->addPropertyManager(manager); - d_ptr->m_spinBoxFactory->addPropertyManager(manager->subIntPropertyManager()); - d_ptr->m_comboBoxFactory->addPropertyManager(manager->subEnumPropertyManager()); - d_ptr->m_checkBoxFactory->addPropertyManager(manager->subBoolPropertyManager()); - } - - QList cursorPropertyManagers = manager->findChildren(); - QListIterator itCursor(cursorPropertyManagers); - while (itCursor.hasNext()) - d_ptr->m_cursorEditorFactory->addPropertyManager(itCursor.next()); - - QList flagPropertyManagers = manager->findChildren(); - QListIterator itFlag(flagPropertyManagers); - while (itFlag.hasNext()) - d_ptr->m_checkBoxFactory->addPropertyManager(itFlag.next()->subBoolPropertyManager()); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -QWidget *QtVariantEditorFactory::createEditor(QtVariantPropertyManager *manager, QtProperty *property, - QWidget *parent) -{ - const int propType = manager->propertyType(property); - QtAbstractEditorFactoryBase *factory = d_ptr->m_typeToFactory.value(propType, 0); - if (!factory) - return 0; - return factory->createEditor(wrappedProperty(property), parent); -} - -/*! - \internal - - Reimplemented from the QtAbstractEditorFactory class. -*/ -void QtVariantEditorFactory::disconnectPropertyManager(QtVariantPropertyManager *manager) -{ - QList intPropertyManagers = manager->findChildren(); - QListIterator itInt(intPropertyManagers); - while (itInt.hasNext()) - d_ptr->m_spinBoxFactory->removePropertyManager(itInt.next()); - - QList doublePropertyManagers = manager->findChildren(); - QListIterator itDouble(doublePropertyManagers); - while (itDouble.hasNext()) - d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itDouble.next()); - - QList boolPropertyManagers = manager->findChildren(); - QListIterator itBool(boolPropertyManagers); - while (itBool.hasNext()) - d_ptr->m_checkBoxFactory->removePropertyManager(itBool.next()); - - QList stringPropertyManagers = manager->findChildren(); - QListIterator itString(stringPropertyManagers); - while (itString.hasNext()) - d_ptr->m_lineEditFactory->removePropertyManager(itString.next()); - - QList datePropertyManagers = manager->findChildren(); - QListIterator itDate(datePropertyManagers); - while (itDate.hasNext()) - d_ptr->m_dateEditFactory->removePropertyManager(itDate.next()); - - QList timePropertyManagers = manager->findChildren(); - QListIterator itTime(timePropertyManagers); - while (itTime.hasNext()) - d_ptr->m_timeEditFactory->removePropertyManager(itTime.next()); - - QList dateTimePropertyManagers = manager->findChildren(); - QListIterator itDateTime(dateTimePropertyManagers); - while (itDateTime.hasNext()) - d_ptr->m_dateTimeEditFactory->removePropertyManager(itDateTime.next()); - - QList keySequencePropertyManagers = manager->findChildren(); - QListIterator itKeySequence(keySequencePropertyManagers); - while (itKeySequence.hasNext()) - d_ptr->m_keySequenceEditorFactory->removePropertyManager(itKeySequence.next()); - - QList charPropertyManagers = manager->findChildren(); - QListIterator itChar(charPropertyManagers); - while (itChar.hasNext()) - d_ptr->m_charEditorFactory->removePropertyManager(itChar.next()); - - QList pointPropertyManagers = manager->findChildren(); - QListIterator itPoint(pointPropertyManagers); - while (itPoint.hasNext()) - d_ptr->m_spinBoxFactory->removePropertyManager(itPoint.next()->subIntPropertyManager()); - - QList pointFPropertyManagers = manager->findChildren(); - QListIterator itPointF(pointFPropertyManagers); - while (itPointF.hasNext()) - d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itPointF.next()->subDoublePropertyManager()); - - QList sizePropertyManagers = manager->findChildren(); - QListIterator itSize(sizePropertyManagers); - while (itSize.hasNext()) - d_ptr->m_spinBoxFactory->removePropertyManager(itSize.next()->subIntPropertyManager()); - - QList sizeFPropertyManagers = manager->findChildren(); - QListIterator itSizeF(sizeFPropertyManagers); - while (itSizeF.hasNext()) - d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itSizeF.next()->subDoublePropertyManager()); - - QList rectPropertyManagers = manager->findChildren(); - QListIterator itRect(rectPropertyManagers); - while (itRect.hasNext()) - d_ptr->m_spinBoxFactory->removePropertyManager(itRect.next()->subIntPropertyManager()); - - QList rectFPropertyManagers = manager->findChildren(); - QListIterator itRectF(rectFPropertyManagers); - while (itRectF.hasNext()) - d_ptr->m_doubleSpinBoxFactory->removePropertyManager(itRectF.next()->subDoublePropertyManager()); - - QList colorPropertyManagers = manager->findChildren(); - QListIterator itColor(colorPropertyManagers); - while (itColor.hasNext()) { - QtColorPropertyManager *manager = itColor.next(); - d_ptr->m_colorEditorFactory->removePropertyManager(manager); - d_ptr->m_spinBoxFactory->removePropertyManager(manager->subIntPropertyManager()); - } - - QList enumPropertyManagers = manager->findChildren(); - QListIterator itEnum(enumPropertyManagers); - while (itEnum.hasNext()) - d_ptr->m_comboBoxFactory->removePropertyManager(itEnum.next()); - - QList fontPropertyManagers = manager->findChildren(); - QListIterator itFont(fontPropertyManagers); - while (itFont.hasNext()) { - QtFontPropertyManager *manager = itFont.next(); - d_ptr->m_fontEditorFactory->removePropertyManager(manager); - d_ptr->m_spinBoxFactory->removePropertyManager(manager->subIntPropertyManager()); - d_ptr->m_comboBoxFactory->removePropertyManager(manager->subEnumPropertyManager()); - d_ptr->m_checkBoxFactory->removePropertyManager(manager->subBoolPropertyManager()); - } - - QList cursorPropertyManagers = manager->findChildren(); - QListIterator itCursor(cursorPropertyManagers); - while (itCursor.hasNext()) - d_ptr->m_cursorEditorFactory->removePropertyManager(itCursor.next()); - - QList flagPropertyManagers = manager->findChildren(); - QListIterator itFlag(flagPropertyManagers); - while (itFlag.hasNext()) - d_ptr->m_checkBoxFactory->removePropertyManager(itFlag.next()->subBoolPropertyManager()); -} - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -#include "moc_qtvariantproperty.cpp" diff --git a/src/qtpropertybrowser/src/qtvariantproperty.h b/src/qtpropertybrowser/src/qtvariantproperty.h deleted file mode 100644 index 98e7085855..0000000000 --- a/src/qtpropertybrowser/src/qtvariantproperty.h +++ /dev/null @@ -1,188 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Solutions component. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef QTVARIANTPROPERTY_H -#define QTVARIANTPROPERTY_H - -#include "qtpropertybrowser.h" -#include -#include - -#if QT_VERSION >= 0x040400 -QT_BEGIN_NAMESPACE -#endif - -typedef QMap QtIconMap; - -class QtVariantPropertyManager; -class QtVariantPropertyPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtVariantProperty : public QtProperty -{ -public: - ~QtVariantProperty(); - QVariant value() const; - QVariant attributeValue(const QString &attribute) const; - int valueType() const; - int propertyType() const; - - void setValue(const QVariant &value); - void setAttribute(const QString &attribute, const QVariant &value); -protected: - explicit QtVariantProperty(QtVariantPropertyManager *manager); -private: - friend class QtVariantPropertyManager; - QtVariantPropertyPrivate *d_ptr; -}; - -class QtVariantPropertyManagerPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtVariantPropertyManager : public QtAbstractPropertyManager -{ - Q_OBJECT -public: - QtVariantPropertyManager(QObject *parent = 0); - ~QtVariantPropertyManager(); - - virtual QtVariantProperty *addProperty(int propertyType, const QString &name = QString()); - - int propertyType(const QtProperty *property) const; - int valueType(const QtProperty *property) const; - QtVariantProperty *variantProperty(const QtProperty *property) const; - - virtual bool isPropertyTypeSupported(int propertyType) const; - virtual int valueType(int propertyType) const; - virtual QStringList attributes(int propertyType) const; - virtual int attributeType(int propertyType, const QString &attribute) const; - - virtual QVariant value(const QtProperty *property) const; - virtual QVariant attributeValue(const QtProperty *property, const QString &attribute) const; - - static int enumTypeId(); - static int flagTypeId(); - static int groupTypeId(); - static int iconMapTypeId(); -public Q_SLOTS: - virtual void setValue(QtProperty *property, const QVariant &val); - virtual void setAttribute(QtProperty *property, - const QString &attribute, const QVariant &value); -Q_SIGNALS: - void valueChanged(QtProperty *property, const QVariant &val); - void attributeChanged(QtProperty *property, - const QString &attribute, const QVariant &val); -protected: - virtual bool hasValue(const QtProperty *property) const; - QString valueText(const QtProperty *property) const; - QIcon valueIcon(const QtProperty *property) const; - virtual void initializeProperty(QtProperty *property); - virtual void uninitializeProperty(QtProperty *property); - virtual QtProperty *createProperty(); -private: - QtVariantPropertyManagerPrivate *d_ptr; - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, int, int)) - Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, double)) - Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, double, double)) - Q_PRIVATE_SLOT(d_func(), void slotSingleStepChanged(QtProperty *, double)) - Q_PRIVATE_SLOT(d_func(), void slotDecimalsChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, bool)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QString &)) - Q_PRIVATE_SLOT(d_func(), void slotRegExpChanged(QtProperty *, const QRegularExpression &)) - Q_PRIVATE_SLOT(d_func(), void slotEchoModeChanged(QtProperty *, int)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QDate &)) - Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, const QDate &, const QDate &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QTime &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QDateTime &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QKeySequence &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QChar &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QLocale &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QPoint &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QPointF &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QSize &)) - Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, const QSize &, const QSize &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QSizeF &)) - Q_PRIVATE_SLOT(d_func(), void slotRangeChanged(QtProperty *, const QSizeF &, const QSizeF &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QRect &)) - Q_PRIVATE_SLOT(d_func(), void slotConstraintChanged(QtProperty *, const QRect &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QRectF &)) - Q_PRIVATE_SLOT(d_func(), void slotConstraintChanged(QtProperty *, const QRectF &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QColor &)) - Q_PRIVATE_SLOT(d_func(), void slotEnumNamesChanged(QtProperty *, const QStringList &)) - Q_PRIVATE_SLOT(d_func(), void slotEnumIconsChanged(QtProperty *, const QMap &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QSizePolicy &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QFont &)) - Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QCursor &)) - Q_PRIVATE_SLOT(d_func(), void slotFlagNamesChanged(QtProperty *, const QStringList &)) - Q_PRIVATE_SLOT(d_func(), void slotReadOnlyChanged(QtProperty *, bool)) - Q_PRIVATE_SLOT(d_func(), void slotTextVisibleChanged(QtProperty *, bool)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyInserted(QtProperty *, QtProperty *, QtProperty *)) - Q_PRIVATE_SLOT(d_func(), void slotPropertyRemoved(QtProperty *, QtProperty *)) - Q_DECLARE_PRIVATE(QtVariantPropertyManager) - Q_DISABLE_COPY(QtVariantPropertyManager) -}; - -class QtVariantEditorFactoryPrivate; - -class QT_QTPROPERTYBROWSER_EXPORT QtVariantEditorFactory : public QtAbstractEditorFactory -{ - Q_OBJECT -public: - QtVariantEditorFactory(QObject *parent = 0); - ~QtVariantEditorFactory(); -protected: - void connectPropertyManager(QtVariantPropertyManager *manager); - QWidget *createEditor(QtVariantPropertyManager *manager, QtProperty *property, - QWidget *parent); - void disconnectPropertyManager(QtVariantPropertyManager *manager); -private: - QtVariantEditorFactoryPrivate *d_ptr; - Q_DECLARE_PRIVATE(QtVariantEditorFactory) - Q_DISABLE_COPY(QtVariantEditorFactory) -}; - -#if QT_VERSION >= 0x040400 -QT_END_NAMESPACE -#endif - -Q_DECLARE_METATYPE(QIcon) -Q_DECLARE_METATYPE(QtIconMap) -#endif diff --git a/src/tiled/addpropertydialog.cpp b/src/tiled/addpropertydialog.cpp deleted file mode 100644 index 230ba545ad..0000000000 --- a/src/tiled/addpropertydialog.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * addpropertydialog.cpp - * Copyright 2015, CaptainFrog - * Copyright 2016, Thorbjørn Lindeijer - * - * This file is part of Tiled. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#include "addpropertydialog.h" -#include "ui_addpropertydialog.h" - -#include "documentmanager.h" -#include "object.h" -#include "preferences.h" -#include "properties.h" -#include "propertytypesmodel.h" -#include "session.h" -#include "utils.h" - -#include - -using namespace Tiled; - -namespace session { -static SessionOption propertyType { "property.type", QStringLiteral("string") }; -} // namespace session - -AddPropertyDialog::AddPropertyDialog(QWidget *parent) - : QDialog(parent) - , mUi(new Ui::AddPropertyDialog) -{ - initialize(nullptr); -} - -AddPropertyDialog::AddPropertyDialog(const ClassPropertyType *parentClassType, QWidget *parent) - : QDialog(parent) - , mUi(new Ui::AddPropertyDialog) -{ - initialize(parentClassType); -} - -void AddPropertyDialog::initialize(const Tiled::ClassPropertyType *parentClassType) -{ - mUi->setupUi(this); - resize(Utils::dpiScaled(size())); - - const QIcon plain(QStringLiteral("://images/scalable/property-type-plain.svg")); - - // Add possible types from QVariant - mUi->typeBox->addItem(plain, typeToName(QMetaType::Bool), false); - mUi->typeBox->addItem(plain, typeToName(QMetaType::QColor), QColor()); - mUi->typeBox->addItem(plain, typeToName(QMetaType::Double), 0.0); - mUi->typeBox->addItem(plain, typeToName(filePathTypeId()), QVariant::fromValue(FilePath())); - mUi->typeBox->addItem(plain, typeToName(QMetaType::Int), 0); - mUi->typeBox->addItem(plain, typeToName(objectRefTypeId()), QVariant::fromValue(ObjectRef())); - mUi->typeBox->addItem(plain, typeToName(QMetaType::QString), QString()); - - for (const auto propertyType : Object::propertyTypes()) { - // Avoid suggesting the creation of circular dependencies between types - if (parentClassType && !parentClassType->canAddMemberOfType(propertyType)) - continue; - - // Avoid suggesting classes not meant to be used as property value - if (propertyType->isClass()) - if (!static_cast(propertyType)->isPropertyValueType()) - continue; - - const QVariant var = propertyType->wrap(propertyType->defaultValue()); - const QIcon icon = PropertyTypesModel::iconForPropertyType(propertyType->type); - mUi->typeBox->addItem(icon, propertyType->name, var); - } - - mUi->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - - // Restore previously used type - mUi->typeBox->setCurrentText(session::propertyType); - - connect(mUi->name, &QLineEdit::textChanged, - this, &AddPropertyDialog::nameChanged); - connect(mUi->typeBox, &QComboBox::currentTextChanged, - this, &AddPropertyDialog::typeChanged); - - mUi->name->setFocus(); -} - -AddPropertyDialog::~AddPropertyDialog() -{ - delete mUi; -} - -QString AddPropertyDialog::propertyName() const -{ - return mUi->name->text(); -} - -QVariant AddPropertyDialog::propertyValue() const -{ - return mUi->typeBox->currentData(); -} - -void AddPropertyDialog::nameChanged(const QString &text) -{ - mUi->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!text.isEmpty()); -} - -void AddPropertyDialog::typeChanged(const QString &text) -{ - session::propertyType = text; -} - -#include "moc_addpropertydialog.cpp" diff --git a/src/tiled/addpropertydialog.h b/src/tiled/addpropertydialog.h deleted file mode 100644 index ba36977958..0000000000 --- a/src/tiled/addpropertydialog.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * addpropertydialog.h - * Copyright 2015, CaptainFrog - * Copyright 2016, Thorbjørn Lindeijer - * - * This file is part of Tiled. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#pragma once - -#include -#include - -namespace Tiled { -class ClassPropertyType; -} - -namespace Ui { -class AddPropertyDialog; -} - -class AddPropertyDialog : public QDialog -{ - Q_OBJECT - -public: - explicit AddPropertyDialog(QWidget *parent = nullptr); - AddPropertyDialog(const Tiled::ClassPropertyType *parentClassType, QWidget *parent = nullptr); - ~AddPropertyDialog() override; - - QString propertyName() const; - QVariant propertyValue() const; - -private: - void initialize(const Tiled::ClassPropertyType *parentClassType); - - void nameChanged(const QString &text); - void typeChanged(const QString &text); - - Ui::AddPropertyDialog *mUi; -}; diff --git a/src/tiled/addpropertydialog.ui b/src/tiled/addpropertydialog.ui deleted file mode 100644 index 1b927c33b5..0000000000 --- a/src/tiled/addpropertydialog.ui +++ /dev/null @@ -1,103 +0,0 @@ - - - AddPropertyDialog - - - - 0 - 0 - 320 - 134 - - - - - 0 - 0 - - - - Add Property - - - - QLayout::SetMinAndMaxSize - - - - - - - - Qt::Horizontal - - - - 214 - 18 - - - - - - - - Property name - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - typeBox - name - - - - - buttonBox - accepted() - AddPropertyDialog - accept() - - - 302 - 96 - - - 157 - 105 - - - - - buttonBox - rejected() - AddPropertyDialog - reject() - - - 338 - 96 - - - 286 - 105 - - - - - diff --git a/src/tiled/changeevents.h b/src/tiled/changeevents.h index c5e4061f27..313bb36dfa 100644 --- a/src/tiled/changeevents.h +++ b/src/tiled/changeevents.h @@ -61,6 +61,7 @@ class ChangeEvent WangSetRemoved, WangSetChanged, WangColorAboutToBeRemoved, + WangColorChanged, } type; protected: @@ -164,7 +165,7 @@ class TileLayerChangeEvent : public LayerChangeEvent class ImageLayerChangeEvent : public LayerChangeEvent { public: - enum TileLayerProperty { + enum ImageLayerProperty { TransparentColorProperty = 1 << 7, ImageSourceProperty = 1 << 8, RepeatProperty = 1 << 9, @@ -277,17 +278,20 @@ class WangSetChangeEvent : public ChangeEvent { public: enum WangSetProperty { - TypeProperty = 1 << 0, + NameProperty, + TypeProperty, + ImageProperty, + ColorCountProperty, }; - WangSetChangeEvent(WangSet *wangSet, int properties) + WangSetChangeEvent(WangSet *wangSet, WangSetProperty property) : ChangeEvent(WangSetChanged) , wangSet(wangSet) - , properties(properties) + , property(property) {} WangSet *wangSet; - int properties; + WangSetProperty property; }; class WangColorEvent : public ChangeEvent @@ -303,4 +307,24 @@ class WangColorEvent : public ChangeEvent int color; }; +class WangColorChangeEvent : public ChangeEvent +{ +public: + enum WangColorProperty { + NameProperty, + ColorProperty, + ImageProperty, + ProbabilityProperty, + }; + + WangColorChangeEvent(WangColor *wangColor, WangColorProperty property) + : ChangeEvent(WangColorChanged) + , wangColor(wangColor) + , property(property) + {} + + WangColor *wangColor; + WangColorProperty property; +}; + } // namespace Tiled diff --git a/src/tiled/changelayer.cpp b/src/tiled/changelayer.cpp index 93ce88f176..39427fb664 100644 --- a/src/tiled/changelayer.cpp +++ b/src/tiled/changelayer.cpp @@ -23,7 +23,6 @@ #include "changeevents.h" #include "document.h" #include "layer.h" -#include "map.h" #include diff --git a/src/tiled/changemapproperty.cpp b/src/tiled/changemapproperty.cpp deleted file mode 100644 index c52d4052d0..0000000000 --- a/src/tiled/changemapproperty.cpp +++ /dev/null @@ -1,241 +0,0 @@ -/* - * changemapproperty.cpp - * Copyright 2012, Emmanuel Barroga emmanuelbarroga@gmail.com - * - * This file is part of Tiled. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#include "changemapproperty.h" - -#include "changeevents.h" -#include "map.h" -#include "mapdocument.h" - -#include - -using namespace Tiled; - -ChangeMapProperty::ChangeMapProperty(MapDocument *mapDocument, - Map::Property property, - int value) - : mMapDocument(mapDocument) - , mProperty(property) - , mIntValue(value) -{ - switch (property) { - case Map::TileWidthProperty: - setText(QCoreApplication::translate("Undo Commands", - "Change Tile Width")); - break; - case Map::TileHeightProperty: - setText(QCoreApplication::translate("Undo Commands", - "Change Tile Height")); - break; - case Map::InfiniteProperty: - setText(QCoreApplication::translate("Undo Commands", - "Change Infinite Property")); - break; - case Map::HexSideLengthProperty: - setText(QCoreApplication::translate("Undo Commands", - "Change Hex Side Length")); - break; - case Map::CompressionLevelProperty: - setText(QCoreApplication::translate("Undo Commands", - "Change Compression Level")); - break; - default: - break; - } -} - -ChangeMapProperty::ChangeMapProperty(MapDocument *mapDocument, - const QColor &backgroundColor) - : QUndoCommand(QCoreApplication::translate("Undo Commands", - "Change Background Color")) - , mMapDocument(mapDocument) - , mProperty(Map::BackgroundColorProperty) - , mBackgroundColor(backgroundColor) -{ -} - -ChangeMapProperty::ChangeMapProperty(MapDocument *mapDocument, - QSize chunkSize) - : QUndoCommand(QCoreApplication::translate("Undo Commands", - "Change Chunk Size")) - , mMapDocument(mapDocument) - , mProperty(Map::ChunkSizeProperty) - , mChunkSize(chunkSize) -{ -} - -ChangeMapProperty::ChangeMapProperty(MapDocument *mapDocument, - Map::StaggerAxis staggerAxis) - : QUndoCommand(QCoreApplication::translate("Undo Commands", - "Change Stagger Axis")) - , mMapDocument(mapDocument) - , mProperty(Map::StaggerAxisProperty) - , mStaggerAxis(staggerAxis) -{ -} - -ChangeMapProperty::ChangeMapProperty(MapDocument *mapDocument, - Map::StaggerIndex staggerIndex) - : QUndoCommand(QCoreApplication::translate("Undo Commands", - "Change Stagger Index")) - , mMapDocument(mapDocument) - , mProperty(Map::StaggerIndexProperty) - , mStaggerIndex(staggerIndex) -{ -} - -ChangeMapProperty::ChangeMapProperty(MapDocument *mapDocument, - const QPointF ¶llaxOrigin) - : QUndoCommand(QCoreApplication::translate("Undo Commands", - "Change Parallax Origin")) - , mMapDocument(mapDocument) - , mProperty(Map::ParallaxOriginProperty) - , mParallaxOrigin(parallaxOrigin) -{ -} - -ChangeMapProperty::ChangeMapProperty(MapDocument *mapDocument, - Map::Orientation orientation) - : QUndoCommand(QCoreApplication::translate("Undo Commands", - "Change Orientation")) - , mMapDocument(mapDocument) - , mProperty(Map::OrientationProperty) - , mOrientation(orientation) -{ -} - -ChangeMapProperty::ChangeMapProperty(MapDocument *mapDocument, - Map::RenderOrder renderOrder) - : QUndoCommand(QCoreApplication::translate("Undo Commands", - "Change Render Order")) - , mMapDocument(mapDocument) - , mProperty(Map::RenderOrderProperty) - , mRenderOrder(renderOrder) -{ -} - -ChangeMapProperty::ChangeMapProperty(MapDocument *mapDocument, - Map::LayerDataFormat layerDataFormat) - : QUndoCommand(QCoreApplication::translate("Undo Commands", - "Change Layer Data Format")) - , mMapDocument(mapDocument) - , mProperty(Map::LayerDataFormatProperty) - , mLayerDataFormat(layerDataFormat) -{ -} - -void ChangeMapProperty::redo() -{ - swap(); -} - -void ChangeMapProperty::undo() -{ - swap(); -} - -void ChangeMapProperty::swap() -{ - Map *map = mMapDocument->map(); - - switch (mProperty) { - case Map::TileWidthProperty: { - const int tileWidth = map->tileWidth(); - map->setTileWidth(mIntValue); - mIntValue = tileWidth; - break; - } - case Map::TileHeightProperty: { - const int tileHeight = map->tileHeight(); - map->setTileHeight(mIntValue); - mIntValue = tileHeight; - break; - } - case Map::InfiniteProperty: { - const int infinite = map->infinite(); - map->setInfinite(mIntValue); - mIntValue = infinite; - break; - } - case Map::OrientationProperty: { - const Map::Orientation orientation = map->orientation(); - map->setOrientation(mOrientation); - mOrientation = orientation; - break; - } - case Map::HexSideLengthProperty: { - const int hexSideLength = map->hexSideLength(); - map->setHexSideLength(mIntValue); - mIntValue = hexSideLength; - break; - } - case Map::StaggerAxisProperty: { - const Map::StaggerAxis staggerAxis = map->staggerAxis(); - map->setStaggerAxis(mStaggerAxis); - mStaggerAxis = staggerAxis; - break; - } - case Map::StaggerIndexProperty: { - const Map::StaggerIndex staggerIndex = map->staggerIndex(); - map->setStaggerIndex(mStaggerIndex); - mStaggerIndex = staggerIndex; - break; - } - case Map::ParallaxOriginProperty: { - const QPointF parallaxOrigin = map->parallaxOrigin(); - map->setParallaxOrigin(mParallaxOrigin); - mParallaxOrigin = parallaxOrigin; - break; - } - case Map::RenderOrderProperty: { - const Map::RenderOrder renderOrder = map->renderOrder(); - map->setRenderOrder(mRenderOrder); - mRenderOrder = renderOrder; - break; - } - case Map::BackgroundColorProperty: { - const QColor backgroundColor = map->backgroundColor(); - map->setBackgroundColor(mBackgroundColor); - mBackgroundColor = backgroundColor; - break; - } - case Map::LayerDataFormatProperty: { - const Map::LayerDataFormat layerDataFormat = map->layerDataFormat(); - map->setLayerDataFormat(mLayerDataFormat); - mLayerDataFormat = layerDataFormat; - break; - } - case Map::CompressionLevelProperty: { - const int compressionLevel = map->compressionLevel(); - map->setCompressionLevel(mIntValue); - mIntValue = compressionLevel; - break; - } - case Map::ChunkSizeProperty: { - const QSize chunkSize = map->chunkSize(); - map->setChunkSize(mChunkSize); - mChunkSize = chunkSize; - break; - } - } - - emit mMapDocument->changed(MapChangeEvent(mProperty)); - emit mMapDocument->mapChanged(); -} diff --git a/src/tiled/changemapproperty.h b/src/tiled/changemapproperty.h index 03e93dd403..3ea19d0237 100644 --- a/src/tiled/changemapproperty.h +++ b/src/tiled/changemapproperty.h @@ -1,6 +1,7 @@ /* * changemapproperty.h * Copyright 2012, Emmanuel Barroga emmanuelbarroga@gmail.com + * Copyright 2014-2024, Thorbjørn Lindeijer * * This file is part of Tiled. * @@ -20,111 +21,212 @@ #pragma once +#include "changeevents.h" +#include "changevalue.h" #include "map.h" +#include "mapdocument.h" #include -#include +#include namespace Tiled { class MapDocument; -class ChangeMapProperty : public QUndoCommand +struct MapBackgroundColor +{ + using Type = QColor; + + static void set(Map *map, Type value) { map->setBackgroundColor(value); } + static Type get(const Map *map) { return map->backgroundColor(); } + static int undoId() { return Cmd_ChangeMapBackgroundColor; } + static Map::Property property() { return Map::BackgroundColorProperty; } + static QString undoName() { + return QCoreApplication::translate("Undo Commands", "Change Background Color"); + } +}; + +struct MapChunkSize +{ + using Type = QSize; + + static void set(Map *map, Type value) { map->setChunkSize(value); } + static Type get(const Map *map) { return map->chunkSize(); } + static int undoId() { return Cmd_ChangeMapChunkSize; } + static Map::Property property() { return Map::ChunkSizeProperty; } + static QString undoName() { + return QCoreApplication::translate("Undo Commands", "Change Chunk Size"); + } +}; + +struct MapStaggerAxis +{ + using Type = Map::StaggerAxis; + + static void set(Map *map, Type value) { map->setStaggerAxis(value); } + static Type get(const Map *map) { return map->staggerAxis(); } + static int undoId() { return Cmd_ChangeMapStaggerAxis; } + static Map::Property property() { return Map::StaggerAxisProperty; } + static QString undoName() { + return QCoreApplication::translate("Undo Commands", "Change Stagger Axis"); + } +}; + +struct MapStaggerIndex +{ + using Type = Map::StaggerIndex; + + static void set(Map *map, Type value) { map->setStaggerIndex(value); } + static Type get(const Map *map) { return map->staggerIndex(); } + static int undoId() { return Cmd_ChangeMapStaggerIndex; } + static Map::Property property() { return Map::StaggerIndexProperty; } + static QString undoName() { + return QCoreApplication::translate("Undo Commands", "Change Stagger Index"); + } +}; + +struct MapParallaxOrigin +{ + using Type = QPointF; + + static void set(Map *map, Type value) { map->setParallaxOrigin(value); } + static Type get(const Map *map) { return map->parallaxOrigin(); } + static int undoId() { return Cmd_ChangeMapParallaxOrigin; } + static Map::Property property() { return Map::ParallaxOriginProperty; } + static QString undoName() { + return QCoreApplication::translate("Undo Commands", "Change Parallax Origin"); + } +}; + +struct MapOrientation +{ + using Type = Map::Orientation; + + static void set(Map *map, Type value) { map->setOrientation(value); } + static Type get(const Map *map) { return map->orientation(); } + static int undoId() { return Cmd_ChangeMapOrientation; } + static Map::Property property() { return Map::OrientationProperty; } + static QString undoName() { + return QCoreApplication::translate("Undo Commands", "Change Orientation"); + } +}; + +struct MapRenderOrder +{ + using Type = Map::RenderOrder; + + static void set(Map *map, Type value) { map->setRenderOrder(value); } + static Type get(const Map *map) { return map->renderOrder(); } + static int undoId() { return Cmd_ChangeMapRenderOrder; } + static Map::Property property() { return Map::RenderOrderProperty; } + static QString undoName() { + return QCoreApplication::translate("Undo Commands", "Change Render Order"); + } +}; + +struct MapLayerDataFormat +{ + using Type = Map::LayerDataFormat; + + static void set(Map *map, Type value) { map->setLayerDataFormat(value); } + static Type get(const Map *map) { return map->layerDataFormat(); } + static int undoId() { return Cmd_ChangeMapLayerDataFormat; } + static Map::Property property() { return Map::LayerDataFormatProperty; } + static QString undoName() { + return QCoreApplication::translate("Undo Commands", "Change Layer Data Format"); + } +}; + +struct MapTileSize +{ + using Type = QSize; + + static void set(Map *map, Type value) { map->setTileSize(value); } + static Type get(const Map *map) { return map->tileSize(); } + static int undoId() { return Cmd_ChangeMapTileSize; } + static Map::Property property() { return Map::TileSizeProperty; } + static QString undoName() { + return QCoreApplication::translate("Undo Commands", "Change Tile Size"); + } +}; + +struct MapInfinite +{ + using Type = bool; + + static void set(Map *map, Type value) { map->setInfinite(value); } + static Type get(const Map *map) { return map->infinite(); } + static int undoId() { return Cmd_ChangeMapInfinite; } + static Map::Property property() { return Map::InfiniteProperty; } + static QString undoName() { + return QCoreApplication::translate("Undo Commands", "Change Infinite"); + } +}; + +struct MapHexSideLength +{ + using Type = int; + + static void set(Map *map, Type value) { map->setHexSideLength(value); } + static Type get(const Map *map) { return map->hexSideLength(); } + static int undoId() { return Cmd_ChangeMapHexSideLength; } + static Map::Property property() { return Map::HexSideLengthProperty; } + static QString undoName() { + return QCoreApplication::translate("Undo Commands", "Change Hex Side Length"); + } +}; + +struct MapCompressionLevel +{ + using Type = int; + + static void set(Map *map, Type value) { map->setCompressionLevel(value); } + static Type get(const Map *map) { return map->compressionLevel(); } + static int undoId() { return Cmd_ChangeMapCompressionLevel; } + static Map::Property property() { return Map::CompressionLevelProperty; } + static QString undoName() { + return QCoreApplication::translate("Undo Commands", "Change Compression Level"); + } +}; + + +template +class ChangeMapProperty : public ChangeValue { public: - /** - * Constructs a command that changes the value of the given property. - * - * Can only be used for the HexSideLength property. - * - * @param mapDocument the map document of the map - * @param backgroundColor the new color to apply for the background - */ - ChangeMapProperty(MapDocument *mapDocument, Map::Property property, int value); - - /** - * Constructs a command that changes the map background color. - * - * @param mapDocument the map document of the map - * @param backgroundColor the new color to apply for the background - */ - ChangeMapProperty(MapDocument *mapDocument, const QColor &backgroundColor); - - /** - * Constructs a command that changes the chunk size. - * - * @param mapDocument the map document of the map - * @param chunkSize the new chunk size to use for tile layers - */ - ChangeMapProperty(MapDocument *mapDocument, QSize chunkSize); - - /** - * Constructs a command that changes the map stagger axis. - * - * @param mapDocument the map document of the map - * @param staggerAxis the new map stagger axis - */ - ChangeMapProperty(MapDocument *mapDocument, Map::StaggerAxis staggerAxis); - - /** - * Constructs a command that changes the map stagger index. - * - * @param mapDocument the map document of the map - * @param staggerIndex the new map stagger index - */ - ChangeMapProperty(MapDocument *mapDocument, Map::StaggerIndex staggerIndex); - - /** - * Constructs a command that changes the parallax origin. - * - * @param mapDocument the map document of the map - * @param parallaxOrigin the new parallax origin - */ - ChangeMapProperty(MapDocument *mapDocument, const QPointF ¶llaxOrigin); - - /** - * Constructs a command that changes the map orientation. - * - * @param mapDocument the map document of the map - * @param orientation the new map orientation - */ - ChangeMapProperty(MapDocument *mapDocument, Map::Orientation orientation); - - /** - * Constructs a command that changes the render order. - * - * @param mapDocument the map document of the map - * @param renderOrder the new map render order - */ - ChangeMapProperty(MapDocument *mapDocument, Map::RenderOrder renderOrder); - - /** - * Constructs a command that changes the layer data format. - * - * @param mapDocument the map document of the map - * @param layerDataFormat the new layer data format - */ - ChangeMapProperty(MapDocument *mapDocument, Map::LayerDataFormat layerDataFormat); - - void undo() override; - void redo() override; + ChangeMapProperty(MapDocument *document, const typename Member::Type &value) + : ChangeValue(document, { document->map() }, value) + { + QUndoCommand::setText(Member::undoName()); + } + + int id() const override { return Member::undoId(); } private: - void swap(); - - MapDocument *mMapDocument; - Map::Property mProperty; - QColor mBackgroundColor; - QSize mChunkSize; - union { - int mIntValue; - Map::StaggerAxis mStaggerAxis; - Map::StaggerIndex mStaggerIndex; - QPointF mParallaxOrigin; - Map::Orientation mOrientation; - Map::RenderOrder mRenderOrder; - Map::LayerDataFormat mLayerDataFormat; - }; + typename Member::Type getValue(const Map *map) const override + { + return Member::get(map); + } + + void setValue(Map *map, const typename Member::Type &value) const override + { + Member::set(map, value); + emit ChangeValue::document()->changed(MapChangeEvent(Member::property())); + } }; + +using ChangeMapBackgroundColor = ChangeMapProperty; +using ChangeMapChunkSize = ChangeMapProperty; +using ChangeMapStaggerAxis = ChangeMapProperty; +using ChangeMapStaggerIndex = ChangeMapProperty; +using ChangeMapParallaxOrigin = ChangeMapProperty; +using ChangeMapOrientation = ChangeMapProperty; +using ChangeMapRenderOrder = ChangeMapProperty; +using ChangeMapLayerDataFormat = ChangeMapProperty; +using ChangeMapTileSize = ChangeMapProperty; +using ChangeMapInfinite = ChangeMapProperty; +using ChangeMapHexSideLength = ChangeMapProperty; +using ChangeMapCompressionLevel = ChangeMapProperty; + } // namespace Tiled diff --git a/src/tiled/changeproperties.cpp b/src/tiled/changeproperties.cpp index 613c3022ec..8814936668 100644 --- a/src/tiled/changeproperties.cpp +++ b/src/tiled/changeproperties.cpp @@ -34,7 +34,7 @@ ChangeClassName::ChangeClassName(Document *document, QUndoCommand *parent) : ChangeValue(document, objects, className, parent) { - setText(QCoreApplication::translate("Undo Commands", "Change Type")); + setText(QCoreApplication::translate("Undo Commands", "Change Class")); } void ChangeClassName::undo() @@ -164,8 +164,7 @@ void SetProperty::undo() void SetProperty::redo() { - const QList &objects = mObjects; - for (Object *obj : objects) + for (Object *obj : std::as_const(mObjects)) mDocument->setPropertyMember(obj, mPath, mValue); } @@ -212,8 +211,7 @@ void RemoveProperty::undo() void RemoveProperty::redo() { - const QList &objects = mObjects; - for (Object *obj : objects) + for (Object *obj : std::as_const(mObjects)) mDocument->removeProperty(obj, mName); } diff --git a/src/tiled/colorbutton.cpp b/src/tiled/colorbutton.cpp index 85d39307c9..32358d4a23 100644 --- a/src/tiled/colorbutton.cpp +++ b/src/tiled/colorbutton.cpp @@ -22,7 +22,6 @@ #include "utils.h" -#include #include #include @@ -40,7 +39,7 @@ ColorButton::ColorButton(QWidget *parent) void ColorButton::setColor(const QColor &color) { - if (mColor == color || !color.isValid()) + if (mColor == color) return; mColor = color; @@ -68,14 +67,17 @@ void ColorButton::changeEvent(QEvent *e) void ColorButton::pickColor() { - const QColor newColor = QColorDialog::getColor(mColor, this); + const QColor newColor = QColorDialog::getColor(mColor, this, QString(), + mDialogOptions); if (newColor.isValid()) setColor(newColor); } void ColorButton::updateIcon() { + // todo: fix gray icon in disabled state (consider using opacity, and not using an icon at all) setIcon(Utils::colorIcon(mColor, iconSize())); + setText(mColor.isValid() ? QString() : tr("Not set")); } #include "moc_colorbutton.cpp" diff --git a/src/tiled/colorbutton.h b/src/tiled/colorbutton.h index b623dc772f..b32de0cc2a 100644 --- a/src/tiled/colorbutton.h +++ b/src/tiled/colorbutton.h @@ -21,6 +21,7 @@ #pragma once #include +#include #include namespace Tiled { @@ -41,6 +42,9 @@ class ColorButton : public QToolButton QColor color() const { return mColor; } void setColor(const QColor &color); + void setShowAlphaChannel(bool enabled) + { mDialogOptions.setFlag(QColorDialog::ShowAlphaChannel, enabled); } + signals: void colorChanged(const QColor &color); @@ -52,6 +56,7 @@ class ColorButton : public QToolButton void updateIcon(); QColor mColor; + QColorDialog::ColorDialogOptions mDialogOptions; }; } // namespace Tiled diff --git a/src/tiled/custompropertieshelper.cpp b/src/tiled/custompropertieshelper.cpp deleted file mode 100644 index a64dd7ed3a..0000000000 --- a/src/tiled/custompropertieshelper.cpp +++ /dev/null @@ -1,351 +0,0 @@ -/* - * custompropertieshelper.cpp - * Copyright 2021, Thorbjørn Lindeijer - * - * This file is part of Tiled. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#include "custompropertieshelper.h" - -#include "object.h" -#include "preferences.h" -#include "propertytype.h" -#include "varianteditorfactory.h" -#include "variantpropertymanager.h" - -#include -#include - -namespace Tiled { - -CustomPropertiesHelper::CustomPropertiesHelper(QtAbstractPropertyBrowser *propertyBrowser, - QObject *parent) - : QObject(parent) - , mPropertyBrowser(propertyBrowser) - , mPropertyManager(new VariantPropertyManager(this)) -{ - auto variantEditorFactory = new VariantEditorFactory(this); - - propertyBrowser->setFactoryForManager(mPropertyManager, variantEditorFactory); - - connect(mPropertyManager, &QtVariantPropertyManager::valueChanged, - this, &CustomPropertiesHelper::onValueChanged); - - connect(variantEditorFactory, &VariantEditorFactory::resetProperty, - this, &CustomPropertiesHelper::resetProperty); - - connect(Preferences::instance(), &Preferences::propertyTypesChanged, - this, &CustomPropertiesHelper::propertyTypesChanged); -} - -CustomPropertiesHelper::~CustomPropertiesHelper() -{ - mPropertyBrowser->unsetFactoryForManager(mPropertyManager); -} - -QtVariantProperty *CustomPropertiesHelper::createProperty(const QString &name, - const QVariant &value) -{ - Q_ASSERT(!mProperties.contains(name)); - - QScopedValueRollback updating(mUpdating, true); - - QtVariantProperty *property = createPropertyInternal(name, value); - property->setValue(toDisplayValue(value)); - - mProperties.insert(name, property); - - return property; -} - -QtVariantProperty *CustomPropertiesHelper::createPropertyInternal(const QString &name, - const QVariant &value) -{ - int type = value.userType(); - - const PropertyType *propertyType = nullptr; - - if (type == propertyValueId()) { - const PropertyValue propertyValue = value.value(); - propertyType = propertyValue.type(); - - if (propertyType) { - switch (propertyType->type) { - case PropertyType::PT_Invalid: - break; - case PropertyType::PT_Class: - type = VariantPropertyManager::unstyledGroupTypeId(); - break; - case PropertyType::PT_Enum: { - const auto &enumType = static_cast(*propertyType); - if (enumType.valuesAsFlags) - type = QtVariantPropertyManager::flagTypeId(); - else - type = QtVariantPropertyManager::enumTypeId(); - break; - } - } - } - } - - if (type == objectRefTypeId()) - type = VariantPropertyManager::displayObjectRefTypeId(); - - QtVariantProperty *property = mPropertyManager->addProperty(type, name); - if (!property) { - // fall back to string property for unsupported property types - property = mPropertyManager->addProperty(QMetaType::QString, name); - } - - if (type == QMetaType::Bool) - property->setAttribute(QLatin1String("textVisible"), false); - if (type == QMetaType::QString) - property->setAttribute(QLatin1String("multiline"), true); - if (type == QMetaType::Double) - property->setAttribute(QLatin1String("decimals"), 9); - - if (propertyType) { - mPropertyTypeIds.insert(property, propertyType->id); - setPropertyAttributes(property, *propertyType); - } else { - mPropertyTypeIds.insert(property, 0); - } - - return property; -} - -void CustomPropertiesHelper::deleteProperty(QtProperty *property) -{ - Q_ASSERT(hasProperty(property)); - - mProperties.remove(property->propertyName()); - deletePropertyInternal(property); -} - -void CustomPropertiesHelper::deletePropertyInternal(QtProperty *property) -{ - Q_ASSERT(mPropertyTypeIds.contains(property)); - deleteSubProperties(property); - mPropertyTypeIds.remove(property); - delete property; -} - -void CustomPropertiesHelper::deleteSubProperties(QtProperty *property) -{ - const auto subProperties = property->subProperties(); - for (QtProperty *subProperty : subProperties) { - if (mPropertyParents.value(subProperty) == property) { - deletePropertyInternal(subProperty); - mPropertyParents.remove(subProperty); - } - } -} - -void CustomPropertiesHelper::clear() -{ - QHashIterator it(mPropertyTypeIds); - while (it.hasNext()) - delete it.next().key(); - - mProperties.clear(); - mPropertyTypeIds.clear(); - mPropertyParents.clear(); -} - -QVariant CustomPropertiesHelper::toDisplayValue(QVariant value) const -{ - if (value.userType() == propertyValueId()) - value = value.value().value; - - if (value.userType() == objectRefTypeId()) - value = QVariant::fromValue(DisplayObjectRef { value.value(), mMapDocument }); - - return value; -} - -QVariant CustomPropertiesHelper::fromDisplayValue(QtProperty *property, - QVariant value) const -{ - if (value.userType() == VariantPropertyManager::displayObjectRefTypeId()) - value = QVariant::fromValue(value.value().ref); - - if (auto type = propertyType(property)) - value = type->wrap(value); - - return value; -} - -void CustomPropertiesHelper::onValueChanged(QtProperty *property, const QVariant &value) -{ - if (!mPropertyTypeIds.contains(property)) - return; - - if (!mUpdating) { - const auto propertyValue = fromDisplayValue(property, value); - const auto path = propertyPath(property); - - QScopedValueRollback emittingValueChanged(mEmittingValueChanged, true); - emit propertyMemberValueChanged(path, propertyValue); - } - - if (auto type = propertyType(property); type && type->isClass()) { - // Apply the change to the children - - auto &members = static_cast(*type).members; - - const auto subProperties = property->subProperties(); - const auto map = value.toMap(); - - QScopedValueRollback updating(mUpdating, true); - - for (QtProperty *subProperty : subProperties) { - const auto name = subProperty->propertyName(); - const bool modified = map.contains(name); - const auto value = modified ? map.value(name) - : members.value(name); - - // Avoid setting child class members as modified, just because - // the class definition sets different defaults on them. - const bool isParentTopLevel = !mPropertyParents.contains(property); - const bool isParentModified = property->isModified(); - subProperty->setModified(modified && (isParentTopLevel || isParentModified)); - - static_cast(subProperty)->setValue(toDisplayValue(value)); - } - } -} - -void CustomPropertiesHelper::resetProperty(QtProperty *property) -{ - // Reset class property value by removing it - if (property->isModified()) { - // Only nested properties are currently marked as "modified", so in - // this case we rely on the handling of this signal - emit propertyMemberValueChanged(propertyPath(property), QVariant()); - return; - } - - // Some other type can reset their value - auto typeId = mPropertyManager->propertyType(property); - - if (typeId == QMetaType::QColor) - mPropertyManager->setValue(property, QColor()); - else if (typeId == VariantPropertyManager::displayObjectRefTypeId()) { - mPropertyManager->setValue(property, toDisplayValue(QVariant::fromValue(ObjectRef()))); - } else { - qWarning() << "Requested reset of unsupported type" << typeId << "for property" << property->propertyName(); - } -} - -void CustomPropertiesHelper::propertyTypesChanged() -{ - // When this happens in response to emitting propertyValueChanged, it means - // we have triggered a change in a class definition. In this case we should - // not update ourselves. - if (mEmittingValueChanged) - return; - - QHashIterator it(mProperties); - while (it.hasNext()) { - it.next(); - const auto property = it.value(); - const auto typeId = mPropertyTypeIds.value(property); - if (!typeId) - continue; - - if (const auto type = Object::propertyTypes().findTypeById(typeId)) { - setPropertyAttributes(property, *type); - - if (type->isClass()) { - // Restore the existing member values - QScopedValueRollback updating(mUpdating, true); - onValueChanged(property, property->value()); - } - } - } -} - -void CustomPropertiesHelper::setPropertyAttributes(QtVariantProperty *property, - const PropertyType &propertyType) -{ - switch (propertyType.type) { - case Tiled::PropertyType::PT_Invalid: - break; - case Tiled::PropertyType::PT_Class: { - const auto &classType = static_cast(propertyType); - - // Delete any existing sub-properties - deleteSubProperties(property); - - // Create a sub-property for each member - QMapIterator it(classType.members); - while (it.hasNext()) { - it.next(); - const QString &name = it.key(); - const QVariant &value = it.value(); - - auto subProperty = createPropertyInternal(name, value); - property->addSubProperty(subProperty); - mPropertyParents.insert(subProperty, property); - } - break; - } - case Tiled::PropertyType::PT_Enum: { - const auto &enumType = static_cast(propertyType); - const bool isFlags = property->propertyType() == QtVariantPropertyManager::flagTypeId(); - - // Need to re-create the property when valuesAsFlags changed, but we - // don't have access to the view. - if (enumType.valuesAsFlags != isFlags) { - emit recreateProperty(property, fromDisplayValue(property, property->value())); - return; - } - - // Setting these attributes leads to emission of valueChanged... - QScopedValueRollback updating(mUpdating, true); - - if (enumType.valuesAsFlags) { - mPropertyManager->setAttribute(property, QStringLiteral("flagNames"), enumType.values); - } else { - // TODO: Support icons for enum values - mPropertyManager->setAttribute(property, QStringLiteral("enumNames"), enumType.values); - } - break; - } - } -} - -const PropertyType *CustomPropertiesHelper::propertyType(QtProperty *property) const -{ - if (const auto typeId = mPropertyTypeIds.value(property)) - return Object::propertyTypes().findTypeById(typeId); - return nullptr; -} - -QStringList CustomPropertiesHelper::propertyPath(QtProperty *property) const -{ - QStringList path; - - if (auto parent = mPropertyParents.value(property)) - path = propertyPath(parent); - - path.append(property->propertyName()); - return path; -} - -} // namespace Tiled - -#include "moc_custompropertieshelper.cpp" diff --git a/src/tiled/custompropertieshelper.h b/src/tiled/custompropertieshelper.h deleted file mode 100644 index 1006b4a071..0000000000 --- a/src/tiled/custompropertieshelper.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * custompropertieshelper.h - * Copyright 2021, Thorbjørn Lindeijer - * - * This file is part of Tiled. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#pragma once - -#include -#include - -class QtAbstractPropertyBrowser; -class QtProperty; -class QtVariantProperty; -class QtVariantPropertyManager; - -namespace Tiled { - -class MapDocument; -class PropertyType; -class VariantEditorFactory; - -class CustomPropertiesHelper : public QObject -{ - Q_OBJECT - -public: - CustomPropertiesHelper(QtAbstractPropertyBrowser *propertyBrowser, - QObject *parent = nullptr); - ~CustomPropertiesHelper() override; - - QtVariantProperty *createProperty(const QString &name, const QVariant &value); - void deleteProperty(QtProperty *property); - void clear(); - bool hasProperty(QtProperty *property) const; - QtVariantProperty *property(const QString &name); - const QHash &properties() const; - - QVariant toDisplayValue(QVariant value) const; - QVariant fromDisplayValue(QtProperty *property, QVariant value) const; - - void setMapDocument(MapDocument *mapDocument); - -signals: - void propertyMemberValueChanged(const QStringList &path, const QVariant &value); - void recreateProperty(QtVariantProperty *property, const QVariant &value); - -private: - QtVariantProperty *createPropertyInternal(const QString &name, - const QVariant &value); - void deletePropertyInternal(QtProperty *property); - void deleteSubProperties(QtProperty *property); - - void onValueChanged(QtProperty *property, const QVariant &value); - void resetProperty(QtProperty *property); - void propertyTypesChanged(); - - void setPropertyAttributes(QtVariantProperty *property, - const PropertyType &propertyType); - - const PropertyType *propertyType(QtProperty *property) const; - QStringList propertyPath(QtProperty *property) const; - - QtAbstractPropertyBrowser *mPropertyBrowser; - QtVariantPropertyManager *mPropertyManager; - MapDocument *mMapDocument = nullptr; - QHash mProperties; - QHash mPropertyTypeIds; - QHash mPropertyParents; - bool mUpdating = false; - bool mEmittingValueChanged = false; -}; - -inline bool CustomPropertiesHelper::hasProperty(QtProperty *property) const -{ - return mPropertyTypeIds.contains(property) && !mPropertyParents.contains(property); -} - -inline QtVariantProperty *CustomPropertiesHelper::property(const QString &name) -{ - return mProperties.value(name); -} - -inline const QHash &CustomPropertiesHelper::properties() const -{ - return mProperties; -} - -inline void CustomPropertiesHelper::setMapDocument(MapDocument *mapDocument) -{ - mMapDocument = mapDocument; -} - -} // namespace Tiled diff --git a/src/tiled/document.cpp b/src/tiled/document.cpp index 7c546cd1e1..51c3fe7d4c 100644 --- a/src/tiled/document.cpp +++ b/src/tiled/document.cpp @@ -145,6 +145,7 @@ void Document::setCurrentObject(Object *object, Document *owningDocument) emit currentObjectSet(object); emit currentObjectChanged(object); + emit currentObjectsChanged(); } /** diff --git a/src/tiled/document.h b/src/tiled/document.h index a99b8049ac..62c2088bfb 100644 --- a/src/tiled/document.h +++ b/src/tiled/document.h @@ -139,6 +139,7 @@ class Document : public QObject, void currentObjectSet(Object *object); void currentObjectChanged(Object *object); + void currentObjectsChanged(); /** * Makes the Properties window visible and take focus. diff --git a/src/tiled/editablemap.cpp b/src/tiled/editablemap.cpp index d0f3a2878a..02c0b97572 100644 --- a/src/tiled/editablemap.cpp +++ b/src/tiled/editablemap.cpp @@ -495,7 +495,7 @@ void EditableMap::setSize(int width, int height) void EditableMap::setTileWidth(int value) { if (auto doc = mapDocument()) - push(new ChangeMapProperty(doc, Map::TileWidthProperty, value)); + push(new ChangeMapTileSize(doc, QSize(value, tileHeight()))); else if (!checkReadOnly()) map()->setTileWidth(value); } @@ -503,7 +503,7 @@ void EditableMap::setTileWidth(int value) void EditableMap::setTileHeight(int value) { if (auto doc = mapDocument()) - push(new ChangeMapProperty(doc, Map::TileHeightProperty, value)); + push(new ChangeMapTileSize(doc, QSize(tileWidth(), value))); else if (!checkReadOnly()) map()->setTileHeight(value); } @@ -528,7 +528,7 @@ void EditableMap::setTileSize(int width, int height) void EditableMap::setInfinite(bool value) { if (auto doc = mapDocument()) - push(new ChangeMapProperty(doc, Map::InfiniteProperty, value)); + push(new ChangeMapInfinite(doc, value)); else if (!checkReadOnly()) map()->setInfinite(value); } @@ -536,7 +536,7 @@ void EditableMap::setInfinite(bool value) void EditableMap::setHexSideLength(int value) { if (auto doc = mapDocument()) - push(new ChangeMapProperty(doc, Map::HexSideLengthProperty, value)); + push(new ChangeMapHexSideLength(doc, value)); else if (!checkReadOnly()) map()->setHexSideLength(value); } @@ -544,7 +544,7 @@ void EditableMap::setHexSideLength(int value) void EditableMap::setStaggerAxis(StaggerAxis value) { if (auto doc = mapDocument()) - push(new ChangeMapProperty(doc, static_cast(value))); + push(new ChangeMapStaggerAxis(doc, static_cast(value))); else if (!checkReadOnly()) map()->setStaggerAxis(static_cast(value)); } @@ -552,7 +552,7 @@ void EditableMap::setStaggerAxis(StaggerAxis value) void EditableMap::setStaggerIndex(StaggerIndex value) { if (auto doc = mapDocument()) - push(new ChangeMapProperty(doc, static_cast(value))); + push(new ChangeMapStaggerIndex(doc, static_cast(value))); else if (!checkReadOnly()) map()->setStaggerIndex(static_cast(value)); } @@ -560,7 +560,7 @@ void EditableMap::setStaggerIndex(StaggerIndex value) void EditableMap::setParallaxOrigin(const QPointF ¶llaxOrigin) { if (auto doc = mapDocument()) - push(new ChangeMapProperty(doc, parallaxOrigin)); + push(new ChangeMapParallaxOrigin(doc, parallaxOrigin)); else if (!checkReadOnly()) map()->setParallaxOrigin(parallaxOrigin); } @@ -568,7 +568,7 @@ void EditableMap::setParallaxOrigin(const QPointF ¶llaxOrigin) void EditableMap::setOrientation(Orientation value) { if (auto doc = mapDocument()) { - push(new ChangeMapProperty(doc, static_cast(value))); + push(new ChangeMapOrientation(doc, static_cast(value))); } else if (!checkReadOnly()) { map()->setOrientation(static_cast(value)); mRenderer.reset(); @@ -578,7 +578,7 @@ void EditableMap::setOrientation(Orientation value) void EditableMap::setRenderOrder(RenderOrder value) { if (auto doc = mapDocument()) - push(new ChangeMapProperty(doc, static_cast(value))); + push(new ChangeMapRenderOrder(doc, static_cast(value))); else if (!checkReadOnly()) map()->setRenderOrder(static_cast(value)); } @@ -586,7 +586,7 @@ void EditableMap::setRenderOrder(RenderOrder value) void EditableMap::setBackgroundColor(const QColor &value) { if (auto doc = mapDocument()) - push(new ChangeMapProperty(doc, value)); + push(new ChangeMapBackgroundColor(doc, value)); else if (!checkReadOnly()) map()->setBackgroundColor(value); } @@ -594,7 +594,7 @@ void EditableMap::setBackgroundColor(const QColor &value) void EditableMap::setLayerDataFormat(LayerDataFormat value) { if (auto doc = mapDocument()) - push(new ChangeMapProperty(doc, static_cast(value))); + push(new ChangeMapLayerDataFormat(doc, static_cast(value))); else if (!checkReadOnly()) map()->setLayerDataFormat(static_cast(value)); } diff --git a/src/tiled/fileedit.cpp b/src/tiled/fileedit.cpp index e6804e999b..5e1b09e266 100644 --- a/src/tiled/fileedit.cpp +++ b/src/tiled/fileedit.cpp @@ -45,7 +45,7 @@ FileEdit::FileEdit(QWidget *parent) mOkTextColor = mLineEdit->palette().color(QPalette::Active, QPalette::Text); QToolButton *button = new QToolButton(this); - button->setText(QLatin1String("...")); + button->setText(QStringLiteral("…")); button->setAutoRaise(true); button->setToolTip(tr("Choose")); layout->addWidget(mLineEdit); diff --git a/src/tiled/layerdock.cpp b/src/tiled/layerdock.cpp index 4810d0367d..f6dd6b3abc 100644 --- a/src/tiled/layerdock.cpp +++ b/src/tiled/layerdock.cpp @@ -29,7 +29,6 @@ #include "map.h" #include "mapdocument.h" #include "mapdocumentactionhandler.h" -#include "objectgroup.h" #include "reversingproxymodel.h" #include "utils.h" #include "iconcheckdelegate.h" @@ -39,10 +38,8 @@ #include #include #include -#include #include #include -#include #include #include #include @@ -54,8 +51,6 @@ using namespace Tiled; LayerDock::LayerDock(QWidget *parent): QDockWidget(parent), - mOpacityLabel(new QLabel), - mOpacitySlider(new QSlider(Qt::Horizontal)), mLayerView(new LayerView) { setObjectName(QLatin1String("layerDock")); @@ -64,13 +59,6 @@ LayerDock::LayerDock(QWidget *parent): QVBoxLayout *layout = new QVBoxLayout(widget); layout->setContentsMargins(0, 0, 0, 0); - QHBoxLayout *opacityLayout = new QHBoxLayout; - mOpacitySlider->setRange(0, 100); - mOpacitySlider->setEnabled(false); - opacityLayout->addWidget(mOpacityLabel); - opacityLayout->addWidget(mOpacitySlider); - mOpacityLabel->setBuddy(mOpacitySlider); - MapDocumentActionHandler *handler = MapDocumentActionHandler::instance(); QMenu *newLayerMenu = handler->createNewLayerMenu(this); @@ -99,20 +87,12 @@ LayerDock::LayerDock(QWidget *parent): buttonContainer->addWidget(spacerWidget); buttonContainer->addAction(ActionManager::action("HighlightCurrentLayer")); - QVBoxLayout *listAndToolBar = new QVBoxLayout; - listAndToolBar->setSpacing(0); - listAndToolBar->addWidget(mLayerView); - listAndToolBar->addWidget(buttonContainer); - - layout->addLayout(opacityLayout); - layout->addLayout(listAndToolBar); + layout->setSpacing(0); + layout->addWidget(mLayerView); + layout->addWidget(buttonContainer); setWidget(widget); retranslateUi(); - - connect(mOpacitySlider, &QAbstractSlider::valueChanged, - this, &LayerDock::sliderValueChanged); - updateOpacitySlider(); } void LayerDock::setMapDocument(MapDocument *mapDocument) @@ -126,10 +106,6 @@ void LayerDock::setMapDocument(MapDocument *mapDocument) mMapDocument = mapDocument; if (mMapDocument) { - connect(mMapDocument, &MapDocument::changed, - this, &LayerDock::documentChanged); - connect(mMapDocument, &MapDocument::currentLayerChanged, - this, &LayerDock::updateOpacitySlider); connect(mMapDocument, &MapDocument::editLayerNameRequested, this, &LayerDock::editLayerName); } @@ -145,8 +121,6 @@ void LayerDock::setMapDocument(MapDocument *mapDocument) mLayerView->header()->resizeSection(1, iconSectionWidth); mLayerView->header()->resizeSection(2, iconSectionWidth); } - - updateOpacitySlider(); } void LayerDock::changeEvent(QEvent *e) @@ -162,40 +136,6 @@ void LayerDock::changeEvent(QEvent *e) } } -void LayerDock::updateOpacitySlider() -{ - const bool enabled = mMapDocument && - mMapDocument->currentLayer() != nullptr; - - mOpacitySlider->setEnabled(enabled); - mOpacityLabel->setEnabled(enabled); - - QScopedValueRollback updating(mUpdatingSlider, true); - if (enabled) { - qreal opacity = mMapDocument->currentLayer()->opacity(); - mOpacitySlider->setValue(qRound(opacity * 100)); - } else { - mOpacitySlider->setValue(100); - } -} - -void LayerDock::documentChanged(const ChangeEvent &change) -{ - switch (change.type) { - case ChangeEvent::LayerChanged: { - auto &layerChange = static_cast(change); - - // Don't update the slider when we're the ones changing the layer opacity - if ((layerChange.properties & LayerChangeEvent::OpacityProperty) && !mChangingLayerOpacity) - if (layerChange.layer == mMapDocument->currentLayer()) - updateOpacitySlider(); - break; - } - default: - break; - } -} - void LayerDock::editLayerName() { if (!isVisible()) @@ -208,33 +148,9 @@ void LayerDock::editLayerName() mLayerView->editLayerModelIndex(layerModel->index(currentLayer)); } -void LayerDock::sliderValueChanged(int opacity) -{ - if (!mMapDocument) - return; - - // When the slider changes value just because we're updating it, it - // shouldn't try to set the layer opacity. - if (mUpdatingSlider) - return; - - const auto layer = mMapDocument->currentLayer(); - if (!layer) - return; - - if (static_cast(layer->opacity() * 100) != opacity) { - LayerModel *layerModel = mMapDocument->layerModel(); - QScopedValueRollback updating(mChangingLayerOpacity, true); - layerModel->setData(layerModel->index(layer), - qreal(opacity) / 100, - LayerModel::OpacityRole); - } -} - void LayerDock::retranslateUi() { setWindowTitle(tr("Layers")); - mOpacityLabel->setText(tr("Opacity:")); mNewLayerButton->setToolTip(tr("New Layer")); } diff --git a/src/tiled/layerdock.h b/src/tiled/layerdock.h index 41e286c530..2b1692750d 100644 --- a/src/tiled/layerdock.h +++ b/src/tiled/layerdock.h @@ -28,9 +28,7 @@ #include class QAbstractProxyModel; -class QLabel; class QModelIndex; -class QUndoStack; namespace Tiled { @@ -58,20 +56,13 @@ class LayerDock : public QDockWidget void changeEvent(QEvent *e) override; private: - void updateOpacitySlider(); - void documentChanged(const ChangeEvent &change); void editLayerName(); - void sliderValueChanged(int opacity); void retranslateUi(); - QLabel *mOpacityLabel; - QSlider *mOpacitySlider; QToolButton *mNewLayerButton; LayerView *mLayerView; MapDocument *mMapDocument = nullptr; - bool mUpdatingSlider = false; - bool mChangingLayerOpacity = false; }; /** diff --git a/src/tiled/libtilededitor.qbs b/src/tiled/libtilededitor.qbs index b31c299cf1..a09578dc3d 100644 --- a/src/tiled/libtilededitor.qbs +++ b/src/tiled/libtilededitor.qbs @@ -7,7 +7,6 @@ DynamicLibrary { Depends { name: "libtiled" } Depends { name: "translations" } - Depends { name: "qtpropertybrowser" } Depends { name: "qtsingleapplication" } Depends { name: "Qt"; submodules: ["core", "widgets", "concurrent", "qml", "svg"]; versionAtLeast: "5.12" } Depends { name: "Qt.openglwidgets"; condition: Qt.core.versionMajor >= 6; required: false } @@ -95,9 +94,6 @@ DynamicLibrary { "actionmanager.h", "actionsearch.cpp", "actionsearch.h", - "addpropertydialog.cpp", - "addpropertydialog.h", - "addpropertydialog.ui", "addremovelayer.cpp", "addremovelayer.h", "addremovemapobject.cpp", @@ -135,7 +131,6 @@ DynamicLibrary { "changemapobject.h", "changemapobjectsorder.cpp", "changemapobjectsorder.h", - "changemapproperty.cpp", "changemapproperty.h", "changeobjectgroupproperties.cpp", "changeobjectgroupproperties.h", @@ -200,8 +195,6 @@ DynamicLibrary { "createtextobjecttool.h", "createtileobjecttool.cpp", "createtileobjecttool.h", - "custompropertieshelper.cpp", - "custompropertieshelper.h", "debugdrawitem.cpp", "debugdrawitem.h", "document.cpp", @@ -403,10 +396,12 @@ DynamicLibrary { "projectpropertiesdialog.ui", "propertiesdock.cpp", "propertiesdock.h", + "propertiesview.cpp", + "propertiesview.h", "propertieswidget.cpp", "propertieswidget.h", - "propertybrowser.cpp", - "propertybrowser.h", + "propertyeditorwidgets.cpp", + "propertyeditorwidgets.h", "propertytypeseditor.cpp", "propertytypeseditor.h", "propertytypeseditor.ui", @@ -553,10 +548,8 @@ DynamicLibrary { "undodock.h", "utils.cpp", "utils.h", - "varianteditorfactory.cpp", - "varianteditorfactory.h", - "variantpropertymanager.cpp", - "variantpropertymanager.h", + "variantmapproperty.cpp", + "variantmapproperty.h", "wangbrush.cpp", "wangbrush.h", "wangcolormodel.cpp", diff --git a/src/tiled/mapdocument.cpp b/src/tiled/mapdocument.cpp index 06ba3b6d1b..64da85f709 100644 --- a/src/tiled/mapdocument.cpp +++ b/src/tiled/mapdocument.cpp @@ -326,6 +326,9 @@ void MapDocument::setSelectedLayers(const QList &layers) mSelectedLayers = layers; emit selectedLayersChanged(); + + if (currentObject() && currentObject()->typeId() == Object::LayerType) + emit currentObjectsChanged(); } void MapDocument::switchCurrentLayer(Layer *layer) @@ -1277,8 +1280,10 @@ void MapDocument::setSelectedObjects(const QList &selectedObjects) // Make sure the current object is one of the selected ones if (!selectedObjects.isEmpty()) { if (currentObject() && currentObject()->typeId() == Object::MapObjectType) { - if (selectedObjects.contains(static_cast(currentObject()))) + if (selectedObjects.contains(static_cast(currentObject()))) { + emit currentObjectsChanged(); return; + } } setCurrentObject(selectedObjects.first()); @@ -1730,8 +1735,11 @@ void MapDocument::deselectObjects(const QList &objects) removedAboutToBeSelectedObjects += mAboutToBeSelectedObjects.removeAll(object); } - if (removedSelectedObjects > 0) + if (removedSelectedObjects > 0) { emit selectedObjectsChanged(); + if (mCurrentObject && mCurrentObject->typeId() == Object::MapObjectType) + emit currentObjectsChanged(); + } if (removedAboutToBeSelectedObjects > 0) emit aboutToBeSelectedObjectsChanged(mAboutToBeSelectedObjects); } diff --git a/src/tiled/mapdocument.h b/src/tiled/mapdocument.h index 6b44705ff8..803de30937 100644 --- a/src/tiled/mapdocument.h +++ b/src/tiled/mapdocument.h @@ -322,9 +322,9 @@ class TILED_EDITOR_EXPORT MapDocument final : public Document void mapObjectPicked(MapObject *object); /** - * Emitted when the map size or its tile size changes. + * Emitted when the map size size changes. */ - void mapChanged(); + void mapResized(); void layerAdded(Layer *layer); void layerAboutToBeRemoved(GroupLayer *parentLayer, int index); diff --git a/src/tiled/mapdocumentactionhandler.cpp b/src/tiled/mapdocumentactionhandler.cpp index 91f3c625ce..4b5b4666f0 100644 --- a/src/tiled/mapdocumentactionhandler.cpp +++ b/src/tiled/mapdocumentactionhandler.cpp @@ -24,6 +24,7 @@ #include "actionmanager.h" #include "addremovelayer.h" #include "addremovemapobject.h" +#include "changeevents.h" #include "changeselectedarea.h" #include "clipboardmanager.h" #include "documentmanager.h" @@ -297,8 +298,12 @@ void MapDocumentActionHandler::setMapDocument(MapDocument *mapDocument) this, &MapDocumentActionHandler::updateActions); connect(mapDocument, &MapDocument::selectedObjectsChanged, this, &MapDocumentActionHandler::updateActions); - connect(mapDocument, &MapDocument::mapChanged, - this, &MapDocumentActionHandler::updateActions); + connect(mapDocument, &MapDocument::changed, + this, [this] (const ChangeEvent &change) { + if (change.type == ChangeEvent::MapChanged) + if (static_cast(change).property == Map::InfiniteProperty) + updateActions(); + }); } } diff --git a/src/tiled/mapitem.cpp b/src/tiled/mapitem.cpp index 034a1c0404..27f0f1f4a9 100644 --- a/src/tiled/mapitem.cpp +++ b/src/tiled/mapitem.cpp @@ -155,7 +155,7 @@ MapItem::MapItem(const MapDocumentPtr &mapDocument, DisplayMode displayMode, connect(prefs, &Preferences::backgroundFadeColorChanged, this, [this] (QColor color) { mDarkRectangle->setBrush(color); }); connect(mapDocument.data(), &Document::changed, this, &MapItem::documentChanged); - connect(mapDocument.data(), &MapDocument::mapChanged, this, &MapItem::mapChanged); + connect(mapDocument.data(), &MapDocument::mapResized, this, &MapItem::mapChanged); connect(mapDocument.data(), &MapDocument::regionChanged, this, &MapItem::repaintRegion); connect(mapDocument.data(), &MapDocument::tileLayerChanged, this, &MapItem::tileLayerChanged); connect(mapDocument.data(), &MapDocument::layerAdded, this, &MapItem::layerAdded); @@ -391,6 +391,27 @@ void MapItem::documentChanged(const ChangeEvent &change) break; } + case ChangeEvent::MapChanged: { + auto &mapChange = static_cast(change); + switch (mapChange.property) { + case Map::TileSizeProperty: + case Map::InfiniteProperty: + case Map::HexSideLengthProperty: + case Map::StaggerAxisProperty: + case Map::StaggerIndexProperty: + case Map::ParallaxOriginProperty: + case Map::OrientationProperty: + mapChanged(); + break; + case Map::RenderOrderProperty: + case Map::BackgroundColorProperty: + case Map::LayerDataFormatProperty: + case Map::CompressionLevelProperty: + case Map::ChunkSizeProperty: + break; + } + break; + } case ChangeEvent::LayerChanged: layerChanged(static_cast(change)); break; diff --git a/src/tiled/mapscene.cpp b/src/tiled/mapscene.cpp index c87faf96b2..d9609b1d80 100644 --- a/src/tiled/mapscene.cpp +++ b/src/tiled/mapscene.cpp @@ -102,8 +102,6 @@ void MapScene::setMapDocument(MapDocument *mapDocument) if (mMapDocument) { connect(mMapDocument, &MapDocument::changed, this, &MapScene::changeEvent); - connect(mMapDocument, &MapDocument::mapChanged, - this, &MapScene::mapChanged); connect(mMapDocument, &MapDocument::tilesetTilePositioningChanged, this, [this] { update(); }); connect(mMapDocument, &MapDocument::tileImageSourceChanged, @@ -405,10 +403,19 @@ MapItem *MapScene::takeOrCreateMapItem(const MapDocumentPtr &mapDocument, MapIte void MapScene::changeEvent(const ChangeEvent &change) { switch (change.type) { - case ChangeEvent::MapChanged: - if (static_cast(change).property == Map::ParallaxOriginProperty) + case ChangeEvent::MapChanged: { + switch (static_cast(change).property) { + case Map::ParallaxOriginProperty: emit parallaxParametersChanged(); + break; + case Map::BackgroundColorProperty: + updateBackgroundColor(); + break; + default: + break; + } break; + } case ChangeEvent::TilesetChanged:{ auto &tilesetChange = static_cast(change); switch (tilesetChange.property) { @@ -424,14 +431,6 @@ void MapScene::changeEvent(const ChangeEvent &change) } } -/** - * Updates the possibly changed background color. - */ -void MapScene::mapChanged() -{ - updateBackgroundColor(); -} - void MapScene::repaintTileset(Tileset *tileset) { for (MapItem *mapItem : std::as_const(mMapItems)) { diff --git a/src/tiled/mapscene.h b/src/tiled/mapscene.h index 7eacf13290..3e81127b9d 100644 --- a/src/tiled/mapscene.h +++ b/src/tiled/mapscene.h @@ -112,7 +112,6 @@ class MapScene : public QGraphicsScene void refreshScene(); void changeEvent(const ChangeEvent &change); - void mapChanged(); void repaintTileset(Tileset *tileset); void tilesetReplaced(int index, Tileset *tileset, Tileset *oldTileset); diff --git a/src/tiled/objectrefdialog.cpp b/src/tiled/objectrefdialog.cpp index 22d5599ac2..9751b4af24 100644 --- a/src/tiled/objectrefdialog.cpp +++ b/src/tiled/objectrefdialog.cpp @@ -38,6 +38,14 @@ namespace Tiled { +MapObject *DisplayObjectRef::object() const +{ + if (!mapDocument || ref.id <= 0) + return nullptr; + return mapDocument->map()->findObjectById(ref.id); +} + + class ImmutableMapObjectProxyModel : public ReversingProxyModel { public: diff --git a/src/tiled/objectrefdialog.h b/src/tiled/objectrefdialog.h index 5959e27875..9dd39ea8a2 100644 --- a/src/tiled/objectrefdialog.h +++ b/src/tiled/objectrefdialog.h @@ -21,7 +21,6 @@ #pragma once #include "properties.h" -#include "variantpropertymanager.h" #include #include @@ -37,6 +36,25 @@ class MapDocument; class ImmutableMapObjectProxyModel; class Tile; +class DisplayObjectRef +{ +public: + explicit DisplayObjectRef(ObjectRef ref = ObjectRef(), + MapDocument *mapDocument = nullptr) + : ref(ref) + , mapDocument(mapDocument) + {} + + bool operator==(const DisplayObjectRef &o) const + { return ref.id == o.ref.id && mapDocument == o.mapDocument; } + + int id() const { return ref.id; } + MapObject *object() const; + + ObjectRef ref; + MapDocument *mapDocument; +}; + class ObjectsTreeView : public QTreeView { Q_OBJECT diff --git a/src/tiled/objectrefedit.cpp b/src/tiled/objectrefedit.cpp index 5927f4f996..f26a7060ce 100644 --- a/src/tiled/objectrefedit.cpp +++ b/src/tiled/objectrefedit.cpp @@ -23,7 +23,6 @@ #include "mapdocument.h" #include "mapobject.h" -#include "objectrefdialog.h" #include "utils.h" #include diff --git a/src/tiled/objectrefedit.h b/src/tiled/objectrefedit.h index bb518f6577..628fc640d0 100644 --- a/src/tiled/objectrefedit.h +++ b/src/tiled/objectrefedit.h @@ -20,8 +20,7 @@ #pragma once -#include "properties.h" -#include "variantpropertymanager.h" +#include "objectrefdialog.h" #include diff --git a/src/tiled/objectselectionitem.cpp b/src/tiled/objectselectionitem.cpp index 572e6650d2..3f9d9ccf91 100644 --- a/src/tiled/objectselectionitem.cpp +++ b/src/tiled/objectselectionitem.cpp @@ -29,11 +29,11 @@ #include "maprenderer.h" #include "mapscene.h" #include "objectgroup.h" +#include "objectrefdialog.h" #include "objectreferenceitem.h" #include "preferences.h" #include "tile.h" #include "utils.h" -#include "variantpropertymanager.h" #include #include @@ -280,9 +280,6 @@ ObjectSelectionItem::ObjectSelectionItem(MapDocument *mapDocument, connect(mapDocument, &MapDocument::aboutToBeSelectedObjectsChanged, this, &ObjectSelectionItem::aboutToBeSelectedObjectsChanged); - connect(mapDocument, &MapDocument::mapChanged, - this, &ObjectSelectionItem::mapChanged); - connect(mapDocument, &MapDocument::layerAdded, this, &ObjectSelectionItem::layerAdded); @@ -403,6 +400,9 @@ void ObjectSelectionItem::changeEvent(const ChangeEvent &event) } break; } + case ChangeEvent::MapChanged: + updateItemPositions(); + break; case ChangeEvent::LayerChanged: layerChanged(static_cast(event)); break; @@ -493,11 +493,6 @@ void ObjectSelectionItem::hoveredMapObjectChanged(MapObject *object, } } -void ObjectSelectionItem::mapChanged() -{ - updateItemPositions(); -} - static void collectObjects(const GroupLayer &groupLayer, QList &objects, bool onlyVisibleLayers = false) { for (Layer *layer : groupLayer) { diff --git a/src/tiled/objectselectionitem.h b/src/tiled/objectselectionitem.h index e67fbe088b..ce29bf8607 100644 --- a/src/tiled/objectselectionitem.h +++ b/src/tiled/objectselectionitem.h @@ -95,7 +95,6 @@ class ObjectSelectionItem : public QGraphicsObject void selectedObjectsChanged(); void aboutToBeSelectedObjectsChanged(); void hoveredMapObjectChanged(MapObject *object, MapObject *previous); - void mapChanged(); void layerAdded(Layer *layer); void layerAboutToBeRemoved(GroupLayer *parentLayer, int index); void layerChanged(const LayerChangeEvent &event); diff --git a/src/tiled/objectselectiontool.cpp b/src/tiled/objectselectiontool.cpp index 758eb7a113..e1b67c8c31 100644 --- a/src/tiled/objectselectiontool.cpp +++ b/src/tiled/objectselectiontool.cpp @@ -54,7 +54,6 @@ #include #include -#include using namespace Tiled; @@ -335,8 +334,10 @@ ObjectSelectionTool::ObjectSelectionTool(QObject *parent) else mSelectContained->setChecked(true); - connect(mSelectIntersected, &QAction::triggered, [this] { setSelectionMode(Qt::IntersectsItemShape); }); - connect(mSelectContained, &QAction::triggered, [this] { setSelectionMode(Qt::ContainsItemShape); }); + connect(mSelectIntersected, &QAction::triggered, + this, [this] { setSelectionMode(Qt::IntersectsItemShape); }); + connect(mSelectContained, &QAction::triggered, + this, [this] { setSelectionMode(Qt::ContainsItemShape); }); for (int i = 0; i < CornerAnchorCount; ++i) mRotateHandles[i] = new RotateHandle(static_cast(i)); @@ -366,8 +367,6 @@ void ObjectSelectionTool::activate(MapScene *scene) updateHandlesAndOrigin(); - connect(mapDocument(), &MapDocument::mapChanged, - this, &ObjectSelectionTool::updateHandlesAndOrigin); connect(mapDocument(), &MapDocument::selectedObjectsChanged, this, &ObjectSelectionTool::updateHandlesAndOrigin); connect(mapDocument(), &MapDocument::tilesetTilePositioningChanged, @@ -390,8 +389,6 @@ void ObjectSelectionTool::deactivate(MapScene *scene) for (ResizeHandle *handle : mResizeHandles) scene->removeItem(handle); - disconnect(mapDocument(), &MapDocument::mapChanged, - this, &ObjectSelectionTool::updateHandlesAndOrigin); disconnect(mapDocument(), &MapDocument::selectedObjectsChanged, this, &ObjectSelectionTool::updateHandlesAndOrigin); disconnect(mapDocument(), &MapDocument::tilesetTilePositioningChanged, @@ -779,6 +776,9 @@ void ObjectSelectionTool::changeEvent(const ChangeEvent &event) return; switch (event.type) { + case ChangeEvent::MapChanged: + updateHandlesAndOrigin(); + break; case ChangeEvent::LayerChanged: if (static_cast(event).properties & LayerChangeEvent::PositionProperties) updateHandlesAndOrigin(); diff --git a/src/tiled/pch.h b/src/tiled/pch.h index 4c2f93d024..3db4ff3c2f 100644 --- a/src/tiled/pch.h +++ b/src/tiled/pch.h @@ -40,8 +40,6 @@ #include #include -#include - // libtiled #include #include diff --git a/src/tiled/projectpropertiesdialog.cpp b/src/tiled/projectpropertiesdialog.cpp index 304abb8d85..50594027bb 100644 --- a/src/tiled/projectpropertiesdialog.cpp +++ b/src/tiled/projectpropertiesdialog.cpp @@ -24,66 +24,90 @@ #include "mapformat.h" #include "project.h" #include "projectdocument.h" -#include "varianteditorfactory.h" -#include "variantpropertymanager.h" +#include "propertiesview.h" +#include "tiled.h" +#include "utils.h" -#include +#include +#include namespace Tiled { +template<> EnumData enumData() +{ + return {{ + QCoreApplication::translate("Tiled::ProjectPropertiesDialog", "Tiled 1.8"), + QCoreApplication::translate("Tiled::ProjectPropertiesDialog", "Tiled 1.9"), + QCoreApplication::translate("Tiled::ProjectPropertiesDialog", "Tiled 1.10"), + QCoreApplication::translate("Tiled::ProjectPropertiesDialog", "Latest"), + }, { + Tiled_1_8, + Tiled_1_9, + Tiled_1_10, + Tiled_Latest, + }}; +} + ProjectPropertiesDialog::ProjectPropertiesDialog(Project &project, QWidget *parent) : QDialog(parent) , ui(new Ui::ProjectPropertiesDialog) , mProject(project) - , mPropertiesProjectDocument(new ProjectDocument(std::make_unique(), this)) + , mLocalProjectDocument(new ProjectDocument(std::make_unique(project), this)) { ui->setupUi(this); - mPropertiesProjectDocument->project().setProperties(project.properties()); - - auto variantPropertyManager = new VariantPropertyManager(this); - auto variantEditorFactory = new VariantEditorFactory(this); - auto groupPropertyManager = new QtGroupPropertyManager(this); - - ui->propertyBrowser->setFactoryForManager(variantPropertyManager, - variantEditorFactory); - - const QMap versionToName { - { Tiled_1_8, tr("Tiled 1.8") }, - { Tiled_1_9, tr("Tiled 1.9") }, - { Tiled_1_10, tr("Tiled 1.10") }, - { Tiled_Latest, tr("Latest") }, - }; - mVersions = versionToName.keys(); - - mCompatibilityVersionProperty = variantPropertyManager->addProperty(QtVariantPropertyManager::enumTypeId(), - tr("Compatibility Version")); - mCompatibilityVersionProperty->setAttribute(QLatin1String("enumNames"), - QVariant::fromValue(versionToName.values())); - mCompatibilityVersionProperty->setValue(mVersions.indexOf(project.mCompatibilityVersion)); - - mExtensionPathProperty = variantPropertyManager->addProperty(filePathTypeId(), tr("Extensions Directory")); - mExtensionPathProperty->setValue(project.mExtensionsPath); - mExtensionPathProperty->setAttribute(QStringLiteral("directory"), true); + mCompatibilityVersionProperty = new EnumProperty( + tr("Compatibility Version"), + [=] { + return localProject().mCompatibilityVersion; + }, + [=](CompatibilityVersion value) { + localProject().mCompatibilityVersion = value; + }); + + mExtensionPathProperty = new UrlProperty( + tr("Extensions Directory"), + [=] { + return QUrl::fromLocalFile(localProject().mExtensionsPath); + }, + [=](const QUrl &value) { + localProject().mExtensionsPath = value.toLocalFile(); + }); + mExtensionPathProperty->setIsDirectory(true); QString ruleFileFilter = QCoreApplication::translate("File Types", "Automapping Rules files (*.txt)"); FormatHelper helper(FileFormat::ReadWrite, std::move(ruleFileFilter)); - mAutomappingRulesFileProperty = variantPropertyManager->addProperty(filePathTypeId(), tr("Automapping rules")); - mAutomappingRulesFileProperty->setValue(project.mAutomappingRulesFile); - mAutomappingRulesFileProperty->setAttribute(QStringLiteral("filter"), helper.filter()); + mAutomappingRulesFileProperty = new UrlProperty( + tr("Automapping rules"), + [=] { + return QUrl::fromLocalFile(localProject().mAutomappingRulesFile); + }, + [=](const QUrl &value) { + localProject().mAutomappingRulesFile = value.toLocalFile(); + }); + mAutomappingRulesFileProperty->setFilter(helper.filter()); + + auto generalGroup = new QGroupBox(tr("General")); + auto generalLayout = new QFormLayout(generalGroup); + generalLayout->addRow(mCompatibilityVersionProperty->name(), mCompatibilityVersionProperty->createEditor(generalGroup)); - auto generalGroupProperty = groupPropertyManager->addProperty(tr("General")); - generalGroupProperty->addSubProperty(mCompatibilityVersionProperty); + auto filesGroup = new QGroupBox(tr("Paths && Files")); + auto filesLayout = new QFormLayout(filesGroup); + filesLayout->addRow(mExtensionPathProperty->name(), mExtensionPathProperty->createEditor(filesGroup)); + filesLayout->addRow(mAutomappingRulesFileProperty->name(), mAutomappingRulesFileProperty->createEditor(filesGroup)); - auto filesGroupProperty = groupPropertyManager->addProperty(tr("Paths && Files")); - filesGroupProperty->addSubProperty(mExtensionPathProperty); - filesGroupProperty->addSubProperty(mAutomappingRulesFileProperty); + ui->dialogLayout->insertWidget(0, filesGroup); + ui->dialogLayout->insertWidget(0, generalGroup); - ui->propertyBrowser->addProperty(generalGroupProperty); - ui->propertyBrowser->addProperty(filesGroupProperty); + // Don't display the "Custom Properties" header + ui->propertiesWidget->customPropertiesGroup()->setName(QString()); - ui->propertiesWidget->setDocument(mPropertiesProjectDocument); + // Tweak margins + const auto halfSpacing = Utils::dpiScaled(2); + ui->propertiesWidget->propertiesView()->widget()->setContentsMargins(0, halfSpacing, 0, halfSpacing); + + ui->propertiesWidget->setDocument(mLocalProjectDocument); } ProjectPropertiesDialog::~ProjectPropertiesDialog() @@ -93,14 +117,21 @@ ProjectPropertiesDialog::~ProjectPropertiesDialog() void ProjectPropertiesDialog::accept() { - mProject.setProperties(mPropertiesProjectDocument->project().properties()); - mProject.mCompatibilityVersion = mVersions.at(mCompatibilityVersionProperty->value().toInt()); - mProject.mExtensionsPath = mExtensionPathProperty->value().toString(); - mProject.mAutomappingRulesFile = mAutomappingRulesFileProperty->value().toString(); + auto &project = localProject(); + + mProject.setProperties(project.properties()); + mProject.mCompatibilityVersion = project.mCompatibilityVersion; + mProject.mExtensionsPath = project.mExtensionsPath; + mProject.mAutomappingRulesFile = project.mAutomappingRulesFile; QDialog::accept(); } +Project &ProjectPropertiesDialog::localProject() +{ + return mLocalProjectDocument->project(); +} + } // namespace Tiled #include "moc_projectpropertiesdialog.cpp" diff --git a/src/tiled/projectpropertiesdialog.h b/src/tiled/projectpropertiesdialog.h index dbfd4e59d9..5ba34f905b 100644 --- a/src/tiled/projectpropertiesdialog.h +++ b/src/tiled/projectpropertiesdialog.h @@ -20,20 +20,18 @@ #pragma once -#include "tiled.h" - #include -class QtVariantProperty; - namespace Ui { class ProjectPropertiesDialog; } namespace Tiled { +class IntProperty; class Project; class ProjectDocument; +class UrlProperty; class ProjectPropertiesDialog : public QDialog { @@ -46,14 +44,15 @@ class ProjectPropertiesDialog : public QDialog void accept() override; private: + Project &localProject(); + Ui::ProjectPropertiesDialog *ui; Project &mProject; - ProjectDocument *mPropertiesProjectDocument; - QList mVersions; - QtVariantProperty *mCompatibilityVersionProperty; - QtVariantProperty *mExtensionPathProperty; - QtVariantProperty *mAutomappingRulesFileProperty; + ProjectDocument *mLocalProjectDocument; + IntProperty *mCompatibilityVersionProperty; + UrlProperty *mExtensionPathProperty; + UrlProperty *mAutomappingRulesFileProperty; }; } // namespace Tiled diff --git a/src/tiled/projectpropertiesdialog.ui b/src/tiled/projectpropertiesdialog.ui index 899db3ac9c..1e94e909b8 100644 --- a/src/tiled/projectpropertiesdialog.ui +++ b/src/tiled/projectpropertiesdialog.ui @@ -7,25 +7,19 @@ 0 0 586 - 356 + 489 Project Properties - + - - - - - - - 0 - 1 - + + + Custom Properties - + @@ -35,22 +29,16 @@ - Qt::Horizontal + Qt::Orientation::Horizontal - QDialogButtonBox::Cancel|QDialogButtonBox::Ok + QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok - - QtGroupBoxPropertyBrowser - QWidget -
QtGroupBoxPropertyBrowser
- 1 -
Tiled::PropertiesWidget QTreeView diff --git a/src/tiled/propertiesdock.cpp b/src/tiled/propertiesdock.cpp index 36cde21f64..87d0aaad9d 100644 --- a/src/tiled/propertiesdock.cpp +++ b/src/tiled/propertiesdock.cpp @@ -20,9 +20,10 @@ #include "propertiesdock.h" +#include "propertiesview.h" #include "propertieswidget.h" -#include +#include namespace Tiled { @@ -56,6 +57,14 @@ bool PropertiesDock::event(QEvent *event) case QEvent::LanguageChange: retranslateUi(); break; + case QEvent::ShortcutOverride: + if (static_cast(event)->key() == Qt::Key_Tab) { + if (!mPropertiesWidget->propertiesView()->hasFocus()) { + event->accept(); + return true; + } + } + break; default: break; } diff --git a/src/tiled/propertiesview.cpp b/src/tiled/propertiesview.cpp new file mode 100644 index 0000000000..59b8da8feb --- /dev/null +++ b/src/tiled/propertiesview.cpp @@ -0,0 +1,1489 @@ +/* + * propertiesview.cpp + * Copyright 2024, Thorbjørn Lindeijer + * + * This file is part of Tiled. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "propertiesview.h" + +#include "colorbutton.h" +#include "fileedit.h" +#include "textpropertyedit.h" +#include "utils.h" +#include "propertyeditorwidgets.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Tiled { + +void Property::setName(const QString &name) +{ + if (m_name != name) { + m_name = name; + emit nameChanged(name); + } +} + +void Property::setToolTip(const QString &toolTip) +{ + if (m_toolTip != toolTip) { + m_toolTip = toolTip; + emit toolTipChanged(toolTip); + } +} + +void Property::setEnabled(bool enabled) +{ + if (m_enabled != enabled) { + m_enabled = enabled; + emit enabledChanged(enabled); + } +} + +void Property::setModified(bool modified) +{ + if (m_modified != modified) { + m_modified = modified; + emit modifiedChanged(modified); + } +} + +void Property::setSelected(bool selected) +{ + if (m_selected != selected) { + m_selected = selected; + emit selectedChanged(selected); + } +} + +void Property::setActions(Actions actions) +{ + if (m_actions != actions) { + m_actions = actions; + emit actionsChanged(actions); + } +} + +QWidget *Property::createLabel(int level, QWidget *parent) +{ + auto label = new PropertyLabel(parent); + label->setLevel(level); + + if (displayMode() != Property::DisplayMode::NoLabel) { + label->setText(name()); + label->setToolTip(toolTip()); + label->setModified(isModified()); + label->setSelected(isSelected()); + connect(this, &Property::nameChanged, label, &PropertyLabel::setText); + connect(this, &Property::toolTipChanged, label, &PropertyLabel::setToolTip); + connect(this, &Property::modifiedChanged, label, &PropertyLabel::setModified); + connect(this, &Property::selectedChanged, label, &PropertyLabel::setSelected); + } + + if (displayMode() == Property::DisplayMode::Header) + label->setHeader(true); + + return label; +} + +Property::DisplayMode GroupProperty::displayMode() const +{ + if (name().isEmpty()) + return DisplayMode::ChildrenOnly; + + if (m_header) + return DisplayMode::Header; + + return DisplayMode::Default; +} + +QWidget *GroupProperty::createLabel(int level, QWidget *parent) +{ + auto label = static_cast(Property::createLabel(level, parent)); + label->setExpandable(true); + label->setExpanded(isExpanded()); + + connect(this, &GroupProperty::expandedChanged, label, &PropertyLabel::setExpanded); + connect(label, &PropertyLabel::toggled, this, &GroupProperty::setExpanded); + + return label; +} + +void GroupProperty::addContextMenuActions(QMenu *menu) +{ + menu->addAction(tr("Expand All"), this, &GroupProperty::expandAll); + menu->addAction(tr("Collapse All"), this, &GroupProperty::collapseAll); +} + +void GroupProperty::setExpanded(bool expanded) +{ + if (m_expanded != expanded) { + m_expanded = expanded; + emit expandedChanged(expanded); + } +} + +void GroupProperty::expandAll() +{ + setExpanded(true); + for (auto property : std::as_const(m_subProperties)) + if (auto groupProperty = qobject_cast(property)) + groupProperty->expandAll(); +} + +void GroupProperty::collapseAll() +{ + setExpanded(false); + for (auto property : std::as_const(m_subProperties)) + if (auto groupProperty = qobject_cast(property)) + groupProperty->collapseAll(); +} + +void StringProperty::setPlaceholderText(const QString &placeholderText) +{ + if (m_placeholderText != placeholderText) { + m_placeholderText = placeholderText; + emit placeholderTextChanged(placeholderText); + } +} + +QWidget *StringProperty::createEditor(QWidget *parent) +{ + auto editor = new LineEdit(parent); + editor->setPlaceholderText(m_placeholderText); + + auto syncEditor = [=] { + // Avoid affecting cursor position when the text is the same + const QString v = value(); + if (editor->text() != v) + editor->setText(v); + }; + syncEditor(); + + connect(this, &Property::valueChanged, editor, syncEditor); + connect(this, &StringProperty::placeholderTextChanged, editor, &QLineEdit::setPlaceholderText); + connect(editor, &QLineEdit::textEdited, this, &StringProperty::setValue); + + return editor; +} + +QWidget *MultilineStringProperty::createEditor(QWidget *parent) +{ + auto editor = new TextPropertyEdit(parent); + editor->lineEdit()->setPlaceholderText(placeholderText()); + + auto syncEditor = [=] { + const QSignalBlocker blocker(editor); + editor->setText(value()); + }; + syncEditor(); + + connect(this, &StringProperty::valueChanged, editor, syncEditor); + connect(this, &StringProperty::placeholderTextChanged, + editor->lineEdit(), &QLineEdit::setPlaceholderText); + connect(editor, &TextPropertyEdit::textChanged, this, &StringProperty::setValue); + + return editor; +} + +QWidget *UrlProperty::createEditor(QWidget *parent) +{ + auto editor = new FileEdit(parent); + editor->setFilter(m_filter); + editor->setIsDirectory(m_isDirectory); + + auto syncEditor = [=] { + editor->setFileUrl(value()); + }; + syncEditor(); + + connect(this, &Property::valueChanged, editor, syncEditor); + connect(editor, &FileEdit::fileUrlChanged, this, &UrlProperty::setValue); + + return editor; +} + +void UrlProperty::addContextMenuActions(QMenu *menu) +{ + const QString localFile = value().toLocalFile(); + + if (!localFile.isEmpty()) { + Utils::addOpenContainingFolderAction(*menu, localFile); + + if (QFileInfo { localFile }.isFile()) + Utils::addOpenWithSystemEditorAction(*menu, localFile); + } +} + +QWidget *IntProperty::createEditor(QWidget *parent) +{ + auto widget = new QWidget(parent); + auto layout = new QHBoxLayout(widget); + layout->setContentsMargins(QMargins()); + + if (m_sliderEnabled) { + auto slider = new Slider(Qt::Horizontal, widget); + slider->setRange(m_minimum, m_maximum); + slider->setSingleStep(m_singleStep); + slider->setValue(value()); + + layout->addWidget(slider); + + connect(this, &Property::valueChanged, slider, [this, slider] { + const QSignalBlocker blocker(slider); + slider->setValue(value()); + }); + connect(slider, &QSlider::valueChanged, this, &IntProperty::setValue); + } + + auto spinBox = new SpinBox(parent); + spinBox->setRange(m_minimum, m_maximum); + spinBox->setSingleStep(m_singleStep); + spinBox->setSuffix(m_suffix); + spinBox->setValue(value()); + + layout->addWidget(spinBox); + + connect(this, &Property::valueChanged, spinBox, [this, spinBox] { + const QSignalBlocker blocker(spinBox); + spinBox->setValue(value()); + }); + connect(spinBox, qOverload(&SpinBox::valueChanged), + this, &IntProperty::setValue); + + return widget; +} + +QWidget *FloatProperty::createEditor(QWidget *parent) +{ + auto editor = new DoubleSpinBox(parent); + editor->setRange(m_minimum, m_maximum); + editor->setSingleStep(m_singleStep); + editor->setSuffix(m_suffix); + + auto syncEditor = [=] { + const QSignalBlocker blocker(editor); + editor->setValue(value()); + }; + syncEditor(); + + connect(this, &Property::valueChanged, editor, syncEditor); + connect(editor, qOverload(&DoubleSpinBox::valueChanged), + this, &FloatProperty::setValue); + + return editor; +} + +Property::DisplayMode BoolProperty::displayMode() const +{ + return m_nameOnCheckBox ? DisplayMode::NoLabel : DisplayMode::Default; +} + +QWidget *BoolProperty::createEditor(QWidget *parent) +{ + auto editor = new QCheckBox(name(), parent); + auto syncEditor = [=] { + const QSignalBlocker blocker(editor); + bool checked = value(); + editor->setChecked(checked); + if (!m_nameOnCheckBox) + editor->setText(checked ? tr("On") : tr("Off")); + + // Reflect modified state on the checkbox, since we're not showing the + // property label. + auto font = editor->font(); + font.setBold(isModified()); + editor->setFont(font); + + // Make sure the label remains readable when selected + auto pal = QGuiApplication::palette(); + if (isSelected()) + pal.setBrush(QPalette::WindowText, pal.brush(QPalette::HighlightedText)); + editor->setPalette(pal); + }; + syncEditor(); + + connect(this, &Property::selectedChanged, editor, syncEditor); + connect(this, &Property::valueChanged, editor, syncEditor); + connect(this, &Property::modifiedChanged, editor, syncEditor); + connect(editor, &QCheckBox::toggled, this, [=](bool checked) { + if (!m_nameOnCheckBox) + editor->setText(checked ? QObject::tr("On") : QObject::tr("Off")); + setValue(checked); + }); + + return editor; +} + +QWidget *PointProperty::createEditor(QWidget *parent) +{ + auto editor = new PointEdit(parent); + editor->setSuffix(m_suffix); + + auto syncEditor = [this, editor] { + const QSignalBlocker blocker(editor); + editor->setValue(value()); + }; + syncEditor(); + + connect(this, &Property::valueChanged, editor, syncEditor); + connect(editor, &PointEdit::valueChanged, this, [this, editor] { + setValue(editor->value()); + }); + + return editor; +} + +QWidget *PointFProperty::createEditor(QWidget *parent) +{ + auto editor = new PointFEdit(parent); + editor->setSingleStep(m_singleStep); + + auto syncEditor = [this, editor] { + const QSignalBlocker blocker(editor); + editor->setValue(value()); + }; + syncEditor(); + + connect(this, &Property::valueChanged, editor, syncEditor); + connect(editor, &PointFEdit::valueChanged, this, [this, editor] { + this->setValue(editor->value()); + }); + + return editor; +} + +QWidget *SizeProperty::createEditor(QWidget *parent) +{ + auto editor = new SizeEdit(parent); + editor->setMinimum(m_minimum); + editor->setSuffix(m_suffix); + + auto syncEditor = [this, editor] { + const QSignalBlocker blocker(editor); + editor->setValue(value()); + }; + syncEditor(); + + connect(this, &Property::valueChanged, editor, syncEditor); + connect(editor, &SizeEdit::valueChanged, this, [this, editor] { + setValue(editor->value()); + }); + + return editor; +} + +QWidget *SizeFProperty::createEditor(QWidget *parent) +{ + auto editor = new SizeFEdit(parent); + auto syncEditor = [this, editor] { + const QSignalBlocker blocker(editor); + editor->setValue(value()); + }; + syncEditor(); + + connect(this, &Property::valueChanged, editor, syncEditor); + connect(editor, &SizeFEdit::valueChanged, this, [this, editor] { + setValue(editor->value()); + }); + + return editor; +} + +QWidget *RectProperty::createEditor(QWidget *parent) +{ + auto editor = new RectEdit(parent); + editor->setConstraint(m_constraint); + + auto syncEditor = [this, editor] { + const QSignalBlocker blocker(editor); + editor->setValue(value()); + }; + syncEditor(); + + connect(this, &Property::valueChanged, editor, syncEditor); + connect(editor, &RectEdit::valueChanged, this, [this, editor] { + setValue(editor->value()); + }); + connect(this, &RectProperty::constraintChanged, + editor, &RectEdit::setConstraint); + + return editor; +} + +void RectProperty::setConstraint(const QRect &constraint) +{ + if (m_constraint != constraint) { + m_constraint = constraint; + emit constraintChanged(m_constraint); + } +} + +QWidget *RectFProperty::createEditor(QWidget *parent) +{ + auto editor = new RectFEdit(parent); + auto syncEditor = [this, editor] { + const QSignalBlocker blocker(editor); + editor->setValue(value()); + }; + syncEditor(); + + connect(this, &Property::valueChanged, editor, syncEditor); + connect(editor, &RectFEdit::valueChanged, this, [this, editor] { + setValue(editor->value()); + }); + + return editor; +} + +QWidget *ColorProperty::createEditor(QWidget *parent) +{ + auto editor = new QWidget(parent); + auto layout = new QHBoxLayout(editor); + layout->setContentsMargins(QMargins()); + layout->setSpacing(0); + + auto colorButton = new ColorButton(editor); + colorButton->setShowAlphaChannel(m_alpha); + colorButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding); + + QIcon resetIcon(QStringLiteral(":/images/16/edit-clear.png")); + resetIcon.addFile(QStringLiteral(":/images/24/edit-clear.png")); + + auto resetButton = new QToolButton(editor); + resetButton->setIcon(resetIcon); + resetButton->setToolTip(tr("Clear Color")); + resetButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::MinimumExpanding); + Utils::setThemeIcon(resetButton, "edit-clear"); + + layout->addWidget(colorButton); + layout->addWidget(resetButton); + + auto syncEditor = [=] { + const QSignalBlocker blocker(colorButton); + auto v = value(); + colorButton->setColor(v); + resetButton->setEnabled(v.isValid()); + }; + syncEditor(); + + connect(resetButton, &QToolButton::clicked, colorButton, [colorButton] { + colorButton->setColor(QColor()); + }); + connect(this, &Property::valueChanged, colorButton, syncEditor); + connect(colorButton, &ColorButton::colorChanged, this, [=] { + resetButton->setEnabled(colorButton->color().isValid()); + setValue(colorButton->color()); + }); + + editor->setFocusProxy(colorButton); + + return editor; +} + +QWidget *FontProperty::createEditor(QWidget *parent) +{ + auto editor = new QWidget(parent); + auto fontComboBox = new QFontComboBox(editor); + + auto sizeSpinBox = new QSpinBox(editor); + sizeSpinBox->setRange(1, 999); + sizeSpinBox->setSuffix(tr(" px")); + sizeSpinBox->setKeyboardTracking(false); + + auto bold = new QToolButton(editor); + bold->setIcon(QIcon(QStringLiteral("://images/scalable/text-bold-symbolic.svg"))); + bold->setToolTip(tr("Bold")); + bold->setCheckable(true); + + auto italic = new QToolButton(editor); + italic->setIcon(QIcon(QStringLiteral("://images/scalable/text-italic-symbolic.svg"))); + italic->setToolTip(tr("Italic")); + italic->setCheckable(true); + + auto underline = new QToolButton(editor); + underline->setIcon(QIcon(QStringLiteral("://images/scalable/text-underline-symbolic.svg"))); + underline->setToolTip(tr("Underline")); + underline->setCheckable(true); + + auto strikeout = new QToolButton(editor); + strikeout->setIcon(QIcon(QStringLiteral("://images/scalable/text-strikethrough-symbolic.svg"))); + strikeout->setToolTip(tr("Strikethrough")); + strikeout->setCheckable(true); + + auto kerning = new QCheckBox(tr("Kerning"), editor); + + auto layout = new QVBoxLayout(editor); + layout->setContentsMargins(QMargins()); + layout->setSpacing(Utils::dpiScaled(4)); + layout->addWidget(fontComboBox); + layout->addWidget(sizeSpinBox); + + auto buttonsLayout = new QHBoxLayout; + buttonsLayout->setContentsMargins(QMargins()); + buttonsLayout->addWidget(bold); + buttonsLayout->addWidget(italic); + buttonsLayout->addWidget(underline); + buttonsLayout->addWidget(strikeout); + buttonsLayout->addStretch(); + + layout->addLayout(buttonsLayout); + layout->addWidget(kerning); + + auto syncEditor = [=] { + const auto font = value(); + const QSignalBlocker fontBlocker(fontComboBox); + const QSignalBlocker sizeBlocker(sizeSpinBox); + const QSignalBlocker boldBlocker(bold); + const QSignalBlocker italicBlocker(italic); + const QSignalBlocker underlineBlocker(underline); + const QSignalBlocker strikeoutBlocker(strikeout); + const QSignalBlocker kerningBlocker(kerning); + fontComboBox->setCurrentFont(font); + sizeSpinBox->setValue(font.pixelSize()); + bold->setChecked(font.bold()); + italic->setChecked(font.italic()); + underline->setChecked(font.underline()); + strikeout->setChecked(font.strikeOut()); + kerning->setChecked(font.kerning()); + }; + + auto syncProperty = [=] { + auto font = fontComboBox->currentFont(); + font.setPixelSize(sizeSpinBox->value()); + font.setBold(bold->isChecked()); + font.setItalic(italic->isChecked()); + font.setUnderline(underline->isChecked()); + font.setStrikeOut(strikeout->isChecked()); + font.setKerning(kerning->isChecked()); + setValue(font); + }; + + syncEditor(); + + connect(this, &Property::valueChanged, fontComboBox, syncEditor); + connect(fontComboBox, &QFontComboBox::currentFontChanged, this, syncProperty); + connect(sizeSpinBox, qOverload(&QSpinBox::valueChanged), this, syncProperty); + connect(bold, &QAbstractButton::toggled, this, syncProperty); + connect(italic, &QAbstractButton::toggled, this, syncProperty); + connect(underline, &QAbstractButton::toggled, this, syncProperty); + connect(strikeout, &QAbstractButton::toggled, this, syncProperty); + connect(kerning, &QAbstractButton::toggled, this, syncProperty); + + return editor; +} + +QWidget *QtAlignmentProperty::createEditor(QWidget *parent) +{ + auto editor = new QWidget(parent); + auto layout = new QGridLayout(editor); + layout->setContentsMargins(QMargins()); + layout->setSpacing(Utils::dpiScaled(4)); + + auto horizontalLabel = new ElidingLabel(tr("Horizontal"), editor); + layout->addWidget(horizontalLabel, 0, 0); + + auto verticalLabel = new ElidingLabel(tr("Vertical"), editor); + layout->addWidget(verticalLabel, 1, 0); + + auto horizontalComboBox = new ComboBox(editor); + horizontalComboBox->addItem(tr("Left"), Qt::AlignLeft); + horizontalComboBox->addItem(tr("Center"), Qt::AlignHCenter); + horizontalComboBox->addItem(tr("Right"), Qt::AlignRight); + horizontalComboBox->addItem(tr("Justify"), Qt::AlignJustify); + layout->addWidget(horizontalComboBox, 0, 1); + + auto verticalComboBox = new ComboBox(editor); + verticalComboBox->addItem(tr("Top"), Qt::AlignTop); + verticalComboBox->addItem(tr("Center"), Qt::AlignVCenter); + verticalComboBox->addItem(tr("Bottom"), Qt::AlignBottom); + layout->addWidget(verticalComboBox, 1, 1); + + layout->setColumnStretch(1, 1); + + auto syncEditor = [=] { + const QSignalBlocker horizontalBlocker(horizontalComboBox); + const QSignalBlocker verticalBlocker(verticalComboBox); + const auto alignment = value(); + horizontalComboBox->setCurrentIndex(horizontalComboBox->findData(static_cast(alignment & Qt::AlignHorizontal_Mask))); + verticalComboBox->setCurrentIndex(verticalComboBox->findData(static_cast(alignment & Qt::AlignVertical_Mask))); + }; + + auto syncProperty = [=] { + setValue(Qt::Alignment(horizontalComboBox->currentData().toInt() | + verticalComboBox->currentData().toInt())); + }; + + syncEditor(); + + connect(this, &Property::valueChanged, editor, syncEditor); + connect(horizontalComboBox, qOverload(&QComboBox::currentIndexChanged), this, syncProperty); + connect(verticalComboBox, qOverload(&QComboBox::currentIndexChanged), this, syncProperty); + + return editor; +} + +QWidget *BaseEnumProperty::createEnumEditor(QWidget *parent) +{ + auto editor = new ComboBox(parent); + + for (qsizetype i = 0; i < m_enumData.names.size(); ++i) { + auto value = m_enumData.values.value(i, i); + editor->addItem(m_enumData.icons[value], + m_enumData.names[i], + value); + } + + auto syncEditor = [this, editor] { + const QSignalBlocker blocker(editor); + editor->setCurrentIndex(editor->findData(value())); + }; + syncEditor(); + + QObject::connect(this, &Property::valueChanged, editor, syncEditor); + QObject::connect(editor, qOverload(&QComboBox::currentIndexChanged), this, + [editor, this] { + setValue(editor->currentData().toInt()); + }); + + return editor; +} + +QWidget *BaseEnumProperty::createFlagsEditor(QWidget *parent) +{ + auto editor = new QWidget(parent); + auto layout = new QVBoxLayout(editor); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + + for (qsizetype i = 0; i < m_enumData.names.size(); ++i) { + auto checkBox = new QCheckBox(m_enumData.names[i], editor); + layout->addWidget(checkBox); + + QObject::connect(checkBox, &QCheckBox::toggled, this, [=](bool checked) { + const auto enumItemValue = m_enumData.values.value(i, 1 << i); + int flags = value(); + if (checked) + flags |= enumItemValue; + else + flags &= ~enumItemValue; + setValue(flags); + }); + } + + auto syncEditor = [=] { + for (int i = 0; i < layout->count(); ++i) { + auto checkBox = qobject_cast(layout->itemAt(i)->widget()); + if (checkBox) { + const auto enumItemValue = m_enumData.values.value(i, 1 << i); + + QSignalBlocker blocker(checkBox); + checkBox->setChecked((value() & enumItemValue) == enumItemValue); + } + } + }; + + syncEditor(); + + QObject::connect(this, &Property::valueChanged, editor, syncEditor); + + return editor; +} + +/** + * Creates a property that wraps a QObject property. + */ +Property *createQObjectProperty(QObject *qObject, + const char *propertyName, + const QString &displayName) +{ + auto metaObject = qObject->metaObject(); + auto propertyIndex = metaObject->indexOfProperty(propertyName); + if (propertyIndex < 0) + return nullptr; + + auto metaProperty = metaObject->property(propertyIndex); + auto property = createVariantProperty( + displayName.isEmpty() ? QString::fromUtf8(propertyName) + : displayName, + [=] { + return metaProperty.read(qObject); + }, + [=] (const QVariant &value) { + metaProperty.write(qObject, value); + }); + + // If the property has a notify signal, forward it to valueChanged + auto notify = metaProperty.notifySignal(); + if (notify.isValid()) { + auto propertyMetaObject = property->metaObject(); + auto valuePropertyIndex = propertyMetaObject->indexOfProperty("value"); + auto valueProperty = propertyMetaObject->property(valuePropertyIndex); + auto valueChanged = valueProperty.notifySignal(); + + QObject::connect(qObject, notify, property, valueChanged); + } + + property->setEnabled(metaProperty.isWritable()); + + return property; +} + +template +Property *createTypedProperty(const QString &name, + std::function get, + std::function set) +{ + return new PropertyClass(name, + [get = std::move(get)] { return get().value(); }, + [set = std::move(set)] (const typename PropertyClass::ValueType &v) { set(QVariant::fromValue(v)); }); +} + +/** + * Creates a property with the given name and get/set functions. The + * value type determines the kind of property that will be created. + */ +Property *createVariantProperty(const QString &name, + std::function get, + std::function set) +{ + const auto type = get().userType(); + switch (type) { + case QMetaType::QString: + return createTypedProperty(name, get, set); + case QMetaType::QUrl: + return createTypedProperty(name, get, set); + case QMetaType::Int: + return createTypedProperty(name, get, set); + case QMetaType::Double: + return createTypedProperty(name, get, set); + case QMetaType::Bool: + return createTypedProperty(name, get, set); + case QMetaType::QColor: + return createTypedProperty(name, get, set); + case QMetaType::QFont: + return createTypedProperty(name, get, set); + case QMetaType::QPoint: + return createTypedProperty(name, get, set); + case QMetaType::QPointF: + return createTypedProperty(name, get, set); + case QMetaType::QRect: + return createTypedProperty(name, get, set); + case QMetaType::QRectF: + return createTypedProperty(name, get, set); + case QMetaType::QSize: + return createTypedProperty(name, get, set); + case QMetaType::QSizeF: + return createTypedProperty(name, get, set); + default: + if (type == qMetaTypeId()) + return createTypedProperty(name, get, set); + } + + return nullptr; +} + + +PropertiesView::PropertiesView(QWidget *parent) + : QScrollArea(parent) + , m_resetIcon(QIcon(QStringLiteral(":/images/16/edit-clear.png"))) + , m_removeIcon(QIcon(QStringLiteral(":/images/16/remove.png"))) + , m_addIcon(QIcon(QStringLiteral(":/images/16/add.png"))) + , m_rootLayout(new QVBoxLayout) +{ + m_resetIcon.addFile(QStringLiteral(":/images/24/edit-clear.png")); + m_removeIcon.addFile(QStringLiteral(":/images/22/remove.png")); + m_addIcon.addFile(QStringLiteral(":/images/22/add.png")); + + auto scrollWidget = new QWidget(this); + scrollWidget->setBackgroundRole(QPalette::AlternateBase); + scrollWidget->setMinimumWidth(Utils::dpiScaled(120)); + + auto verticalLayout = new QVBoxLayout(scrollWidget); + verticalLayout->addLayout(m_rootLayout); + verticalLayout->addStretch(); + verticalLayout->setContentsMargins(QMargins()); + verticalLayout->setSpacing(0); + + setWidgetResizable(true); + setWidget(scrollWidget); +} + +/** + * Sets the root property. + * + * The view does not take ownership of the property. + */ +void PropertiesView::setRootProperty(GroupProperty *root) +{ + if (m_root == root) + return; + + QHashIterator it(m_propertyWidgets); + while (it.hasNext()) + it.next().key()->disconnect(this); + m_propertyWidgets.clear(); + + Utils::deleteAllFromLayout(m_rootLayout); + + m_root = root; + + if (root) + createPropertyWidgets(root, widget(), 0, m_rootLayout, 0); +} + +static Property *nextProperty(Property *property) +{ + if (auto groupProperty = qobject_cast(property)) + if (groupProperty->isExpanded() && !groupProperty->subProperties().isEmpty()) + return groupProperty->subProperties().first(); + + while (auto parent = property->parentProperty()) { + const int index = parent->indexOfProperty(property); + if (index < parent->subProperties().size() - 1) + return parent->subProperties().at(index + 1); + + property = parent; + } + + return nullptr; +} + +static Property *previousProperty(Property *property) +{ + auto parent = property->parentProperty(); + if (!parent) + return nullptr; + + const int index = parent->indexOfProperty(property); + if (index > 0) { + auto previous = parent->subProperties().at(index - 1); + while (auto groupProperty = qobject_cast(previous)) { + if (groupProperty->isExpanded() && !groupProperty->subProperties().isEmpty()) + previous = groupProperty->subProperties().last(); + else + break; + } + return previous; + } + + return parent; +} + +static void collectSelectedProperties(GroupProperty *groupProperty, + QList &selected) +{ + for (auto property : groupProperty->subProperties()) { + if (property->isSelected()) + selected.append(property); + if (auto childGroup = qobject_cast(property)) + collectSelectedProperties(childGroup, selected); + } +} + +static bool assignSelectedProperties(GroupProperty *groupProperty, + const QList &selected) +{ + bool changed = false; + + for (auto property : groupProperty->subProperties()) { + const bool isSelected = selected.contains(property); + changed |= isSelected != property->isSelected(); + + property->setSelected(isSelected); + + if (auto childGroup = qobject_cast(property)) + changed |= assignSelectedProperties(childGroup, selected); + } + + return changed; +} + +static bool assignSelectedPropertiesRange(GroupProperty *root, + Property *a, + Property *b) +{ + bool changed = false; + bool selected = false; + Property *end = nullptr; + + for (Property *cur = root; cur; cur = nextProperty(cur)) { + if (!end) { + if (cur == a) { + end = b; + selected = true; + } else if (cur == b) { + end = a; + selected = true; + } + } + if (cur->actions().testFlag(Property::Action::Select)) { + changed |= selected != cur->isSelected(); + cur->setSelected(selected); + } + if (cur == end) + selected = false; + } + + return changed; +} + +QList PropertiesView::selectedProperties() const +{ + QList selected; + if (m_root) + collectSelectedProperties(m_root, selected); + return selected; +} + +void PropertiesView::setSelectedProperties(const QList &properties) +{ + if (m_root && assignSelectedProperties(m_root, properties)) + emit selectedPropertiesChanged(); +} + +bool PropertiesView::focusProperty(Property *property, FocusTarget target) +{ + if (!property || !m_root) + return false; + + const auto displayMode = property->displayMode(); + if (displayMode == Property::DisplayMode::Separator || + displayMode == Property::DisplayMode::ChildrenOnly) + return false; + + auto widget = focusPropertyImpl(m_root, property, target); + if (!widget) + return false; + + if (widget->isVisible()) { + const int margin = Utils::dpiScaled(10); + ensureWidgetVisible(widget, margin, margin); + } else { + // Install event filter to detect when widget becomes visible + widget->installEventFilter(this); + } + + return true; +} + +Property *PropertiesView::focusedProperty() const +{ + auto propertyWidget = qobject_cast(focusWidget()); + return propertyWidget ? propertyWidget->property() : nullptr; +} + +bool PropertiesView::eventFilter(QObject *watched, QEvent *event) +{ + if (event->type() == QEvent::Show) { + if (QPointer widget = qobject_cast(watched)) { + // Schedule after all pending events including layout + QMetaObject::invokeMethod(this, [=] { + if (widget) { + const int margin = Utils::dpiScaled(10); + ensureWidgetVisible(widget, margin, margin); + } + }, Qt::QueuedConnection); + widget->removeEventFilter(this); + } + } + return QScrollArea::eventFilter(watched, event); +} + +void PropertiesView::mousePressEvent(QMouseEvent *event) +{ + // If the view gets mouse press then no PropertyWidget was clicked + if (event->modifiers() == Qt::NoModifier) + setSelectedProperties({}); + + QScrollArea::mousePressEvent(event); +} + +void PropertiesView::keyPressEvent(QKeyEvent *event) +{ + auto property = focusedProperty(); + const auto key = event->key(); + const bool shiftPressed = event->modifiers() & Qt::ShiftModifier; + + auto focusAndSelect = [=] (Property *property) { + if (focusProperty(property, FocusRow)) + setSelectedProperties({ property }); + }; + + switch (key) { + case Qt::Key_Down: + if (focusNextPrevProperty(property, true, shiftPressed)) + return; + break; + case Qt::Key_Up: + if (focusNextPrevProperty(property, false, shiftPressed)) + return; + break; + + case Qt::Key_Left: + case Qt::Key_Right: + case Qt::Key_Plus: + case Qt::Key_Minus: + if (auto groupProperty = qobject_cast(property)) { + const bool expand = + key == Qt::Key_Plus || + key == (isLeftToRight() ? Qt::Key_Right : Qt::Key_Left); + + if (expand) { + if (event->modifiers() & Qt::ControlModifier) { + groupProperty->expandAll(); + } else if (groupProperty->isExpanded() && key != Qt::Key_Plus) { + // If already expanded, focus first child + if (!groupProperty->subProperties().isEmpty()) + focusNextPrevProperty(groupProperty, true, shiftPressed); + } else { + groupProperty->setExpanded(true); + } + } else { + if (event->modifiers() & Qt::ControlModifier) { + groupProperty->collapseAll(); + } else if (!groupProperty->isExpanded() && key != Qt::Key_Minus) { + // If already collapsed, focus parent + focusAndSelect(groupProperty->parentProperty()); + } else { + groupProperty->setExpanded(false); + } + } + } else if (key == Qt::Key_Left || key == Qt::Key_Right) { + const bool focusParent = (key == Qt::Key_Left) ^ isRightToLeft(); + if (focusParent && property) + focusAndSelect(property->parentProperty()); + } + return; + + case Qt::Key_Asterisk: + if (auto groupProperty = qobject_cast(property)) + groupProperty->expandAll(); + return; + } + + QScrollArea::keyPressEvent(event); +} + +bool PropertiesView::focusNextPrevProperty(Property *property, bool next, bool shiftPressed) +{ + if (!property) + return false; + + const auto nextPrev = next ? nextProperty : previousProperty; + + while (Property *propertyToFocus = nextPrev(property)) { + switch (propertyToFocus->displayMode()) { + case Property::DisplayMode::Default: + case Property::DisplayMode::NoLabel: + case Property::DisplayMode::Header: + if (focusProperty(propertyToFocus, FocusRow)) { + if (!shiftPressed) { + m_selectionStart = propertyToFocus; + + if (propertyToFocus->actions().testFlag(Property::Action::Select)) + setSelectedProperties({ propertyToFocus }); + else + setSelectedProperties({}); + } else { + if (assignSelectedPropertiesRange(m_root, m_selectionStart, propertyToFocus)) + emit selectedPropertiesChanged(); + } + + return true; + } + return false; + case Property::DisplayMode::Separator: + case Property::DisplayMode::ChildrenOnly: + break; + } + + property = propertyToFocus; + } + + return false; +} + +void PropertiesView::deletePropertyWidgets(Property *property) +{ + auto it = m_propertyWidgets.constFind(property); + Q_ASSERT(it != m_propertyWidgets.constEnd()); + + if (it == m_propertyWidgets.constEnd()) + return; + + // Immediately remove from layout, but delete later to avoid deleting + // widgets while they are still handling events. + auto rowWidget = it.value().rowWidget; + + QWidget *widget = rowWidget->parentWidget(); + QLayout *layout = widget->layout(); + layout->removeWidget(rowWidget); + + rowWidget->deleteLater(); + + forgetProperty(property); + + // This appears to be necessary to avoid flickering due to relayouting + // not being done before the next paint. + while (widget && widget->layout()) { + widget->layout()->activate(); + widget = widget->parentWidget(); + } +} + +void PropertiesView::forgetProperty(Property *property) +{ + m_propertyWidgets.remove(property); + + if (property == m_selectionStart) + m_selectionStart = nullptr; + + property->disconnect(this); + + if (GroupProperty *groupProperty = qobject_cast(property)) { + for (auto subProperty : groupProperty->subProperties()) + forgetProperty(subProperty); + } +} + +/** + * Focuses the editor or label for the given property. Makes sure any parent + * group properties are expanded. + * + * When the given property is a group property, the group property is expanded + * and the first child property is focused. + * + * Returns the focused widget or nullptr if the property was not found. + */ +QWidget *PropertiesView::focusPropertyImpl(GroupProperty *group, + Property *property, + FocusTarget target) +{ + for (auto subProperty : group->subProperties()) { + auto widgetsIt = m_propertyWidgets.find(subProperty); + if (widgetsIt == m_propertyWidgets.end()) + continue; + + auto &widgets = *widgetsIt; + + if (subProperty == property) { + if (target == PropertiesView::FocusRow) { + widgets.rowWidget->setFocus(); + return widgets.rowWidget->focusWidget(); + } + if (target == PropertiesView::FocusEditor && widgets.editor) { + widgets.editor->setFocus(); + return widgets.editor; + } + if (target == PropertiesView::FocusLabel && widgets.label) { + widgets.label->setFocus(); + return widgets.label; + } + if (auto groupProperty = qobject_cast(subProperty)) { + groupProperty->setExpanded(true); + if (widgets.children && !groupProperty->subProperties().isEmpty()) + focusPropertyImpl(groupProperty, groupProperty->subProperties().first(), target); + return widgets.children; + } + return nullptr; + } else if (auto groupProperty = qobject_cast(subProperty)) { + if (widgets.children) { + if (auto w = focusPropertyImpl(groupProperty, property, target)) { + groupProperty->setExpanded(true); + return w; + } + } + } + } + + return nullptr; +} + +void PropertiesView::createPropertyWidgets(Property *property, QWidget *parent, int level, + QVBoxLayout *layout, int index) +{ + auto widgets = createPropertyWidgets(property, parent, level); + m_propertyWidgets.insert(property, widgets); + layout->insertWidget(index, widgets.rowWidget); +} + +PropertiesView::PropertyWidgets PropertiesView::createPropertyWidgets(Property *property, + QWidget *parent, + int level) +{ + Q_ASSERT(!m_propertyWidgets.contains(property)); + + PropertyWidgets widgets; + widgets.level = level; + + const auto displayMode = property->displayMode(); + + if (displayMode == Property::DisplayMode::ChildrenOnly) { + QWidget *children; + if (auto groupProperty = qobject_cast(property)) + children = createChildrenWidget(groupProperty, parent, level); + else + children = new QWidget(parent); + + widgets.children = children; + widgets.rowWidget = children; + return widgets; + } + + const auto halfSpacing = Utils::dpiScaled(2); + + if (displayMode == Property::DisplayMode::Separator) { + auto rowWidget = new QWidget(parent); + auto rowLayout = new QHBoxLayout(rowWidget); + + auto separator = new QFrame(rowWidget); + rowLayout->setContentsMargins(0, halfSpacing, 0, halfSpacing); + separator->setFrameShape(QFrame::HLine); + separator->setFrameShadow(QFrame::Plain); + separator->setForegroundRole(QPalette::Mid); + rowLayout->addWidget(separator); + + widgets.rowWidget = rowWidget; + return widgets; + } + + auto rowWidget = new PropertyWidget(property, parent); + auto rowLayout = new QHBoxLayout(rowWidget); + + widgets.rowWidget = rowWidget; + + rowLayout->setSpacing(halfSpacing * 2); + rowLayout->setContentsMargins(0, 0, 0, 0); + + rowWidget->setSelectable(property->actions().testFlag(Property::Action::Select)); + + connect(rowWidget, &PropertyWidget::mousePressed, this, [=](Qt::MouseButton button, Qt::KeyboardModifiers modifiers) { + if (modifiers & Qt::ShiftModifier) { + // Select range between m_selectionStart and clicked property + if (assignSelectedPropertiesRange(m_root, m_selectionStart, property)) + emit selectedPropertiesChanged(); + return; + } else if (modifiers & Qt::ControlModifier) { + // Toggle selection + if (property->actions().testFlag(Property::Action::Select)) { + property->setSelected(!property->isSelected()); + emit selectedPropertiesChanged(); + } + } else { + // Select only the clicked property + if (property->actions().testFlag(Property::Action::Select)) { + if (button == Qt::LeftButton || !property->isSelected()) + setSelectedProperties({property}); + } else { + setSelectedProperties({}); + } + } + + m_selectionStart = property; + }); + + widgets.label = property->createLabel(level, rowWidget); // todo: fix level + + if (displayMode != Property::DisplayMode::Header) { + if (isLeftToRight()) + rowLayout->setContentsMargins(0, halfSpacing, halfSpacing * 2, halfSpacing); + else + rowLayout->setContentsMargins(halfSpacing * 2, halfSpacing, 0, halfSpacing); + } + + if (widgets.label) + rowLayout->addWidget(widgets.label, LabelStretch, Qt::AlignTop); + + auto editorLayout = new QHBoxLayout; + widgets.editor = property->createEditor(rowWidget); + + if (widgets.editor) { + widgets.editor->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); + editorLayout->addWidget(widgets.editor, EditorStretch, Qt::AlignTop); + rowLayout->addLayout(editorLayout, EditorStretch); + } else { + rowLayout->addLayout(editorLayout, 0); + } + + widgets.resetButton = new QToolButton(rowWidget); + widgets.resetButton->setToolTip(tr("Reset")); + widgets.resetButton->setIcon(m_resetIcon); + widgets.resetButton->setAutoRaise(true); + widgets.resetButton->setEnabled(property->isModified()); + Utils::setThemeIcon(widgets.resetButton, "edit-clear"); + editorLayout->addWidget(widgets.resetButton, 0, Qt::AlignTop); + connect(widgets.resetButton, &QAbstractButton::clicked, property, &Property::resetRequested); + connect(property, &Property::modifiedChanged, widgets.resetButton, &QWidget::setEnabled); + + widgets.removeButton = new QToolButton(rowWidget); + widgets.removeButton->setToolTip(tr("Remove")); + widgets.removeButton->setIcon(m_removeIcon); + widgets.removeButton->setAutoRaise(true); + Utils::setThemeIcon(widgets.removeButton, "remove"); + editorLayout->addWidget(widgets.removeButton, 0, Qt::AlignTop); + connect(widgets.removeButton, &QAbstractButton::clicked, property, &Property::removeRequested); + + widgets.addButton = new QToolButton(rowWidget); + widgets.addButton->setToolTip(tr("Add")); + widgets.addButton->setIcon(m_addIcon); + widgets.addButton->setAutoRaise(true); + widgets.addButton->setFocusPolicy(Qt::StrongFocus); // needed for AddValueProperty + Utils::setThemeIcon(widgets.addButton, "add"); + editorLayout->addWidget(widgets.addButton, 0, Qt::AlignTop); + connect(widgets.addButton, &QAbstractButton::clicked, property, &Property::addRequested); + + if (auto groupProperty = qobject_cast(property)) { + auto containerWidget = new QWidget(parent); + containerWidget->setFocusProxy(rowWidget); + + auto containerLayout = new QVBoxLayout(containerWidget); + containerLayout->setContentsMargins(0, 0, 0, 0); + containerLayout->setSpacing(halfSpacing); + containerLayout->addWidget(rowWidget); + + connect(groupProperty, &GroupProperty::expandedChanged, this, [=](bool expanded) { + // Need to operate on a copy, because the reference might get invalidated + PropertyWidgets widgets = m_propertyWidgets.value(groupProperty); + setPropertyChildrenExpanded(widgets, groupProperty, containerLayout, expanded); + m_propertyWidgets.insert(groupProperty, widgets); + }); + + setPropertyChildrenExpanded(widgets, groupProperty, containerLayout, groupProperty->isExpanded()); + + widgets.rowWidget = containerWidget; + } + + updatePropertyEnabled(widgets, property->isEnabled()); + updatePropertyActions(widgets, property->actions()); + + connect(property, &Property::enabledChanged, this, [=] (bool enabled) { + updatePropertyEnabled(m_propertyWidgets[property], enabled); + }); + connect(property, &Property::actionsChanged, this, [=] (Property::Actions actions) { + updatePropertyActions(m_propertyWidgets[property], actions); + }); + + return widgets; +} + +QWidget *PropertiesView::createChildrenWidget(GroupProperty *groupProperty, + QWidget *parent, int level) +{ + auto children = new QWidget(parent); + children->setEnabled(groupProperty->isEnabled()); + children->setBackgroundRole((level % 2) ? QPalette::Base + : QPalette::AlternateBase); + children->setAutoFillBackground(level > 0); + + auto layout = new QVBoxLayout(children); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + + connect(groupProperty, &Property::enabledChanged, + children, &QWidget::setEnabled); + + for (auto property : groupProperty->subProperties()) + createPropertyWidgets(property, children, level, layout, layout->count()); + + connect(groupProperty, &GroupProperty::propertyAdded, + this, [=](int index, Property *property) { + createPropertyWidgets(property, children, level, layout, index); + }); + + connect(groupProperty, &GroupProperty::propertyRemoved, + this, &PropertiesView::deletePropertyWidgets); + + return children; +} + +void PropertiesView::setPropertyChildrenExpanded(PropertyWidgets &widgets, + GroupProperty *groupProperty, + QVBoxLayout *rowVerticalLayout, + bool expanded) +{ + // Create the children editor on-demand + if (expanded && !widgets.children) { + const auto displayMode = groupProperty->displayMode(); + const auto level = displayMode == Property::DisplayMode::Default ? widgets.level + 1 + : widgets.level; + + widgets.children = createChildrenWidget(groupProperty, widgets.rowWidget, level); + + const auto halfSpacing = Utils::dpiScaled(2); + const auto top = displayMode == Property::DisplayMode::Header ? 0 : halfSpacing; + const auto bottom = halfSpacing; + widgets.children->setContentsMargins(0, top, 0, bottom); + + rowVerticalLayout->addWidget(widgets.children); + } + + if (widgets.children) { + widgets.children->setVisible(expanded); + + // needed to avoid flickering when hiding the editor + if (!expanded) { + QWidget *widget = widgets.rowWidget; + while (widget && widget->layout()) { + widget->layout()->activate(); + widget = widget->parentWidget(); + } + } + } +} + +void PropertiesView::updatePropertyEnabled(const PropertyWidgets &widgets, bool enabled) +{ + if (widgets.label) + widgets.label->setEnabled(enabled); + if (widgets.editor) + widgets.editor->setEnabled(enabled); + if (widgets.children) + widgets.children->setEnabled(enabled); +} + +void PropertiesView::updatePropertyActions(const PropertyWidgets &widgets, + Property::Actions actions) +{ + if (auto rowWidget = qobject_cast(widgets.rowWidget)) + rowWidget->setSelectable(actions.testFlag(Property::Action::Select)); + + widgets.resetButton->setVisible(actions.testFlag(Property::Action::Reset)); + widgets.removeButton->setVisible(actions.testFlag(Property::Action::Remove)); + widgets.addButton->setVisible(actions.testFlag(Property::Action::Add)); + + widgets.addButton->setEnabled(!actions.testFlag(Property::Action::AddDisabled)); +} + +} // namespace Tiled + +#include "moc_propertiesview.cpp" diff --git a/src/tiled/propertiesview.h b/src/tiled/propertiesview.h new file mode 100644 index 0000000000..58f1ddffac --- /dev/null +++ b/src/tiled/propertiesview.h @@ -0,0 +1,610 @@ +/* + * propertiesview.h + * Copyright 2024, Thorbjørn Lindeijer + * + * This file is part of Tiled. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +class QHBoxLayout; +class QMenu; +class QToolButton; +class QVBoxLayout; + +namespace Tiled { + +class GroupProperty; +class PropertyLabel; + +/** + * A property represents a named value that can create its own edit widget. + */ +class Property : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip NOTIFY toolTipChanged) + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) + Q_PROPERTY(bool modified READ isModified WRITE setModified NOTIFY modifiedChanged) + Q_PROPERTY(bool selected READ isSelected WRITE setSelected NOTIFY selectedChanged) + Q_PROPERTY(Actions actions READ actions WRITE setActions NOTIFY actionsChanged) + +public: + enum class DisplayMode { + Default, + NoLabel, + Header, + Separator, + ChildrenOnly + }; + + enum class Action { + Reset = 0x01, + Remove = 0x02, + Add = 0x04, + AddDisabled = Add | 0x08, + Select = 0x10, + }; + Q_DECLARE_FLAGS(Actions, Action) + + Property(const QString &name, QObject *parent = nullptr) + : QObject(parent) + , m_name(name) + {} + + const QString &name() const { return m_name; } + void setName(const QString &name); + + const QString &toolTip() const { return m_toolTip; } + void setToolTip(const QString &toolTip); + + bool isEnabled() const { return m_enabled; } + void setEnabled(bool enabled); + + bool isModified() const { return m_modified; } + void setModified(bool modified); + + bool isSelected() const { return m_selected; } + void setSelected(bool selected); + + Actions actions() const { return m_actions; } + void setActions(Actions actions); + + GroupProperty *parentProperty() const { return m_parent; } + + virtual DisplayMode displayMode() const { return DisplayMode::Default; } + + virtual QWidget *createLabel(int level, QWidget *parent); + virtual QWidget *createEditor(QWidget *parent) = 0; + virtual void addContextMenuActions(QMenu *) {} + +signals: + void nameChanged(const QString &name); + void toolTipChanged(const QString &toolTip); + void valueChanged(); + void enabledChanged(bool enabled); + void modifiedChanged(bool modified); + void selectedChanged(bool selected); + void actionsChanged(Actions actions); + + void resetRequested(); + void removeRequested(); + void addRequested(); + + void contextMenuRequested(const QPoint &globalPos); + +private: + friend class GroupProperty; + + QString m_name; + QString m_toolTip; + bool m_enabled = true; + bool m_modified = false; + bool m_selected = false; + Actions m_actions; + GroupProperty *m_parent = nullptr; +}; + +class Separator final : public Property +{ + Q_OBJECT + +public: + Separator(QObject *parent = nullptr) + : Property(QString(), parent) + {} + + DisplayMode displayMode() const override { return DisplayMode::Separator; } + QWidget *createEditor(QWidget */*parent*/) override { return nullptr; } +}; + +/** + * A property that can have sub-properties. The GroupProperty owns the sub- + * properties and will delete them when it is deleted. + */ +class GroupProperty : public Property +{ + Q_OBJECT + Q_PROPERTY(bool expanded READ isExpanded WRITE setExpanded NOTIFY expandedChanged) + +public: + /** + * Creates an unnamed group, which will only display its children. + */ + explicit GroupProperty(QObject *parent = nullptr) + : Property(QString(), parent) + {} + + explicit GroupProperty(const QString &name, QObject *parent = nullptr) + : Property(name, parent) + {} + + ~GroupProperty() override { clear(); } + + DisplayMode displayMode() const override; + + QWidget *createLabel(int level, QWidget *parent) override; + QWidget *createEditor(QWidget */* parent */) override { return nullptr; } + void addContextMenuActions(QMenu *) override; + + void setHeader(bool header) { m_header = header; } + + bool isExpanded() const { return m_expanded; } + void setExpanded(bool expanded); + void expandAll(); + void collapseAll(); + + void clear() + { + qDeleteAll(m_subProperties); + m_subProperties.clear(); + } + + void addProperty(Property *property) + { + insertProperty(m_subProperties.size(), property); + } + + void insertProperty(int index, Property *property) + { + property->m_parent = this; + + m_subProperties.insert(index, property); + emit propertyAdded(index, property); + } + + void deleteProperty(Property *property) + { + removeProperty(property); + delete property; + } + + /** + * Removes the given property from this group. Ownership of the property + * is transferred to the caller. + */ + void removeProperty(Property *property) + { + if (!m_subProperties.removeOne(property)) + return; + + property->m_parent = nullptr; + emit propertyRemoved(property); + } + + int indexOfProperty(Property *property) const + { + return m_subProperties.indexOf(property); + } + + void addSeparator() { addProperty(new Separator(this)); } + + const QList &subProperties() const { return m_subProperties; } + +signals: + void expandedChanged(bool expanded); + void propertyAdded(int index, Property *property); + void propertyRemoved(Property *property); + +private: + bool m_header = true; + bool m_expanded = true; + QList m_subProperties; +}; + +/** + * A helper class for creating a property that wraps a value of a given type. + */ +template +class PropertyTemplate : public Property +{ +public: + using ValueType = Type; + + PropertyTemplate(const QString &name, + std::function get, + std::function set = {}, + QObject *parent = nullptr) + : Property(name, parent) + , m_get(std::move(get)) + , m_set(std::move(set)) + {} + + Type value() const { return m_get(); } + void setValue(const Type &value) { if (m_set) m_set(value); } + +private: + std::function m_get; + std::function m_set; +}; + +struct StringProperty : PropertyTemplate +{ + Q_OBJECT + +public: + using PropertyTemplate::PropertyTemplate; + QWidget *createEditor(QWidget *parent) override; + + void setPlaceholderText(const QString &placeholderText); + const QString &placeholderText() const { return m_placeholderText; } + +signals: + void placeholderTextChanged(const QString &placeholderText); + +private: + QString m_placeholderText; +}; + +struct MultilineStringProperty : StringProperty +{ + using StringProperty::StringProperty; + QWidget *createEditor(QWidget *parent) override; +}; + +struct UrlProperty : PropertyTemplate +{ + using PropertyTemplate::PropertyTemplate; + + QWidget *createEditor(QWidget *parent) override; + void addContextMenuActions(QMenu *) override; + + void setFilter(const QString &filter) { m_filter = filter; } + void setIsDirectory(bool isDirectory) { m_isDirectory = isDirectory; } + +private: + QString m_filter; + bool m_isDirectory = false; +}; + +struct IntProperty : PropertyTemplate +{ + using PropertyTemplate::PropertyTemplate; + QWidget *createEditor(QWidget *parent) override; + + void setMinimum(int minimum) { m_minimum = minimum; } + void setMaximum(int maximum) { m_maximum = maximum; } + void setSingleStep(int singleStep) { m_singleStep = singleStep; } + void setSuffix(const QString &suffix) { m_suffix = suffix; } + void setRange(int minimum, int maximum) + { + setMinimum(minimum); + setMaximum(maximum); + } + void setSliderEnabled(bool enabled) { m_sliderEnabled = enabled; } + +protected: + int m_minimum = std::numeric_limits::min(); + int m_maximum = std::numeric_limits::max(); + int m_singleStep = 1; + QString m_suffix; + bool m_sliderEnabled = false; +}; + +struct FloatProperty : PropertyTemplate +{ + using PropertyTemplate::PropertyTemplate; + QWidget *createEditor(QWidget *parent) override; + + void setMinimum(double minimum) { m_minimum = minimum; } + void setMaximum(double maximum) { m_maximum = maximum; } + void setSingleStep(double singleStep) { m_singleStep = singleStep; } + void setSuffix(const QString &suffix) { m_suffix = suffix; } + void setRange(double minimum, double maximum) + { + setMinimum(minimum); + setMaximum(maximum); + } + +private: + double m_minimum = -std::numeric_limits::max(); + double m_maximum = std::numeric_limits::max(); + double m_singleStep = 1.0; + QString m_suffix; +}; + +struct BoolProperty : PropertyTemplate +{ + using PropertyTemplate::PropertyTemplate; + DisplayMode displayMode() const override; + QWidget *createEditor(QWidget *parent) override; + + void setNameOnCheckBox(bool nameOnCheckBox) { m_nameOnCheckBox = nameOnCheckBox; } + +private: + bool m_nameOnCheckBox = false; +}; + +struct PointProperty : PropertyTemplate +{ + using PropertyTemplate::PropertyTemplate; + QWidget *createEditor(QWidget *parent) override; + + void setSuffix(const QString &suffix) { m_suffix = suffix; } + +private: + QString m_suffix; +}; + +struct PointFProperty : PropertyTemplate +{ + using PropertyTemplate::PropertyTemplate; + QWidget *createEditor(QWidget *parent) override; + + void setSingleStep(double singleStep) { m_singleStep = singleStep; } + +private: + double m_singleStep = 1.0; +}; + +struct SizeProperty : PropertyTemplate +{ + using PropertyTemplate::PropertyTemplate; + QWidget *createEditor(QWidget *parent) override; + + void setMinimum(int minimum) { m_minimum = minimum; } + void setSuffix(const QString &suffix) { m_suffix = suffix; } + +private: + int m_minimum = 0; + QString m_suffix; +}; + +struct SizeFProperty : PropertyTemplate +{ + using PropertyTemplate::PropertyTemplate; + QWidget *createEditor(QWidget *parent) override; +}; + +struct RectProperty : PropertyTemplate +{ + Q_OBJECT + +public: + using PropertyTemplate::PropertyTemplate; + QWidget *createEditor(QWidget *parent) override; + + void setConstraint(const QRect &constraint); + +signals: + void constraintChanged(const QRect &constraint); + +private: + QRect m_constraint; +}; + +struct RectFProperty : PropertyTemplate +{ + using PropertyTemplate::PropertyTemplate; + QWidget *createEditor(QWidget *parent) override; +}; + +struct ColorProperty : PropertyTemplate +{ + using PropertyTemplate::PropertyTemplate; + QWidget *createEditor(QWidget *parent) override; + + void setAlpha(bool alpha) { m_alpha = alpha; } + +private: + bool m_alpha = true; +}; + +struct FontProperty : PropertyTemplate +{ + using PropertyTemplate::PropertyTemplate; + QWidget *createEditor(QWidget *parent) override; +}; + +struct QtAlignmentProperty : PropertyTemplate +{ + using PropertyTemplate::PropertyTemplate; + QWidget *createEditor(QWidget *parent) override; +}; + + +Property *createQObjectProperty(QObject *qObject, + const char *propertyName, + const QString &displayName = {}); + +Property *createVariantProperty(const QString &name, + std::function get, + std::function set); + +struct EnumData +{ + EnumData(const QStringList &names = {}, + const QList &values = {}, + const QMap &icons = {}) + : names(names) + , values(values) + , icons(icons) + {} + + QStringList names; + QList values; // optional + QMap icons; // optional +}; + +template +EnumData enumData() +{ + return {}; +} + +/** + * A property that wraps an integer value and creates either a combo box or a + * list of checkboxes based on the given EnumData. + */ +class BaseEnumProperty : public IntProperty +{ + Q_OBJECT + +public: + using IntProperty::IntProperty; + + void setEnumData(const EnumData &enumData) { m_enumData = enumData; } + void setFlags(bool flags) { m_flags = flags; } + + QWidget *createEditor(QWidget *parent) override + { + return m_flags ? createFlagsEditor(parent) + : createEnumEditor(parent); + } + +protected: + QWidget *createFlagsEditor(QWidget *parent); + QWidget *createEnumEditor(QWidget *parent); + + EnumData m_enumData; + bool m_flags = false; +}; + +/** + * A property that wraps an enum value and automatically sets the EnumData + * based on the given type. + */ +template +class EnumProperty : public BaseEnumProperty +{ +public: + EnumProperty(const QString &name, + std::function get, + std::function set, + QObject *parent = nullptr) + : BaseEnumProperty(name, + [get] { + return static_cast(get()); + }, + set ? [set](const int &value){ set(static_cast(value)); } + : std::function(), + parent) + { + setEnumData(enumData()); + } +}; + + +/** + * A scrollable view that displays a tree of properties. + */ +class PropertiesView : public QScrollArea +{ + Q_OBJECT + +public: + explicit PropertiesView(QWidget *parent = nullptr); + + void setRootProperty(GroupProperty *root); + + QList selectedProperties() const; + void setSelectedProperties(const QList &properties); + + enum FocusTarget { + FocusRow, + FocusLabel, + FocusEditor, + }; + + bool focusProperty(Property *property, FocusTarget target = FocusEditor); + Property *focusedProperty() const; + +signals: + void selectedPropertiesChanged(); + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; + + void mousePressEvent(QMouseEvent *event) override; + void keyPressEvent(QKeyEvent *event) override; + +private: + bool focusNextPrevProperty(Property *property, bool next, bool shiftPressed); + + void deletePropertyWidgets(Property *property); + void forgetProperty(Property *property); + + QWidget *focusPropertyImpl(GroupProperty *group, Property *property, FocusTarget target); + + struct PropertyWidgets + { + int level = 0; + QWidget *rowWidget = nullptr; // The top-level widget for this property + QWidget *label = nullptr; + QWidget *editor = nullptr; + QToolButton *resetButton = nullptr; + QToolButton *removeButton = nullptr; + QToolButton *addButton = nullptr; + QWidget *children = nullptr; // The widget that contains the children of a group property + }; + + void createPropertyWidgets(Property *property, QWidget *parent, int level, + QVBoxLayout *layout, int index); + PropertyWidgets createPropertyWidgets(Property *property, QWidget *parent, int level); + QWidget *createChildrenWidget(GroupProperty *groupProperty, QWidget *parent, int level); + + void setPropertyChildrenExpanded(PropertyWidgets &widgets, + GroupProperty *groupProperty, QVBoxLayout *rowVerticalLayout, + bool expanded); + + void updatePropertyEnabled(const PropertyWidgets &widgets, bool enabled); + void updatePropertyActions(const PropertyWidgets &widgets, + Property::Actions actions); + + static constexpr int LabelStretch = 1; + static constexpr int EditorStretch = 1; + + QIcon m_resetIcon; + QIcon m_removeIcon; + QIcon m_addIcon; + QPointer m_root; + QVBoxLayout *m_rootLayout; + QPointer m_selectionStart; + QHash m_propertyWidgets; +}; + +} // namespace Tiled + +Q_DECLARE_OPERATORS_FOR_FLAGS(Tiled::Property::Actions) diff --git a/src/tiled/propertieswidget.cpp b/src/tiled/propertieswidget.cpp index e118088c2f..0a796d7be6 100644 --- a/src/tiled/propertieswidget.cpp +++ b/src/tiled/propertieswidget.cpp @@ -21,51 +21,2179 @@ #include "propertieswidget.h" #include "actionmanager.h" -#include "addpropertydialog.h" +#include "changeimagelayerproperty.h" +#include "changelayer.h" +#include "changemapobject.h" +#include "changemapproperty.h" +#include "changeobjectgroupproperties.h" #include "changeproperties.h" +#include "changetile.h" +#include "changetileimagesource.h" +#include "changewangcolordata.h" +#include "changewangsetdata.h" #include "clipboardmanager.h" +#include "compression.h" #include "mapdocument.h" -#include "mapobject.h" -#include "propertybrowser.h" +#include "objectgroup.h" +#include "objecttemplate.h" +#include "preferences.h" +#include "propertiesview.h" +#include "propertyeditorwidgets.h" +#include "tilesetchanges.h" +#include "tilesetdocument.h" +#include "tilesetparametersedit.h" +#include "transformmapobjects.h" #include "utils.h" -#include "variantpropertymanager.h" +#include "variantmapproperty.h" +#include "wangoverlay.h" #include +#include #include #include #include #include #include #include +#include +#include #include +#include #include #include namespace Tiled { +template<> EnumData enumData() +{ + return {{ + QCoreApplication::translate("Alignment", "Unspecified"), + QCoreApplication::translate("Alignment", "Top Left"), + QCoreApplication::translate("Alignment", "Top"), + QCoreApplication::translate("Alignment", "Top Right"), + QCoreApplication::translate("Alignment", "Left"), + QCoreApplication::translate("Alignment", "Center"), + QCoreApplication::translate("Alignment", "Right"), + QCoreApplication::translate("Alignment", "Bottom Left"), + QCoreApplication::translate("Alignment", "Bottom"), + QCoreApplication::translate("Alignment", "Bottom Right") + }}; +} + +template<> EnumData enumData() +{ + // We leave out the "Unknown" orientation, because it shouldn't occur here + return {{ + QCoreApplication::translate("Tiled::NewMapDialog", "Orthogonal"), + QCoreApplication::translate("Tiled::NewMapDialog", "Isometric"), + QCoreApplication::translate("Tiled::NewMapDialog", "Isometric (Staggered)"), + QCoreApplication::translate("Tiled::NewMapDialog", "Hexagonal (Staggered)") + }, { + Map::Orthogonal, + Map::Isometric, + Map::Staggered, + Map::Hexagonal, + }}; +} + +template<> EnumData enumData() +{ + return {{ + QCoreApplication::translate("StaggerAxis", "X"), + QCoreApplication::translate("StaggerAxis", "Y") + }}; +} + +template<> EnumData enumData() +{ + return {{ + QCoreApplication::translate("StaggerIndex", "Odd"), + QCoreApplication::translate("StaggerIndex", "Even") + }}; +} + +template<> EnumData enumData() +{ + return {{ + QCoreApplication::translate("RenderOrder", "Right Down"), + QCoreApplication::translate("RenderOrder", "Right Up"), + QCoreApplication::translate("RenderOrder", "Left Down"), + QCoreApplication::translate("RenderOrder", "Left Up") + }}; +} + +template<> EnumData enumData() +{ + QStringList names { + QCoreApplication::translate("PreferencesDialog", "CSV"), + QCoreApplication::translate("PreferencesDialog", "XML (deprecated)"), + QCoreApplication::translate("PreferencesDialog", "Base64 (uncompressed)"), + QCoreApplication::translate("PreferencesDialog", "Base64 (gzip compressed)"), + QCoreApplication::translate("PreferencesDialog", "Base64 (zlib compressed)"), + }; + QList values { + Map::CSV, + Map::XML, + Map::Base64, + Map::Base64Gzip, + Map::Base64Zlib, + }; + + if (compressionSupported(Zstandard)) { + names.append(QCoreApplication::translate("PreferencesDialog", "Base64 (Zstandard compressed)")); + values.append(Map::Base64Zstandard); + } + + return { names, values }; +} + +template<> EnumData enumData() +{ + return {{ + QCoreApplication::translate("Tileset", "Orthogonal"), + QCoreApplication::translate("Tileset", "Isometric"), + }}; +} + +template<> EnumData enumData() +{ + return {{ + QCoreApplication::translate("Tileset", "Tile Size"), + QCoreApplication::translate("Tileset", "Map Grid Size"), + }}; +} + +template<> EnumData enumData() +{ + return {{ + QCoreApplication::translate("Tileset", "Stretch"), + QCoreApplication::translate("Tileset", "Preserve Aspect Ratio"), + }}; +} + +template<> EnumData enumData() +{ + return {{ + QCoreApplication::translate("ObjectGroup", "Top Down"), + QCoreApplication::translate("ObjectGroup", "Index Order"), + }}; +} + +template<> EnumData enumData() +{ + const QStringList names { + QCoreApplication::translate("WangSet", "Corner"), + QCoreApplication::translate("WangSet", "Edge"), + QCoreApplication::translate("WangSet", "Mixed"), + }; + + QMap icons; + icons.insert(WangSet::Corner, wangSetIcon(WangSet::Corner)); + icons.insert(WangSet::Edge, wangSetIcon(WangSet::Edge)); + icons.insert(WangSet::Mixed, wangSetIcon(WangSet::Mixed)); + + return { names, {}, icons }; +} + + +class FlippingProperty : public IntProperty +{ + Q_OBJECT + +public: + using IntProperty::IntProperty; + + QWidget *createEditor(QWidget *parent) override + { + QIcon flipHorizontalIcon(QLatin1String(":images/24/flip-horizontal.png")); + QIcon flipVerticalIcon(QLatin1String(":images/24/flip-vertical.png")); + + flipHorizontalIcon.addFile(QLatin1String(":images/32/flip-horizontal.png")); + flipVerticalIcon.addFile(QLatin1String(":images/32/flip-vertical.png")); + + auto editor = new QWidget(parent); + + auto flipHorizontally = new QToolButton(editor); + flipHorizontally->setToolTip(tr("Flip Horizontally")); + flipHorizontally->setIcon(flipHorizontalIcon); + flipHorizontally->setCheckable(true); + + auto flipVertically = new QToolButton(editor); + flipVertically->setToolTip(tr("Flip Vertically")); + flipVertically->setIcon(flipVerticalIcon); + flipVertically->setCheckable(true); + + auto horizontalLayout = new QHBoxLayout(editor); + horizontalLayout->setContentsMargins(QMargins()); + horizontalLayout->addWidget(flipHorizontally); + horizontalLayout->addWidget(flipVertically); + horizontalLayout->addStretch(); + + auto syncEditor = [=] { + const QSignalBlocker horizontalBlocker(flipHorizontally); + const QSignalBlocker verticalBlocker(flipVertically); + const auto v = value(); + flipHorizontally->setChecked(v & Cell::FlippedHorizontally); + flipVertically->setChecked(v & Cell::FlippedVertically); + }; + auto syncProperty = [=] { + int flags = 0; + if (flipHorizontally->isChecked()) + flags |= Cell::FlippedHorizontally; + if (flipVertically->isChecked()) + flags |= Cell::FlippedVertically; + setValue(flags); + }; + + syncEditor(); + + connect(this, &Property::valueChanged, editor, syncEditor); + connect(flipHorizontally, &QAbstractButton::toggled, this, syncProperty); + connect(flipVertically, &QAbstractButton::toggled, this, syncProperty); + return editor; + } +}; + + +class ImageLayerRepeatProperty : public PropertyTemplate +{ + Q_OBJECT + +public: + using PropertyTemplate::PropertyTemplate; + + QWidget *createEditor(QWidget *parent) override + { + auto editor = new QWidget(parent); + auto layout = new QHBoxLayout(editor); + auto repeatX = new QCheckBox(tr("X"), editor); + auto repeatY = new QCheckBox(tr("Y"), editor); + layout->setContentsMargins(QMargins()); + layout->addWidget(repeatX); + layout->addWidget(repeatY); + + auto syncEditor = [=] { + const QSignalBlocker xBlocker(repeatX); + const QSignalBlocker yBlocker(repeatY); + const auto v = value(); + repeatX->setChecked(v & ImageLayer::RepeatX); + repeatY->setChecked(v & ImageLayer::RepeatY); + }; + auto syncProperty = [=] { + ImageLayer::RepetitionFlags v; + if (repeatX->isChecked()) + v |= ImageLayer::RepeatX; + if (repeatY->isChecked()) + v |= ImageLayer::RepeatY; + setValue(v); + }; + + syncEditor(); + + connect(this, &Property::valueChanged, editor, syncEditor); + connect(repeatX, &QCheckBox::toggled, this, syncProperty); + connect(repeatY, &QCheckBox::toggled, this, syncProperty); + return editor; + } +}; + + +class TransformationFlagsProperty : public PropertyTemplate +{ + Q_OBJECT + +public: + using PropertyTemplate::PropertyTemplate; + + QWidget *createEditor(QWidget *parent) override + { + QIcon flipHorizontalIcon(QLatin1String(":images/24/flip-horizontal.png")); + QIcon flipVerticalIcon(QLatin1String(":images/24/flip-vertical.png")); + QIcon rotateRightIcon(QLatin1String(":images/24/rotate-right.png")); + + flipHorizontalIcon.addFile(QLatin1String(":images/32/flip-horizontal.png")); + flipVerticalIcon.addFile(QLatin1String(":images/32/flip-vertical.png")); + rotateRightIcon.addFile(QLatin1String(":images/32/rotate-right.png")); + + auto editor = new QWidget(parent); + + auto flipHorizontally = new QToolButton(editor); + flipHorizontally->setToolTip(tr("Flip Horizontally")); + flipHorizontally->setIcon(flipHorizontalIcon); + flipHorizontally->setCheckable(true); + + auto flipVertically = new QToolButton(editor); + flipVertically->setToolTip(tr("Flip Vertically")); + flipVertically->setIcon(flipVerticalIcon); + flipVertically->setCheckable(true); + + auto rotate = new QToolButton(editor); + rotate->setToolTip(tr("Rotate")); + rotate->setIcon(rotateRightIcon); + rotate->setCheckable(true); + + auto preferUntransformed = new QCheckBox(tr("Prefer Untransformed"), editor); + + auto horizontalLayout = new QHBoxLayout; + horizontalLayout->addWidget(flipHorizontally); + horizontalLayout->addWidget(flipVertically); + horizontalLayout->addWidget(rotate); + horizontalLayout->addStretch(); + + auto verticalLayout = new QVBoxLayout(editor); + verticalLayout->setContentsMargins(QMargins()); + verticalLayout->setSpacing(Utils::dpiScaled(4)); + verticalLayout->addLayout(horizontalLayout); + verticalLayout->addWidget(preferUntransformed); + + auto syncEditor = [=] { + const QSignalBlocker horizontalBlocker(flipHorizontally); + const QSignalBlocker verticalBlocker(flipVertically); + const QSignalBlocker rotateBlocker(rotate); + const QSignalBlocker preferUntransformedBlocker(preferUntransformed); + const auto v = value(); + flipHorizontally->setChecked(v & Tileset::AllowFlipHorizontally); + flipVertically->setChecked(v & Tileset::AllowFlipVertically); + rotate->setChecked(v & Tileset::AllowRotate); + preferUntransformed->setChecked(v & Tileset::PreferUntransformed); + }; + auto syncProperty = [=] { + Tileset::TransformationFlags v; + if (flipHorizontally->isChecked()) + v |= Tileset::AllowFlipHorizontally; + if (flipVertically->isChecked()) + v |= Tileset::AllowFlipVertically; + if (rotate->isChecked()) + v |= Tileset::AllowRotate; + if (preferUntransformed->isChecked()) + v |= Tileset::PreferUntransformed; + setValue(v); + }; + + syncEditor(); + + connect(this, &Property::valueChanged, editor, syncEditor); + connect(flipHorizontally, &QAbstractButton::toggled, this, syncProperty); + connect(flipVertically, &QAbstractButton::toggled, this, syncProperty); + connect(rotate, &QAbstractButton::toggled, this, syncProperty); + connect(preferUntransformed, &QAbstractButton::toggled, this, syncProperty); + return editor; + } +}; + + +class TilesetImageProperty : public GroupProperty +{ + Q_OBJECT + +public: + TilesetImageProperty(TilesetDocument *tilesetDocument, QObject *parent) + : GroupProperty(tr("Tileset Image"), parent) + , mTilesetDocument(tilesetDocument) + {} + + DisplayMode displayMode() const override { return DisplayMode::Default; } + + QWidget *createEditor(QWidget *parent) override + { + auto editor = new TilesetParametersEdit(parent); + editor->setTilesetDocument(mTilesetDocument); + return editor; + } + +private: + TilesetDocument *mTilesetDocument; +}; + +static bool propertyValueAffected(Object *currentObject, + Object *changedObject, + const QString &propertyName) +{ + if (currentObject == changedObject) + return true; + + // Changed property may be inherited + if (currentObject && currentObject->typeId() == Object::MapObjectType && changedObject->typeId() == Object::TileType) { + auto tile = static_cast(currentObject)->cell().tile(); + if (tile == changedObject && !currentObject->hasProperty(propertyName)) + return true; + } + + return false; +} + +static bool objectPropertiesRelevant(Document *document, Object *object) +{ + auto currentObject = document->currentObject(); + if (!currentObject) + return false; + + if (currentObject == object) + return true; + + if (currentObject->typeId() == Object::MapObjectType) + if (static_cast(currentObject)->cell().tile() == object) + return true; + + if (document->currentObjects().contains(object)) + return true; + + return false; +} + +class CustomProperties : public VariantMapProperty +{ + Q_OBJECT + +public: + CustomProperties(QObject *parent = nullptr) + : VariantMapProperty(tr("Custom Properties"), parent) + { + connect(this, &VariantMapProperty::memberValueChanged, + this, &CustomProperties::setPropertyValue); + } + + void setDocument(Document *document); + +protected: + void propertyTypesChanged() override + { + QScopedValueRollback propertyTypesChanged(mPropertyTypesChanged, true); + refresh(); + } + +private: + void onChanged(const ChangeEvent &change) { + if (change.type != ChangeEvent::ObjectsChanged) + return; + + auto object = mDocument->currentObject(); + if (!object) + return; + + auto &objectsChange = static_cast(change); + + if (objectsChange.properties & ObjectsChangeEvent::ClassProperty) { + if (objectsChange.objects.contains(object)) { + refresh(); + } else if (object->typeId() == Object::MapObjectType) { + auto mapObject = static_cast(object); + if (auto tile = mapObject->cell().tile()) { + if (mapObject->className().isEmpty() && objectsChange.objects.contains(tile)) + refresh(); + } + } + } + } + + void propertyAdded(Object *object, const QString &) { + if (mUpdating) + return; + if (!objectPropertiesRelevant(mDocument, object)) + return; + refresh(); + } + + void propertyRemoved(Object *object, const QString &) { + if (mUpdating) + return; + if (!objectPropertiesRelevant(mDocument, object)) + return; + refresh(); + } + + void propertyChanged(Object *object, const QString &name) { + if (mUpdating) + return; + if (!propertyValueAffected(mDocument->currentObject(), object, name)) + return; + refresh(); + } + + void propertiesChanged(Object *object) { + if (!objectPropertiesRelevant(mDocument, object)) + return; + refresh(); + } + + void refresh(); + + void setPropertyValue(const QStringList &path, const QVariant &value); + + bool mUpdating = false; +}; + + +static bool anyObjectHasProperty(const QList &objects, const QString &name) +{ + for (Object *obj : objects) { + if (obj->hasProperty(name)) + return true; + } + return false; +} + +static QStringList classNamesFor(const Object &object) +{ + QStringList names; + for (const auto type : Object::propertyTypes()) + if (type->isClass()) + if (static_cast(type)->isClassFor(object)) + names.append(type->name); + return names; +} + +class ClassNameProperty : public StringProperty +{ + Q_OBJECT + +public: + ClassNameProperty(Document *document, Object *object, QObject *parent = nullptr) + : StringProperty(tr("Class"), + [this] { return mObject->className(); }, + [this] (const QString &value) { + QUndoStack *undoStack = mDocument->undoStack(); + undoStack->push(new ChangeClassName(mDocument, + mDocument->currentObjects(), + value)); + }, + parent) + , mDocument(document) + , mObject(object) + { + updatePlaceholderText(); + + connect(mDocument, &Document::changed, + this, &ClassNameProperty::onChanged); + } + + QWidget *createEditor(QWidget *parent) override + { + auto editor = new ComboBox(parent); + editor->setEditable(true); + editor->lineEdit()->setPlaceholderText(placeholderText()); + editor->addItems(classNamesFor(*mObject)); + auto syncEditor = [this, editor] { + const QSignalBlocker blocker(editor); + + // Avoid affecting cursor position when the text is the same + const auto v = value(); + if (editor->currentText() != v) + editor->setCurrentText(v); + }; + syncEditor(); + connect(this, &Property::valueChanged, editor, syncEditor); + connect(this, &StringProperty::placeholderTextChanged, + editor->lineEdit(), &QLineEdit::setPlaceholderText); + connect(editor, &QComboBox::currentTextChanged, this, &StringProperty::setValue); + connect(Preferences::instance(), &Preferences::propertyTypesChanged, + editor, [=] { + const QSignalBlocker blocker(editor); + editor->clear(); + editor->addItems(classNamesFor(*mObject)); + syncEditor(); + }); + return editor; + } + +private: + void onChanged(const ChangeEvent &event) + { + if (event.type != ChangeEvent::ObjectsChanged) + return; + + const auto objectsEvent = static_cast(event); + if (!objectsEvent.objects.contains(mObject)) + return; + + if (objectsEvent.properties & ObjectsChangeEvent::ClassProperty) { + updatePlaceholderText(); + emit valueChanged(); + } + } + + void updatePlaceholderText() + { + if (mObject->typeId() == Object::MapObjectType && mObject->className().isEmpty()) + setPlaceholderText(static_cast(mObject)->effectiveClassName()); + else + setPlaceholderText(QString()); + } + + Document *mDocument; + Object *mObject; +}; + + +class MapSizeProperty : public SizeProperty +{ + Q_OBJECT + +public: + MapSizeProperty(MapDocument *mapDocument, + QObject *parent = nullptr) + : SizeProperty(tr("Map Size"), + [this]{ return mMapDocument->map()->size(); }, {}, + parent) + , mMapDocument(mapDocument) + { + connect(mMapDocument, &MapDocument::mapResized, + this, &Property::valueChanged); + } + + QWidget *createEditor(QWidget *parent) override + { + auto widget = new QWidget(parent); + auto layout = new QVBoxLayout(widget); + auto valueEdit = SizeProperty::createEditor(widget); + auto resizeButton = new QPushButton(tr("Resize Map"), widget); + + valueEdit->setEnabled(false); + layout->setContentsMargins(QMargins()); + layout->addWidget(valueEdit); + layout->addWidget(resizeButton, 0, Qt::AlignLeft); + + connect(resizeButton, &QPushButton::clicked, [] { + ActionManager::action("ResizeMap")->trigger(); + }); + + return widget; + } + +private: + MapDocument *mMapDocument; +}; + +class ObjectProperties : public GroupProperty +{ + Q_OBJECT + +public: + ObjectProperties(Document *document, Object *object, QObject *parent = nullptr) + : GroupProperty(parent) + , mDocument(document) + , mObject(object) + { + mClassProperty = new ClassNameProperty(document, object, this); + } + +protected: + void push(QUndoCommand *command) + { + mDocument->undoStack()->push(command); + } + + Document *mDocument; + Property *mClassProperty; + Object *mObject; +}; + + +class MapProperties : public ObjectProperties +{ + Q_OBJECT + +public: + MapProperties(MapDocument *document, QObject *parent = nullptr) + : ObjectProperties(document, document->map(), parent) + { + mOrientationProperty = new EnumProperty( + tr("Orientation"), + [this] { + return map()->orientation(); + }, + [this](Map::Orientation value) { + push(new ChangeMapOrientation(mapDocument(), value)); + }); + + mSizeProperty = new MapSizeProperty(mapDocument(), this); + + mTileSizeProperty = new SizeProperty( + tr("Tile Size"), + [this] { + return mapDocument()->map()->tileSize(); + }, + [this](const QSize &newSize) { + push(new ChangeMapTileSize(mapDocument(), newSize)); + }, + this); + mTileSizeProperty->setMinimum(1); + mTileSizeProperty->setSuffix(tr(" px")); + + mInfiniteProperty = new BoolProperty( + tr("Infinite"), + [this] { + return map()->infinite(); + }, + [this](const bool &value) { + push(new ChangeMapInfinite(mapDocument(), value)); + }); + mInfiniteProperty->setNameOnCheckBox(true); + + mHexSideLengthProperty = new IntProperty( + tr("Hex Side Length"), + [this] { + return map()->hexSideLength(); + }, + [this](const int &value) { + push(new ChangeMapHexSideLength(mapDocument(), value)); + }); + mHexSideLengthProperty->setSuffix(tr(" px")); + + mStaggerAxisProperty = new EnumProperty( + tr("Stagger Axis"), + [this] { + return map()->staggerAxis(); + }, + [this](Map::StaggerAxis value) { + push(new ChangeMapStaggerAxis(mapDocument(), value)); + }); + + mStaggerIndexProperty = new EnumProperty( + tr("Stagger Index"), + [this] { + return map()->staggerIndex(); + }, + [this](Map::StaggerIndex value) { + push(new ChangeMapStaggerIndex(mapDocument(), value)); + }); + + mParallaxOriginProperty = new PointFProperty( + tr("Parallax Origin"), + [this] { + return map()->parallaxOrigin(); + }, + [this](const QPointF &value) { + push(new ChangeMapParallaxOrigin(mapDocument(), value)); + }); + + mLayerDataFormatProperty = new EnumProperty( + tr("Layer Data Format"), + [this] { + return map()->layerDataFormat(); + }, + [this](Map::LayerDataFormat value) { + push(new ChangeMapLayerDataFormat(mapDocument(), value)); + }); + + mCompressionLevelProperty = new IntProperty( + tr("Compression Level"), + [this] { + return map()->compressionLevel(); + }, + [this](const int &value) { + push(new ChangeMapCompressionLevel(mapDocument(), value)); + }); + + mChunkSizeProperty = new SizeProperty( + tr("Output Chunk Size"), + [this] { + return map()->chunkSize(); + }, + [this](const QSize &value) { + push(new ChangeMapChunkSize(mapDocument(), value)); + }); + mChunkSizeProperty->setMinimum(CHUNK_SIZE_MIN); + + mRenderOrderProperty = new EnumProperty( + tr("Tile Render Order"), + [this] { + return map()->renderOrder(); + }, + [this](Map::RenderOrder value) { + push(new ChangeMapRenderOrder(mapDocument(), value)); + }); + + mBackgroundColorProperty = new ColorProperty( + tr("Background Color"), + [this] { + return map()->backgroundColor(); + }, + [this](const QColor &value) { + push(new ChangeMapBackgroundColor(mapDocument(), value)); + }); + + mMapProperties = new GroupProperty(tr("Map")); + mMapProperties->addProperty(mClassProperty); + mMapProperties->addSeparator(); + mMapProperties->addProperty(mOrientationProperty); + mMapProperties->addProperty(mSizeProperty); + mMapProperties->addProperty(mInfiniteProperty); + mMapProperties->addProperty(mTileSizeProperty); + mMapProperties->addProperty(mHexSideLengthProperty); + mMapProperties->addProperty(mStaggerAxisProperty); + mMapProperties->addProperty(mStaggerIndexProperty); + mMapProperties->addSeparator(); + mMapProperties->addProperty(mParallaxOriginProperty); + mMapProperties->addSeparator(); + mMapProperties->addProperty(mLayerDataFormatProperty); + mMapProperties->addProperty(mCompressionLevelProperty); + mMapProperties->addProperty(mChunkSizeProperty); + mMapProperties->addSeparator(); + mMapProperties->addProperty(mRenderOrderProperty); + mMapProperties->addProperty(mBackgroundColorProperty); + + addProperty(mMapProperties); + + updateEnabledState(); + connect(document, &Document::changed, + this, &MapProperties::onChanged); + } + +private: + void onChanged(const ChangeEvent &event) + { + if (event.type != ChangeEvent::MapChanged) + return; + + const auto property = static_cast(event).property; + switch (property) { + case Map::TileSizeProperty: + emit mTileSizeProperty->valueChanged(); + break; + case Map::InfiniteProperty: + emit mInfiniteProperty->valueChanged(); + break; + case Map::HexSideLengthProperty: + emit mHexSideLengthProperty->valueChanged(); + break; + case Map::StaggerAxisProperty: + emit mStaggerAxisProperty->valueChanged(); + break; + case Map::StaggerIndexProperty: + emit mStaggerIndexProperty->valueChanged(); + break; + case Map::ParallaxOriginProperty: + emit mParallaxOriginProperty->valueChanged(); + break; + case Map::OrientationProperty: + emit mOrientationProperty->valueChanged(); + break; + case Map::RenderOrderProperty: + emit mRenderOrderProperty->valueChanged(); + break; + case Map::BackgroundColorProperty: + emit mBackgroundColorProperty->valueChanged(); + break; + case Map::LayerDataFormatProperty: + emit mLayerDataFormatProperty->valueChanged(); + break; + case Map::CompressionLevelProperty: + emit mCompressionLevelProperty->valueChanged(); + break; + case Map::ChunkSizeProperty: + emit mChunkSizeProperty->valueChanged(); + break; + } + + updateEnabledState(); + } + + void updateEnabledState() + { + const auto orientation = map()->orientation(); + const bool stagger = orientation == Map::Staggered || orientation == Map::Hexagonal; + + mHexSideLengthProperty->setEnabled(orientation == Map::Hexagonal); + mStaggerAxisProperty->setEnabled(stagger); + mStaggerIndexProperty->setEnabled(stagger); + mRenderOrderProperty->setEnabled(orientation == Map::Orthogonal); + mChunkSizeProperty->setEnabled(map()->infinite()); + + switch (map()->layerDataFormat()) { + case Map::XML: + case Map::Base64: + case Map::CSV: + mCompressionLevelProperty->setEnabled(false); + break; + case Map::Base64Gzip: + case Map::Base64Zlib: + case Map::Base64Zstandard: + mCompressionLevelProperty->setEnabled(true); + break; + } + } + + MapDocument *mapDocument() const + { + return static_cast(mDocument); + } + + Map *map() const + { + return mapDocument()->map(); + } + + GroupProperty *mMapProperties; + Property *mOrientationProperty; + Property *mSizeProperty; + SizeProperty *mTileSizeProperty; + BoolProperty *mInfiniteProperty; + IntProperty *mHexSideLengthProperty; + Property *mStaggerAxisProperty; + Property *mStaggerIndexProperty; + Property *mParallaxOriginProperty; + Property *mLayerDataFormatProperty; + Property *mCompressionLevelProperty; + SizeProperty *mChunkSizeProperty; + Property *mRenderOrderProperty; + Property *mBackgroundColorProperty; +}; + +class LayerProperties : public ObjectProperties +{ + Q_OBJECT + +public: + LayerProperties(MapDocument *document, Layer *object, QObject *parent = nullptr) + : ObjectProperties(document, object, parent) + { + // todo: would be nicer to avoid the SpinBox and use a custom widget + // might also be nice to embed this in the header instead of using a property + mIdProperty = new IntProperty( + tr("ID"), + [this] { return layer()->id(); }); + mIdProperty->setEnabled(false); + + mNameProperty = new StringProperty( + tr("Name"), + [this] { return layer()->name(); }, + [this](const QString &value) { + push(new SetLayerName(mapDocument(), + mapDocument()->selectedLayers(), + value)); + }); + + mVisibleProperty = new BoolProperty( + tr("Visible"), + [this] { return layer()->isVisible(); }, + [this](const bool &value) { + push(new SetLayerVisible(mapDocument(), + mapDocument()->selectedLayers(), + value)); + }); + mVisibleProperty->setNameOnCheckBox(true); + + mLockedProperty = new BoolProperty( + tr("Locked"), + [this] { return layer()->isLocked(); }, + [this](const bool &value) { + push(new SetLayerLocked(mapDocument(), + mapDocument()->selectedLayers(), + value)); + }); + mLockedProperty->setNameOnCheckBox(true); + + mOpacityProperty = new IntProperty( + tr("Opacity"), + [this] { return qRound(layer()->opacity() * 100); }, + [this](const int &value) { + push(new SetLayerOpacity(mapDocument(), + mapDocument()->selectedLayers(), + qreal(value) / 100)); + }); + mOpacityProperty->setRange(0, 100); + mOpacityProperty->setSuffix(tr("%")); + mOpacityProperty->setSliderEnabled(true); + + mTintColorProperty = new ColorProperty( + tr("Tint Color"), + [this] { return layer()->tintColor(); }, + [this](const QColor &value) { + push(new SetLayerTintColor(mapDocument(), + mapDocument()->selectedLayers(), + value)); + }); + + mOffsetProperty = new PointFProperty( + tr("Offset"), + [this] { return layer()->offset(); }, + [this](const QPointF &value) { + const auto oldValue = layer()->offset(); + const bool changedX = oldValue.x() != value.x(); + const bool changedY = oldValue.y() != value.y(); + + QVector offsets; + for (const Layer *layer : mapDocument()->selectedLayers()) + offsets.append(layer->offset()); + + if (changedX) { + for (QPointF &offset : offsets) + offset.setX(value.x()); + } else if (changedY) { + for (QPointF &offset : offsets) + offset.setY(value.y()); + } + + push(new SetLayerOffset(mapDocument(), + mapDocument()->selectedLayers(), + offsets)); + }); + + mParallaxFactorProperty = new PointFProperty( + tr("Parallax Factor"), + [this] { return layer()->parallaxFactor(); }, + [this](const QPointF &value) { + push(new SetLayerParallaxFactor(mapDocument(), + mapDocument()->selectedLayers(), + value)); + }); + mParallaxFactorProperty->setSingleStep(0.1); + + mLayerProperties = new GroupProperty(tr("Layer")); + mLayerProperties->addProperty(mIdProperty); + mLayerProperties->addProperty(mNameProperty); + mLayerProperties->addProperty(mClassProperty); + mLayerProperties->addSeparator(); + mLayerProperties->addProperty(mVisibleProperty); + mLayerProperties->addProperty(mLockedProperty); + mLayerProperties->addProperty(mOpacityProperty); + mLayerProperties->addProperty(mTintColorProperty); + mLayerProperties->addProperty(mOffsetProperty); + mLayerProperties->addProperty(mParallaxFactorProperty); + + addProperty(mLayerProperties); + + connect(document, &Document::changed, + this, &LayerProperties::onChanged); + } + +protected: + virtual void onChanged(const ChangeEvent &event) + { + if (event.type != ChangeEvent::LayerChanged) + return; + + const auto &layerChange = static_cast(event); + if (layerChange.layer != layer()) + return; + + if (layerChange.properties & LayerChangeEvent::NameProperty) + emit mNameProperty->valueChanged(); + if (layerChange.properties & LayerChangeEvent::VisibleProperty) + emit mVisibleProperty->valueChanged(); + if (layerChange.properties & LayerChangeEvent::LockedProperty) + emit mLockedProperty->valueChanged(); + if (layerChange.properties & LayerChangeEvent::OpacityProperty) + emit mOpacityProperty->valueChanged(); + if (layerChange.properties & LayerChangeEvent::TintColorProperty) + emit mTintColorProperty->valueChanged(); + if (layerChange.properties & LayerChangeEvent::OffsetProperty) + emit mOffsetProperty->valueChanged(); + if (layerChange.properties & LayerChangeEvent::ParallaxFactorProperty) + emit mParallaxFactorProperty->valueChanged(); + } + + MapDocument *mapDocument() const + { + return static_cast(mDocument); + } + + Layer *layer() const + { + return static_cast(mObject); + } + + template + QList selectedLayersOfType(Layer::TypeFlag typeFlag) + { + if (mDocument) + return {}; + + QList result; + for (Layer *layer : mapDocument()->selectedLayers()) + if (layer->layerType() == typeFlag) + result.append(static_cast(layer)); + + return result; + } + + GroupProperty *mLayerProperties; + Property *mIdProperty; + Property *mNameProperty; + BoolProperty *mVisibleProperty; + BoolProperty *mLockedProperty; + IntProperty *mOpacityProperty; + Property *mTintColorProperty; + Property *mOffsetProperty; + PointFProperty *mParallaxFactorProperty; +}; + +class ImageLayerProperties : public LayerProperties +{ + Q_OBJECT + +public: + ImageLayerProperties(MapDocument *document, ImageLayer *object, QObject *parent = nullptr) + : LayerProperties(document, object, parent) + { + mImageProperty = new UrlProperty( + tr("Image Source"), + [this] { return imageLayer()->imageSource(); }, + [this](const QUrl &value) { + const auto imageLayers = selectedLayersOfType(Layer::ImageLayerType); + push(new ChangeImageLayerImageSource(mapDocument(), imageLayers, value)); + }); + mImageProperty->setFilter(Utils::readableImageFormatsFilter()); + + mTransparentColorProperty = new ColorProperty( + tr("Transparent Color"), + [this] { return imageLayer()->transparentColor(); }, + [this](const QColor &value) { + const auto imageLayers = selectedLayersOfType(Layer::ImageLayerType); + push(new ChangeImageLayerTransparentColor(mapDocument(), imageLayers, value)); + }); + mTransparentColorProperty->setAlpha(false); + + mRepeatProperty = new ImageLayerRepeatProperty( + tr("Repeat"), + [this] { return imageLayer()->repetition(); }, + [this](const ImageLayer::RepetitionFlags &value) { + const bool repeatX = value & ImageLayer::RepeatX; + const bool repeatY = value & ImageLayer::RepeatY; + const auto imageLayers = selectedLayersOfType(Layer::ImageLayerType); + if (repeatX != imageLayer()->repeatX()) + push(new ChangeImageLayerRepeatX(mapDocument(), imageLayers, repeatX)); + if (repeatY != imageLayer()->repeatY()) + push(new ChangeImageLayerRepeatY(mapDocument(), imageLayers, repeatY)); + }); + + mImageLayerProperties = new GroupProperty(tr("Image Layer")); + mImageLayerProperties->addProperty(mImageProperty); + mImageLayerProperties->addProperty(mTransparentColorProperty); + mImageLayerProperties->addSeparator(); + mImageLayerProperties->addProperty(mRepeatProperty); + + addProperty(mImageLayerProperties); + } + +private: + void onChanged(const ChangeEvent &event) override + { + LayerProperties::onChanged(event); + + if (event.type != ChangeEvent::ImageLayerChanged) + return; + + const auto &layerChange = static_cast(event); + if (layerChange.layer != layer()) + return; + + if (layerChange.properties & ImageLayerChangeEvent::ImageSourceProperty) + emit mImageProperty->valueChanged(); + if (layerChange.properties & ImageLayerChangeEvent::TransparentColorProperty) + emit mTransparentColorProperty->valueChanged(); + if (layerChange.properties & ImageLayerChangeEvent::RepeatProperty) { + emit mRepeatProperty->valueChanged(); + } + } + + ImageLayer *imageLayer() const + { + return static_cast(mObject); + } + + GroupProperty *mImageLayerProperties; + UrlProperty *mImageProperty; + ColorProperty *mTransparentColorProperty; + Property *mRepeatProperty; +}; + +class ObjectGroupProperties : public LayerProperties +{ + Q_OBJECT + +public: + ObjectGroupProperties(MapDocument *document, ObjectGroup *object, QObject *parent = nullptr) + : LayerProperties(document, object, parent) + { + mColorProperty = new ColorProperty( + tr("Color"), + [this] { return objectGroup()->color(); }, + [this](const QColor &value) { + const auto objectGroups = selectedLayersOfType(Layer::ObjectGroupType); + push(new ChangeObjectGroupColor(mapDocument(), objectGroups, value)); + }); + + mDrawOrderProperty = new EnumProperty( + tr("Draw Order"), + [this] { return objectGroup()->drawOrder(); }, + [this](ObjectGroup::DrawOrder value) { + const auto objectGroups = selectedLayersOfType(Layer::ObjectGroupType); + push(new ChangeObjectGroupDrawOrder(mapDocument(), objectGroups, value)); + }); + + mObjectGroupProperties = new GroupProperty(tr("Object Layer")); + mObjectGroupProperties->addProperty(mColorProperty); + mObjectGroupProperties->addProperty(mDrawOrderProperty); + + addProperty(mObjectGroupProperties); + } + +private: + void onChanged(const ChangeEvent &event) override + { + LayerProperties::onChanged(event); + + if (event.type != ChangeEvent::ObjectGroupChanged) + return; + + const auto &layerChange = static_cast(event); + if (layerChange.objectGroup != objectGroup()) + return; + + if (layerChange.properties & ObjectGroupChangeEvent::ColorProperty) + emit mColorProperty->valueChanged(); + if (layerChange.properties & ObjectGroupChangeEvent::DrawOrderProperty) + emit mDrawOrderProperty->valueChanged(); + } + + ObjectGroup *objectGroup() const + { + return static_cast(mObject); + } + + GroupProperty *mObjectGroupProperties; + Property *mColorProperty; + Property *mDrawOrderProperty; +}; + +class TilesetProperties : public ObjectProperties +{ + Q_OBJECT + +public: + TilesetProperties(TilesetDocument *document, QObject *parent = nullptr) + : ObjectProperties(document, document->tileset().data(), parent) + { + mNameProperty = new StringProperty( + tr("Name"), + [this] { + return tilesetDocument()->tileset()->name(); + }, + [this](const QString &value) { + push(new RenameTileset(tilesetDocument(), value)); + }); + + mObjectAlignmentProperty = new EnumProperty( + tr("Object Alignment"), + [this] { + return tileset()->objectAlignment(); + }, + [this](Alignment value) { + push(new ChangeTilesetObjectAlignment(tilesetDocument(), value)); + }); + + mTileOffsetProperty = new PointProperty( + tr("Drawing Offset"), + [this] { + return tileset()->tileOffset(); + }, + [this](const QPoint &value) { + push(new ChangeTilesetTileOffset(tilesetDocument(), value)); + }); + mTileOffsetProperty->setSuffix(tr(" px")); + + mTileRenderSizeProperty = new EnumProperty( + tr("Tile Render Size"), + [this] { + return tileset()->tileRenderSize(); + }, + [this](Tileset::TileRenderSize value) { + push(new ChangeTilesetTileRenderSize(tilesetDocument(), value)); + }); + + mFillModeProperty = new EnumProperty( + tr("Fill Mode"), + [this] { + return tileset()->fillMode(); + }, + [this](Tileset::FillMode value) { + push(new ChangeTilesetFillMode(tilesetDocument(), value)); + }); + + mBackgroundColorProperty = new ColorProperty( + tr("Background Color"), + [this] { + return tileset()->backgroundColor(); + }, + [this](const QColor &value) { + push(new ChangeTilesetBackgroundColor(tilesetDocument(), value)); + }); + + mOrientationProperty = new EnumProperty( + tr("Orientation"), + [this] { + return tileset()->orientation(); + }, + [this](Tileset::Orientation value) { + push(new ChangeTilesetOrientation(tilesetDocument(), value)); + }); + + mGridSizeProperty = new SizeProperty( + tr("Grid Size"), + [this] { + return tileset()->gridSize(); + }, + [this](const QSize &value) { + push(new ChangeTilesetGridSize(tilesetDocument(), value)); + }); + mGridSizeProperty->setMinimum(1); + mGridSizeProperty->setSuffix(tr(" px")); + + mColumnCountProperty = new IntProperty( + tr("Columns"), + [this] { + return tileset()->columnCount(); + }, + [this](const int &value) { + push(new ChangeTilesetColumnCount(tilesetDocument(), value)); + }); + mColumnCountProperty->setMinimum(1); + + mAllowedTransformationsProperty = new TransformationFlagsProperty( + tr("Allowed Transformations"), + [this] { + return tileset()->transformationFlags(); + }, + [this](const Tileset::TransformationFlags &value) { + push(new ChangeTilesetTransformationFlags(tilesetDocument(), value)); + }); + + // todo: image file name doesn't update in the TilesetParametersEdit + mTilesetImageProperty = new TilesetImageProperty(document, this); + + mImageProperty = new UrlProperty( + tr("Image"), + [this] { return tileset()->imageSource(); }); + + mTransparentColorProperty = new ColorProperty( + tr("Transparent Color"), + [this] { return tileset()->transparentColor(); }); + + mTileSizeProperty = new SizeProperty( + tr("Tile Size"), + [this] { return tileset()->tileSize(); }); + + mMarginProperty = new IntProperty( + tr("Margin"), + [this] { return tileset()->margin(); }); + + mTileSpacingProperty = new IntProperty( + tr("Spacing"), + [this] { return tileset()->tileSpacing(); }); + + mTileSizeProperty->setSuffix(tr(" px")); + mMarginProperty->setSuffix(tr(" px")); + mTileSpacingProperty->setSuffix(tr(" px")); + + mImageProperty->setEnabled(false); + mTransparentColorProperty->setEnabled(false); + mTileSizeProperty->setEnabled(false); + mMarginProperty->setEnabled(false); + mTileSpacingProperty->setEnabled(false); + + mTilesetImageProperty->addProperty(mImageProperty); + mTilesetImageProperty->addProperty(mTransparentColorProperty); + mTilesetImageProperty->addProperty(mTileSizeProperty); + mTilesetImageProperty->addProperty(mMarginProperty); + mTilesetImageProperty->addProperty(mTileSpacingProperty); + + mTilesetProperties = new GroupProperty(tr("Tileset")); + mTilesetProperties->addProperty(mNameProperty); + mTilesetProperties->addProperty(mClassProperty); + mTilesetProperties->addSeparator(); + mTilesetProperties->addProperty(mObjectAlignmentProperty); + mTilesetProperties->addProperty(mTileOffsetProperty); + mTilesetProperties->addProperty(mTileRenderSizeProperty); + mTilesetProperties->addProperty(mFillModeProperty); + mTilesetProperties->addProperty(mBackgroundColorProperty); + mTilesetProperties->addProperty(mOrientationProperty); + mTilesetProperties->addProperty(mGridSizeProperty); + mTilesetProperties->addProperty(mColumnCountProperty); + mTilesetProperties->addProperty(mAllowedTransformationsProperty); + + if (!tileset()->isCollection()) + mTilesetProperties->addProperty(mTilesetImageProperty); + + addProperty(mTilesetProperties); + + updateEnabledState(); + connect(tilesetDocument(), &Document::changed, + this, &TilesetProperties::onChanged); + + connect(tilesetDocument(), &TilesetDocument::tilesetNameChanged, + mNameProperty, &Property::valueChanged); + connect(tilesetDocument(), &TilesetDocument::tilesetTileOffsetChanged, + mTileOffsetProperty, &Property::valueChanged); + connect(tilesetDocument(), &TilesetDocument::tilesetObjectAlignmentChanged, + mObjectAlignmentProperty, &Property::valueChanged); + connect(tilesetDocument(), &TilesetDocument::tilesetChanged, + this, &TilesetProperties::onTilesetChanged); + } + +private: + void onChanged(const ChangeEvent &event) + { + if (event.type != ChangeEvent::TilesetChanged) + return; + + const auto property = static_cast(event).property; + switch (property) { + case Tileset::FillModeProperty: + emit mFillModeProperty->valueChanged(); + break; + case Tileset::TileRenderSizeProperty: + emit mTileRenderSizeProperty->valueChanged(); + break; + } + } + + void onTilesetChanged(Tileset *) + { + // the following properties have no specific change events + emit mBackgroundColorProperty->valueChanged(); + emit mOrientationProperty->valueChanged(); + emit mGridSizeProperty->valueChanged(); + emit mColumnCountProperty->valueChanged(); + emit mAllowedTransformationsProperty->valueChanged(); + emit mImageProperty->valueChanged(); + emit mTransparentColorProperty->valueChanged(); + emit mTileSizeProperty->valueChanged(); + emit mMarginProperty->valueChanged(); + emit mTileSpacingProperty->valueChanged(); + } + + void updateEnabledState() + { + const bool collection = tileset()->isCollection(); + mColumnCountProperty->setEnabled(collection); + } + + TilesetDocument *tilesetDocument() const + { + return static_cast(mDocument); + } + + Tileset *tileset() const + { + return tilesetDocument()->tileset().data(); + } + + GroupProperty *mTilesetProperties; + Property *mNameProperty; + Property *mObjectAlignmentProperty; + PointProperty *mTileOffsetProperty; + Property *mTileRenderSizeProperty; + Property *mFillModeProperty; + Property *mBackgroundColorProperty; + Property *mOrientationProperty; + SizeProperty *mGridSizeProperty; + IntProperty *mColumnCountProperty; + Property *mAllowedTransformationsProperty; + GroupProperty *mTilesetImageProperty; + Property *mImageProperty; + Property *mTransparentColorProperty; + SizeProperty *mTileSizeProperty; + IntProperty *mMarginProperty; + IntProperty *mTileSpacingProperty; +}; + +class MapObjectProperties : public ObjectProperties +{ + Q_OBJECT + +public: + MapObjectProperties(MapDocument *document, MapObject *object, QObject *parent = nullptr) + : ObjectProperties(document, object, parent) + { + mIdProperty = new IntProperty( + tr("ID"), + [this] { return mapObject()->id(); }); + mIdProperty->setEnabled(false); + + mTemplateProperty = new UrlProperty( + tr("Template"), + [this] { + if (auto objectTemplate = mapObject()->objectTemplate()) + return QUrl::fromLocalFile(objectTemplate->fileName()); + return QUrl(); + }); + mTemplateProperty->setEnabled(false); + + mNameProperty = new StringProperty( + tr("Name"), + [this] { + return mapObject()->name(); + }, + [this](const QString &value) { + changeMapObject(MapObject::NameProperty, value); + }); + + mVisibleProperty = new BoolProperty( + tr("Visible"), + [this] { + return mapObject()->isVisible(); + }, + [this](const bool &value) { + changeMapObject(MapObject::VisibleProperty, value); + }); + mVisibleProperty->setNameOnCheckBox(true); + + mPositionProperty = new PointFProperty( + tr("Position"), + [this] { + return mapObject()->position(); + }, + [this](const QPointF &value) { + const auto oldValue = mapObject()->position(); + const bool changedX = oldValue.x() != value.x(); + const bool changedY = oldValue.y() != value.y(); + + auto objects = mapDocument()->selectedObjects(); + QVector states; + states.reserve(objects.size()); + + for (MapObject *object : objects) { + states.append(TransformState(object)); + auto &state = states.last(); + + auto position = state.position(); + + if (changedX) + position.setX(value.x()); + if (changedY) + position.setY(value.y()); + + state.setPosition(position); + } + + push(new TransformMapObjects(mDocument, objects, states)); + }); + + mBoundsProperty = new RectFProperty( + tr("Geometry"), + [this] { + return mapObject()->bounds(); + }, + [this](const QRectF &value) { + const auto oldValue = mapObject()->bounds(); + const bool changedX = oldValue.x() != value.x(); + const bool changedY = oldValue.y() != value.y(); + const bool changedWidth = oldValue.width() != value.width(); + const bool changedHeight = oldValue.height() != value.height(); + + auto objects = mapDocument()->selectedObjects(); + QVector states; + states.reserve(objects.size()); + + for (MapObject *object : objects) { + states.append(TransformState(object)); + auto &state = states.last(); + + auto position = state.position(); + auto size = state.size(); + + if (changedX) + position.setX(value.x()); + if (changedY) + position.setY(value.y()); + if (changedWidth && object->hasDimensions()) + size.setWidth(value.width()); + if (changedHeight && object->hasDimensions()) + size.setHeight(value.height()); + + state.setPosition(position); + state.setSize(size); + } + + push(new TransformMapObjects(mDocument, objects, states)); + }); + + mRotationProperty = new FloatProperty( + tr("Rotation"), + [this] { + return mapObject()->rotation(); + }, + [this](const qreal &value) { + changeMapObject(MapObject::RotationProperty, value); + }, + this); + mRotationProperty->setSuffix(QStringLiteral("°")); + + mFlippingProperty = new FlippingProperty( + tr("Flipping"), + [this] { + return mapObject()->cell().flags(); + }, + [this](const int &value) { + const int oldValue = mapObject()->cell().flags(); + const bool changedHorizontally = (oldValue & 1) != (value & 1); + const bool changedVertically = (oldValue & 2) != (value & 2); + + QVector objectChanges; + + for (MapObject *object : mapDocument()->selectedObjects()) { + MapObjectCell mapObjectCell; + mapObjectCell.object = object; + mapObjectCell.cell = object->cell(); + if (changedHorizontally) + mapObjectCell.cell.setFlippedHorizontally(value & 1); + if (changedVertically) + mapObjectCell.cell.setFlippedVertically(value & 2); + objectChanges.append(mapObjectCell); + } + + auto command = new ChangeMapObjectCells(mDocument, objectChanges); + + command->setText(QCoreApplication::translate("Undo Commands", + "Flip %n Object(s)", + nullptr, + objectChanges.size())); + push(command); + }); + + mTextProperty = new MultilineStringProperty( + tr("Text"), + [this] { + return mapObject()->textData().text; + }, + [this](const QString &value) { + changeMapObject(MapObject::TextProperty, value); + }); + + mTextAlignmentProperty = new QtAlignmentProperty( + tr("Alignment"), + [this] { + return mapObject()->textData().alignment; + }, + [this](const Qt::Alignment &value) { + changeMapObject(MapObject::TextAlignmentProperty, + QVariant::fromValue(value)); + }); + + mTextFontProperty = new FontProperty( + tr("Font"), + [this] { + return mapObject()->textData().font; + }, + [this](const QFont &value) { + changeMapObject(MapObject::TextFontProperty, value); + }); + + mTextWordWrapProperty = new BoolProperty( + tr("Word Wrap"), + [this] { + return mapObject()->textData().wordWrap; + }, + [this](const bool &value) { + changeMapObject(MapObject::TextWordWrapProperty, value); + }); + + mTextColorProperty = new ColorProperty( + tr("Text Color"), + [this] { + return mapObject()->textData().color; + }, + [this](const QColor &value) { + changeMapObject(MapObject::TextColorProperty, value); + }); + + mObjectProperties = new GroupProperty(tr("Object")); + mObjectProperties->addProperty(mIdProperty); + mObjectProperties->addProperty(mTemplateProperty); + mObjectProperties->addProperty(mNameProperty); + mObjectProperties->addProperty(mClassProperty); + mObjectProperties->addSeparator(); + + if (mapDocument()->allowHidingObjects()) + mObjectProperties->addProperty(mVisibleProperty); + + if (mapObject()->hasDimensions()) + mObjectProperties->addProperty(mBoundsProperty); + else + mObjectProperties->addProperty(mPositionProperty); + + if (mapObject()->canRotate()) + mObjectProperties->addProperty(mRotationProperty); + + if (mapObject()->isTileObject()) { + mObjectProperties->addSeparator(); + mObjectProperties->addProperty(mFlippingProperty); + } + + if (mapObject()->shape() == MapObject::Text) { + mObjectProperties->addSeparator(); + mObjectProperties->addProperty(mTextProperty); + mObjectProperties->addProperty(mTextAlignmentProperty); + mObjectProperties->addProperty(mTextFontProperty); + mObjectProperties->addProperty(mTextWordWrapProperty); + mObjectProperties->addProperty(mTextColorProperty); + } + + addProperty(mObjectProperties); + + connect(document, &Document::changed, + this, &MapObjectProperties::onChanged); + + updateEnabledState(); + } + +private: + void onChanged(const ChangeEvent &event) + { + if (event.type != ChangeEvent::MapObjectsChanged) + return; + + const auto &change = static_cast(event); + if (!change.mapObjects.contains(mapObject())) + return; + + if (change.properties & MapObject::NameProperty) + emit mNameProperty->valueChanged(); + if (change.properties & MapObject::VisibleProperty) + emit mVisibleProperty->valueChanged(); + if (change.properties & MapObject::PositionProperty) { + emit mPositionProperty->valueChanged(); + emit mBoundsProperty->valueChanged(); + } + if (change.properties & MapObject::SizeProperty) + emit mBoundsProperty->valueChanged(); + if (change.properties & MapObject::RotationProperty) + emit mRotationProperty->valueChanged(); + if (change.properties & MapObject::CellProperty) + emit mFlippingProperty->valueChanged(); + if (change.properties & MapObject::TextProperty) + emit mTextProperty->valueChanged(); + if (change.properties & MapObject::TextFontProperty) + emit mTextFontProperty->valueChanged(); + if (change.properties & MapObject::TextAlignmentProperty) + emit mTextAlignmentProperty->valueChanged(); + if (change.properties & MapObject::TextWordWrapProperty) + emit mTextWordWrapProperty->valueChanged(); + if (change.properties & MapObject::TextColorProperty) + emit mTextColorProperty->valueChanged(); + } + + void updateEnabledState() + { + mVisibleProperty->setEnabled(mapDocument()->allowHidingObjects()); + mBoundsProperty->setEnabled(mapObject()->hasDimensions()); + mRotationProperty->setEnabled(mapObject()->canRotate()); + mFlippingProperty->setEnabled(mapObject()->isTileObject()); + + const bool isText = mapObject()->shape() == MapObject::Text; + mTextProperty->setEnabled(isText); + mTextAlignmentProperty->setEnabled(isText); + mTextFontProperty->setEnabled(isText); + mTextWordWrapProperty->setEnabled(isText); + mTextColorProperty->setEnabled(isText); + } + + MapDocument *mapDocument() const + { + return static_cast(mDocument); + } + + MapObject *mapObject() const + { + return static_cast(mObject); + } + + void changeMapObject(MapObject::Property property, const QVariant &value) + { + QUndoCommand *command = new ChangeMapObject(mapDocument(), mapObject(), + property, value); + + if (mapDocument()->selectedObjects().size() == 1) { + push(command); + return; + } + + auto undoStack = mDocument->undoStack(); + undoStack->beginMacro(command->text()); + undoStack->push(command); + + for (MapObject *obj : mapDocument()->selectedObjects()) { + if (obj != mapObject()) { + QUndoCommand *cmd = new ChangeMapObject(mapDocument(), obj, + property, value); + undoStack->push(cmd); + } + } + + mDocument->undoStack()->endMacro(); + } + + GroupProperty *mObjectProperties; + Property *mIdProperty; + Property *mTemplateProperty; + Property *mNameProperty; + BoolProperty *mVisibleProperty; + Property *mPositionProperty; + Property *mBoundsProperty; + FloatProperty *mRotationProperty; + + // for tile objects + Property *mFlippingProperty; + + // for text objects + Property *mTextProperty; + Property *mTextAlignmentProperty; + Property *mTextFontProperty; + Property *mTextWordWrapProperty; + Property *mTextColorProperty; +}; + +class TileProperties : public ObjectProperties +{ + Q_OBJECT + +public: + TileProperties(Document *document, Tile *object, QObject *parent = nullptr) + : ObjectProperties(document, object, parent) + { + mIdProperty = new IntProperty( + tr("ID"), + [this] { return tile()->id(); }); + mIdProperty->setEnabled(false); + + mImageProperty = new UrlProperty( + tr("Image"), + [this] { return tile()->imageSource(); }, + [this](const QUrl &value) { + push(new ChangeTileImageSource(tilesetDocument(), + tile(), + value)); + }); + mImageProperty->setFilter(Utils::readableImageFormatsFilter()); + + mRectangleProperty = new RectProperty( + tr("Rectangle"), + [this] { return tile()->imageRect(); }, + [this](const QRect &value) { + push(new ChangeTileImageRect(tilesetDocument(), + { tile() }, + { value })); + }); + mRectangleProperty->setConstraint(object->image().rect()); + + mProbabilityProperty = new FloatProperty( + tr("Probability"), + [this] { return tile()->probability(); }, + [this](const double &value) { + push(new ChangeTileProbability(tilesetDocument(), + tilesetDocument()->selectedTiles(), + value)); + }); + mProbabilityProperty->setToolTip(tr("Relative chance this tile will be picked")); + mProbabilityProperty->setMinimum(0.0); + + mTileProperties = new GroupProperty(tr("Tile")); + mTileProperties->addProperty(mIdProperty); + mTileProperties->addProperty(mClassProperty); + mTileProperties->addSeparator(); + + if (!tile()->imageSource().isEmpty()) + mTileProperties->addProperty(mImageProperty); + + mTileProperties->addProperty(mRectangleProperty); + mTileProperties->addProperty(mProbabilityProperty); + + addProperty(mTileProperties); + + // annoying... maybe we should somehow always have the relevant TilesetDocument + if (auto tilesetDocument = qobject_cast(document)) { + connect(tilesetDocument, &TilesetDocument::tileImageSourceChanged, + this, &TileProperties::tileImageSourceChanged); + + connect(tilesetDocument, &TilesetDocument::tileProbabilityChanged, + this, &TileProperties::tileProbabilityChanged); + } else if (auto mapDocument = qobject_cast(document)) { + connect(mapDocument, &MapDocument::tileImageSourceChanged, + this, &TileProperties::tileImageSourceChanged); + + connect(mapDocument, &MapDocument::tileProbabilityChanged, + this, &TileProperties::tileProbabilityChanged); + } + + updateEnabledState(); + } + +private: + void tileImageSourceChanged(Tile *tile) + { + if (tile != this->tile()) + return; + mRectangleProperty->setConstraint(tile->image().rect()); + emit mImageProperty->valueChanged(); + emit mRectangleProperty->valueChanged(); + } + + void tileProbabilityChanged(Tile *tile) + { + if (tile != this->tile()) + return; + emit mProbabilityProperty->valueChanged(); + } + + void updateEnabledState() + { + const bool hasTilesetDocument = tilesetDocument(); + const auto isCollection = tile()->tileset()->isCollection(); + mClassProperty->setEnabled(hasTilesetDocument); + mImageProperty->setEnabled(hasTilesetDocument && isCollection); + mRectangleProperty->setEnabled(hasTilesetDocument && isCollection); + mProbabilityProperty->setEnabled(hasTilesetDocument); + } + + TilesetDocument *tilesetDocument() const + { + return qobject_cast(mDocument); + } + + Tile *tile() const + { + return static_cast(mObject); + } + + GroupProperty *mTileProperties; + Property *mIdProperty; + UrlProperty *mImageProperty; + RectProperty *mRectangleProperty; + FloatProperty *mProbabilityProperty; +}; + +class WangSetProperties : public ObjectProperties +{ + Q_OBJECT + +public: + WangSetProperties(Document *document, WangSet *object, + QObject *parent = nullptr) + : ObjectProperties(document, object, parent) + { + mNameProperty = new StringProperty( + tr("Name"), + [this] { return wangSet()->name(); }, + [this](const QString &value) { + push(new RenameWangSet(tilesetDocument(), wangSet(), value)); + }); + + mTypeProperty = new EnumProperty( + tr("Type"), + [this] { return wangSet()->type(); }, + [this](WangSet::Type value) { + push(new ChangeWangSetType(tilesetDocument(), wangSet(), value)); + }); + + mColorCountProperty = new IntProperty( + tr("Color Count"), + [this] { return wangSet()->colorCount(); }, + [this](const int &value) { + push(new ChangeWangSetColorCount(tilesetDocument(), + wangSet(), + value)); + }); + mColorCountProperty->setRange(0, WangId::MAX_COLOR_COUNT); + + mWangSetProperties = new GroupProperty(tr("Terrain Set")); + mWangSetProperties->addProperty(mNameProperty); + mWangSetProperties->addProperty(mClassProperty); + mWangSetProperties->addSeparator(); + mWangSetProperties->addProperty(mTypeProperty); + mWangSetProperties->addProperty(mColorCountProperty); + + addProperty(mWangSetProperties); + + connect(document, &Document::changed, + this, &WangSetProperties::onChanged); + + updateEnabledState(); + } + +private: + void onChanged(const ChangeEvent &event) + { + if (event.type != ChangeEvent::WangSetChanged) + return; + + const auto &wangSetChange = static_cast(event); + if (wangSetChange.wangSet != wangSet()) + return; + + switch (wangSetChange.property) { + case WangSetChangeEvent::NameProperty: + emit mNameProperty->valueChanged(); + break; + case WangSetChangeEvent::TypeProperty: + emit mTypeProperty->valueChanged(); + break; + case WangSetChangeEvent::ImageProperty: + break; + case WangSetChangeEvent::ColorCountProperty: + emit mColorCountProperty->valueChanged(); + break; + } + } + + void updateEnabledState() + { + const bool hasTilesetDocument = tilesetDocument(); + mNameProperty->setEnabled(hasTilesetDocument); + mTypeProperty->setEnabled(hasTilesetDocument); + mColorCountProperty->setEnabled(hasTilesetDocument); + } + + TilesetDocument *tilesetDocument() const + { + return qobject_cast(mDocument); + } + + WangSet *wangSet() + { + return static_cast(mObject); + } + + GroupProperty *mWangSetProperties; + Property *mNameProperty; + Property *mTypeProperty; + IntProperty *mColorCountProperty; +}; + +class WangColorProperties : public ObjectProperties +{ + Q_OBJECT + +public: + WangColorProperties(Document *document, WangColor *object, + QObject *parent = nullptr) + : ObjectProperties(document, object, parent) + { + mNameProperty = new StringProperty( + tr("Name"), + [this] { return wangColor()->name(); }, + [this](const QString &value) { + push(new ChangeWangColorName(tilesetDocument(), wangColor(), value)); + }); + + mColorProperty = new ColorProperty( + tr("Color"), + [this] { return wangColor()->color(); }, + [this](const QColor &value) { + push(new ChangeWangColorColor(tilesetDocument(), wangColor(), value)); + }); + + mProbabilityProperty = new FloatProperty( + tr("Probability"), + [this] { return wangColor()->probability(); }, + [this](const double &value) { + push(new ChangeWangColorProbability(tilesetDocument(), wangColor(), value)); + }); + mProbabilityProperty->setMinimum(0.01); + + mWangColorProperties = new GroupProperty(tr("Terrain")); + mWangColorProperties->addProperty(mNameProperty); + mWangColorProperties->addProperty(mClassProperty); + mWangColorProperties->addSeparator(); + mWangColorProperties->addProperty(mColorProperty); + mWangColorProperties->addProperty(mProbabilityProperty); + + addProperty(mWangColorProperties); + + connect(document, &Document::changed, + this, &WangColorProperties::onChanged); + + updateEnabledState(); + } + +private: + void onChanged(const ChangeEvent &event) + { + if (event.type != ChangeEvent::WangColorChanged) + return; + + const auto &wangColorChange = static_cast(event); + if (wangColorChange.wangColor != wangColor()) + return; + + switch (wangColorChange.property) { + case WangColorChangeEvent::NameProperty: + emit mNameProperty->valueChanged(); + break; + case WangColorChangeEvent::ColorProperty: + emit mColorProperty->valueChanged(); + break; + case WangColorChangeEvent::ImageProperty: + break; + case WangColorChangeEvent::ProbabilityProperty: + emit mProbabilityProperty->valueChanged(); + break; + } + } + + void updateEnabledState() + { + const bool hasTilesetDocument = tilesetDocument(); + mNameProperty->setEnabled(hasTilesetDocument); + mClassProperty->setEnabled(hasTilesetDocument); + mColorProperty->setEnabled(hasTilesetDocument); + mProbabilityProperty->setEnabled(hasTilesetDocument); + } + + TilesetDocument *tilesetDocument() const + { + return qobject_cast(mDocument); + } + + WangColor *wangColor() + { + return static_cast(mObject); + } + + GroupProperty *mWangColorProperties; + Property *mNameProperty; + Property *mColorProperty; + FloatProperty *mProbabilityProperty; +}; + + PropertiesWidget::PropertiesWidget(QWidget *parent) : QWidget{parent} - , mDocument(nullptr) - , mPropertyBrowser(new PropertyBrowser) + , mResetIcon(QIcon(QStringLiteral(":/images/16/edit-clear.png"))) + , mRemoveIcon(QIcon(QStringLiteral(":/images/16/remove.png"))) + , mAddIcon(QIcon(QStringLiteral(":/images/16/add.png"))) + , mRenameIcon(QIcon(QLatin1String(":/images/16/rename.png"))) + , mRootProperty(new GroupProperty()) + , mCustomProperties(new CustomProperties(mRootProperty)) + , mPropertiesView(new PropertiesView(this)) { + mResetIcon.addFile(QStringLiteral(":/images/24/edit-clear.png")); + mRemoveIcon.addFile(QStringLiteral(":/images/22/remove.png")); + mAddIcon.addFile(QStringLiteral(":/images/22/add.png")); + + mRootProperty->addProperty(mCustomProperties); + mActionAddProperty = new QAction(this); mActionAddProperty->setEnabled(false); - mActionAddProperty->setIcon(QIcon(QLatin1String(":/images/16/add.png"))); + mActionAddProperty->setIcon(mAddIcon); connect(mActionAddProperty, &QAction::triggered, - this, &PropertiesWidget::openAddPropertyDialog); + this, &PropertiesWidget::showAddValueProperty); mActionRemoveProperty = new QAction(this); mActionRemoveProperty->setEnabled(false); - mActionRemoveProperty->setIcon(QIcon(QLatin1String(":/images/16/remove.png"))); + mActionRemoveProperty->setIcon(mRemoveIcon); mActionRemoveProperty->setShortcuts(QKeySequence::Delete); + mActionRemoveProperty->setPriority(QAction::LowPriority); connect(mActionRemoveProperty, &QAction::triggered, this, &PropertiesWidget::removeProperties); mActionRenameProperty = new QAction(this); mActionRenameProperty->setEnabled(false); - mActionRenameProperty->setIcon(QIcon(QLatin1String(":/images/16/rename.png"))); + mActionRenameProperty->setIcon(mRenameIcon); + mActionRenameProperty->setPriority(QAction::LowPriority); connect(mActionRenameProperty, &QAction::triggered, - this, &PropertiesWidget::renameProperty); + this, &PropertiesWidget::renameSelectedProperty); Utils::setThemeIcon(mActionAddProperty, "add"); Utils::setThemeIcon(mActionRemoveProperty, "remove"); @@ -74,6 +2202,7 @@ PropertiesWidget::PropertiesWidget(QWidget *parent) QToolBar *toolBar = new QToolBar; toolBar->setFloatable(false); toolBar->setMovable(false); + toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); toolBar->setIconSize(Utils::smallIconSize()); toolBar->addAction(mActionAddProperty); toolBar->addAction(mActionRemoveProperty); @@ -82,14 +2211,14 @@ PropertiesWidget::PropertiesWidget(QWidget *parent) QVBoxLayout *layout = new QVBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); - layout->addWidget(mPropertyBrowser); + layout->addWidget(mPropertiesView); layout->addWidget(toolBar); setLayout(layout); - mPropertyBrowser->setContextMenuPolicy(Qt::CustomContextMenu); - connect(mPropertyBrowser, &PropertyBrowser::customContextMenuRequested, + mPropertiesView->setContextMenuPolicy(Qt::CustomContextMenu); + connect(mPropertiesView, &QWidget::customContextMenuRequested, this, &PropertiesWidget::showContextMenu); - connect(mPropertyBrowser, &PropertyBrowser::selectedItemsChanged, + connect(mPropertiesView, &PropertiesView::selectedPropertiesChanged, this, &PropertiesWidget::updateActions); retranslateUi(); @@ -98,7 +2227,7 @@ PropertiesWidget::PropertiesWidget(QWidget *parent) PropertiesWidget::~PropertiesWidget() { // Disconnect to avoid crashing due to signals emitted during destruction - mPropertyBrowser->disconnect(this); + mPropertiesView->disconnect(this); } void PropertiesWidget::setDocument(Document *document) @@ -110,13 +2239,17 @@ void PropertiesWidget::setDocument(Document *document) mDocument->disconnect(this); mDocument = document; - mPropertyBrowser->setDocument(document); + mCustomProperties->setDocument(document); if (document) { connect(document, &Document::currentObjectChanged, this, &PropertiesWidget::currentObjectChanged); connect(document, &Document::editCurrentObject, - this, &PropertiesWidget::bringToFront); + this, [this] { + if (mPropertiesObject) + mPropertiesObject->expandAll(); + emit bringToFront(); + }); connect(document, &Document::propertyAdded, this, &PropertiesWidget::updateActions); @@ -129,45 +2262,190 @@ void PropertiesWidget::setDocument(Document *document) } } -void PropertiesWidget::selectCustomProperty(const QString &name) +GroupProperty *PropertiesWidget::customPropertiesGroup() const { - mPropertyBrowser->selectCustomProperty(name); + return mCustomProperties; } -static bool anyObjectHasProperty(const QList &objects, const QString &name) +void PropertiesWidget::selectCustomProperty(const QString &name) { - for (Object *obj : objects) { - if (obj->hasProperty(name)) - return true; + if (auto property = mCustomProperties->property(name)) { + mPropertiesView->focusProperty(property); + mPropertiesView->setSelectedProperties({ property }); } - return false; } void PropertiesWidget::currentObjectChanged(Object *object) { - mPropertyBrowser->setObject(object); + if (mPropertiesObject) { + // Remember the expanded states + const auto &subProperties = mPropertiesObject->subProperties(); + for (int i = 0; i < subProperties.size(); ++i) { + if (auto subGroupProperty = qobject_cast(subProperties.at(i))) + mExpandedStates[i] = subGroupProperty->isExpanded(); + } + + mRootProperty->deleteProperty(mPropertiesObject); + mPropertiesObject = nullptr; + } + + if (object) { + switch (object->typeId()) { + case Object::LayerType: { + auto mapDocument = static_cast(mDocument); + + switch (static_cast(object)->layerType()) { + case Layer::ImageLayerType: + mPropertiesObject = new ImageLayerProperties(mapDocument, + static_cast(object), + this); + break; + case Layer::ObjectGroupType: + mPropertiesObject = new ObjectGroupProperties(mapDocument, + static_cast(object), + this); + break; + case Layer::TileLayerType: + case Layer::GroupLayerType: + mPropertiesObject = new LayerProperties(mapDocument, + static_cast(object), + this); + break; + } + break; + } + case Object::MapObjectType: + mPropertiesObject = new MapObjectProperties(static_cast(mDocument), + static_cast(object), this); + break; + case Object::MapType: + mPropertiesObject = new MapProperties(static_cast(mDocument), + this); + break; + case Object::TilesetType: + mPropertiesObject = new TilesetProperties(static_cast(mDocument), + this); + break; + case Object::TileType: + mPropertiesObject = new TileProperties(mDocument, + static_cast(object), + this); + break; + case Object::WangSetType: + mPropertiesObject = new WangSetProperties(mDocument, + static_cast(object), + this); + break; + case Object::WangColorType: + mPropertiesObject = new WangColorProperties(mDocument, + static_cast(object), + this); + break; + case Object::ProjectType: + case Object::WorldType: + // these types are currently not handled by the Properties dock + break; + } + } + + // Restore the expanded states + if (mPropertiesObject) { + const auto &subProperties = mPropertiesObject->subProperties(); + for (int i = 0; i < subProperties.size(); ++i) { + if (auto subGroupProperty = qobject_cast(subProperties.at(i))) + subGroupProperty->setExpanded(mExpandedStates.value(i, true)); + } + + mRootProperty->insertProperty(0, mPropertiesObject); + } + + mPropertiesView->setRootProperty(object ? mRootProperty : nullptr); bool editingTileset = mDocument && mDocument->type() == Document::TilesetDocumentType; bool isTileset = object && object->isPartOfTileset(); bool enabled = object && (!isTileset || editingTileset); - mPropertyBrowser->setEnabled(object); + mPropertiesView->setEnabled(object); mActionAddProperty->setEnabled(enabled); } + +void CustomProperties::setDocument(Document *document) +{ + if (mDocument == document) + return; + + if (mDocument) + mDocument->disconnect(this); + + mDocument = document; + + if (document) { + connect(document, &Document::changed, this, &CustomProperties::onChanged); + + connect(document, &Document::currentObjectsChanged, this, &CustomProperties::refresh); + + connect(document, &Document::propertyAdded, this, &CustomProperties::propertyAdded); + connect(document, &Document::propertyRemoved, this, &CustomProperties::propertyRemoved); + connect(document, &Document::propertyChanged, this, &CustomProperties::propertyChanged); + connect(document, &Document::propertiesChanged, this, &CustomProperties::propertiesChanged); + } + + refresh(); +} + +void CustomProperties::refresh() +{ + if (!mDocument || !mDocument->currentObject()) { + setValue({}); + return; + } + + const Properties ¤tObjectProperties = mDocument->currentObject()->properties(); + + // Suggest properties from selected objects. + Properties suggestedProperties; + const auto currentObjects = mDocument->currentObjects(); + for (auto object : currentObjects) + if (object != mDocument->currentObject()) + mergeProperties(suggestedProperties, object->properties()); + + // Suggest properties inherited from the class, tile or template. + mergeProperties(suggestedProperties, + mDocument->currentObject()->inheritedProperties()); + + setValue(currentObjectProperties, suggestedProperties); + + const bool editingTileset = mDocument->type() == Document::TilesetDocumentType; + const bool partOfTileset = mDocument->currentObject()->isPartOfTileset(); + setEnabled(!partOfTileset || editingTileset); +} + +void CustomProperties::setPropertyValue(const QStringList &path, const QVariant &value) +{ + const auto objects = mDocument->currentObjects(); + if (!objects.isEmpty()) { + QScopedValueRollback updating(mUpdating, true); + if (path.size() > 1 || value.isValid()) + mDocument->undoStack()->push(new SetProperty(mDocument, objects, path, value)); + else + mDocument->undoStack()->push(new RemoveProperty(mDocument, objects, path.first())); + } +} + + void PropertiesWidget::updateActions() { - const QList items = mPropertyBrowser->selectedItems(); - bool allCustomProperties = !items.isEmpty() && mPropertyBrowser->allCustomPropertyItems(items); + const auto properties = mPropertiesView->selectedProperties(); bool editingTileset = mDocument && mDocument->type() == Document::TilesetDocumentType; - bool isTileset = mPropertyBrowser->object() && mPropertyBrowser->object()->isPartOfTileset(); - bool canModify = allCustomProperties && (!isTileset || editingTileset); + bool isTileset = mDocument && mDocument->currentObject() && mDocument->currentObject()->isPartOfTileset(); + bool canModify = !properties.isEmpty() && (!isTileset || editingTileset); // Disable remove and rename actions when none of the selected objects // actually have the selected property (it may be inherited). if (canModify) { - for (QtBrowserItem *item : items) { - if (!anyObjectHasProperty(mDocument->currentObjects(), item->property()->propertyName())) { + for (auto property : properties) { + if (!anyObjectHasProperty(mDocument->currentObjects(), property->name())) { canModify = false; break; } @@ -175,7 +2453,7 @@ void PropertiesWidget::updateActions() } mActionRemoveProperty->setEnabled(canModify); - mActionRenameProperty->setEnabled(canModify && items.size() == 1); + mActionRenameProperty->setEnabled(canModify && properties.size() == 1); } void PropertiesWidget::cutProperties() @@ -186,18 +2464,17 @@ void PropertiesWidget::cutProperties() bool PropertiesWidget::copyProperties() { - Object *object = mPropertyBrowser->object(); + Object *object = mDocument ? mDocument->currentObject() : nullptr; if (!object) return false; - Properties properties; - - const QList items = mPropertyBrowser->selectedItems(); - for (QtBrowserItem *item : items) { - if (!mPropertyBrowser->isCustomPropertyItem(item)) - return false; + const auto selectedProperties = mPropertiesView->selectedProperties(); + if (selectedProperties.isEmpty()) + return false; - const QString name = item->property()->propertyName(); + Properties properties; + for (auto property : selectedProperties) { + const QString name = property->name(); const QVariant value = object->property(name); if (!value.isValid()) return false; @@ -206,6 +2483,7 @@ bool PropertiesWidget::copyProperties() } ClipboardManager::instance()->setProperties(properties); + return true; } @@ -244,14 +2522,40 @@ void PropertiesWidget::pasteProperties() undoStack->push(command); undoStack->endMacro(); + + // Make sure Custom Properties are expanded + mCustomProperties->setExpanded(true); + } + + // Select the pasted properties + QList selectedProperties; + for (const QString &name : pastedProperties.keys()) { + if (auto property = mCustomProperties->property(name)) + selectedProperties.append(property); + } + if (!selectedProperties.isEmpty()) { + mPropertiesView->focusProperty(selectedProperties.first(), PropertiesView::FocusRow); + mPropertiesView->setSelectedProperties(selectedProperties); } } -void PropertiesWidget::openAddPropertyDialog() +void PropertiesWidget::showAddValueProperty() { - AddPropertyDialog dialog(mPropertyBrowser); - if (dialog.exec() == AddPropertyDialog::Accepted) - addProperty(dialog.propertyName(), dialog.propertyValue()); + if (!mAddValueProperty) { + mAddValueProperty = new AddValueProperty(mCustomProperties); + + connect(mAddValueProperty, &Property::addRequested, this, [this] { + addProperty(mAddValueProperty->name(), mAddValueProperty->value()); + mCustomProperties->deleteProperty(mAddValueProperty); + }); + connect(mAddValueProperty, &Property::removeRequested, this, [this] { + mCustomProperties->deleteProperty(mAddValueProperty); + }); + + mCustomProperties->addProperty(mAddValueProperty); + } + + mPropertiesView->focusProperty(mAddValueProperty, PropertiesView::FocusLabel); } void PropertiesWidget::addProperty(const QString &name, const QVariant &value) @@ -269,7 +2573,7 @@ void PropertiesWidget::addProperty(const QString &name, const QVariant &value) name, value)); } - mPropertyBrowser->editCustomProperty(name); + selectCustomProperty(name); } void PropertiesWidget::removeProperties() @@ -278,13 +2582,11 @@ void PropertiesWidget::removeProperties() if (!object) return; - const QList items = mPropertyBrowser->selectedItems(); - if (items.isEmpty() || !mPropertyBrowser->allCustomPropertyItems(items)) - return; + const auto properties = mPropertiesView->selectedProperties(); QStringList propertyNames; - for (QtBrowserItem *item : items) - propertyNames.append(item->property()->propertyName()); + for (auto property : properties) + propertyNames.append(property->name()); QUndoStack *undoStack = mDocument->undoStack(); undoStack->beginMacro(QCoreApplication::translate("Tiled::PropertiesDock", @@ -301,39 +2603,35 @@ void PropertiesWidget::removeProperties() undoStack->endMacro(); } -void PropertiesWidget::renameProperty() +void PropertiesWidget::renameSelectedProperty() { - QtBrowserItem *item = mPropertyBrowser->currentItem(); - if (!mPropertyBrowser->isCustomPropertyItem(item)) + const auto properties = mPropertiesView->selectedProperties(); + if (properties.size() != 1) return; - const QString oldName = item->property()->propertyName(); + renameProperty(properties.first()->name()); +} - QInputDialog *dialog = new QInputDialog(mPropertyBrowser); +void PropertiesWidget::renameProperty(const QString &name) +{ + QInputDialog *dialog = new QInputDialog(mPropertiesView); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->setInputMode(QInputDialog::TextInput); dialog->setLabelText(QCoreApplication::translate("Tiled::PropertiesDock", "Name:")); - dialog->setTextValue(oldName); + dialog->setTextValue(name); dialog->setWindowTitle(QCoreApplication::translate("Tiled::PropertiesDock", "Rename Property")); - connect(dialog, &QInputDialog::textValueSelected, this, &PropertiesWidget::renamePropertyTo); - dialog->open(); -} -void PropertiesWidget::renamePropertyTo(const QString &name) -{ - if (name.isEmpty()) - return; - - QtBrowserItem *item = mPropertyBrowser->currentItem(); - if (!item) - return; + connect(dialog, &QInputDialog::textValueSelected, this, [=] (const QString &newName) { + if (newName.isEmpty()) + return; + if (newName == name) + return; - const QString oldName = item->property()->propertyName(); - if (oldName == name) - return; + QUndoStack *undoStack = mDocument->undoStack(); + undoStack->push(new RenameProperty(mDocument, mDocument->currentObjects(), name, newName)); + }); - QUndoStack *undoStack = mDocument->undoStack(); - undoStack->push(new RenameProperty(mDocument, mDocument->currentObjects(), oldName, name)); + dialog->open(); } void PropertiesWidget::showContextMenu(const QPoint &pos) @@ -342,43 +2640,43 @@ void PropertiesWidget::showContextMenu(const QPoint &pos) if (!object) return; - const QList items = mPropertyBrowser->selectedItems(); - const bool customPropertiesSelected = !items.isEmpty() && mPropertyBrowser->allCustomPropertyItems(items); + const auto properties = mPropertiesView->selectedProperties(); + const bool customPropertiesSelected = !properties.isEmpty(); bool currentObjectHasAllProperties = true; QStringList propertyNames; - for (QtBrowserItem *item : items) { - const QString propertyName = item->property()->propertyName(); - propertyNames.append(propertyName); + for (auto property : properties) { + propertyNames.append(property->name()); - if (!object->hasProperty(propertyName)) + if (!object->hasProperty(property->name())) currentObjectHasAllProperties = false; } - QMenu contextMenu(mPropertyBrowser); + QMenu contextMenu(mPropertiesView); + + // Add properties specific to the just clicked property + if (auto focusedProperty = mPropertiesView->focusedProperty()) { + focusedProperty->addContextMenuActions(&contextMenu); - if (customPropertiesSelected && propertyNames.size() == 1) { - const auto value = object->resolvedProperty(propertyNames.first()); - if (value.userType() == filePathTypeId()) { - const FilePath filePath = value.value(); - const QString localFile = filePath.url.toLocalFile(); + // Provide the Add, Remove and Reset actions also here + if (const auto actions = focusedProperty->actions()) { + if (!contextMenu.isEmpty()) + contextMenu.addSeparator(); - if (!localFile.isEmpty()) { - Utils::addOpenContainingFolderAction(contextMenu, localFile); + // Note: No "Remove" added here since it's covered below - if (QFileInfo { localFile }.isFile()) - Utils::addOpenWithSystemEditorAction(contextMenu, localFile); + if (actions.testFlag(Property::Action::Add)) { + QAction *add = contextMenu.addAction(mAddIcon, tr("Add"), + focusedProperty, &Property::addRequested); + add->setEnabled(!actions.testFlag(Property::Action::AddDisabled)); + Utils::setThemeIcon(add, "add"); } - } else if (value.userType() == objectRefTypeId()) { - if (auto mapDocument = qobject_cast(mDocument)) { - const DisplayObjectRef objectRef(value.value(), mapDocument); - - contextMenu.addAction(QCoreApplication::translate("Tiled::PropertiesDock", "Go to Object"), [=] { - if (auto object = objectRef.object()) { - objectRef.mapDocument->setSelectedObjects({object}); - emit objectRef.mapDocument->focusMapObjectRequested(object); - } - })->setEnabled(objectRef.object()); + + if (actions.testFlag(Property::Action::Reset)) { + QAction *reset = contextMenu.addAction(mResetIcon, tr("Reset"), + focusedProperty, &Property::resetRequested); + reset->setEnabled(focusedProperty->isModified()); + Utils::setThemeIcon(reset, "edit-clear"); } } } @@ -454,12 +2752,12 @@ void PropertiesWidget::showContextMenu(const QPoint &pos) ActionManager::applyMenuExtensions(&contextMenu, MenuIds::propertiesViewProperties); - const QPoint globalPos = mPropertyBrowser->mapToGlobal(pos); + const QPoint globalPos = mPropertiesView->mapToGlobal(pos); const QAction *selectedItem = contextMenu.exec(globalPos); if (selectedItem && convertMenu && selectedItem->parentWidget() == convertMenu) { QUndoStack *undoStack = mDocument->undoStack(); - undoStack->beginMacro(QCoreApplication::translate("Tiled::PropertiesDock", "Convert Property/Properties", nullptr, items.size())); + undoStack->beginMacro(QCoreApplication::translate("Tiled::PropertiesDock", "Convert Property/Properties", nullptr, properties.size())); for (const QString &propertyName : propertyNames) { QVariant propertyValue = object->property(propertyName); @@ -473,6 +2771,15 @@ void PropertiesWidget::showContextMenu(const QPoint &pos) } undoStack->endMacro(); + + // Restore selected properties + QList selectedProperties; + for (const QString &name : propertyNames) { + if (auto property = mCustomProperties->property(name)) + selectedProperties.append(property); + } + if (!selectedProperties.isEmpty()) + mPropertiesView->setSelectedProperties(selectedProperties); } } @@ -529,3 +2836,4 @@ void PropertiesWidget::retranslateUi() } // namespace Tiled #include "moc_propertieswidget.cpp" +#include "propertieswidget.moc" diff --git a/src/tiled/propertieswidget.h b/src/tiled/propertieswidget.h index 022a520b2f..ccb8f67302 100644 --- a/src/tiled/propertieswidget.h +++ b/src/tiled/propertieswidget.h @@ -20,17 +20,25 @@ #pragma once +#include +#include #include +class QScrollArea; + namespace Tiled { class Object; +class AddValueProperty; +class CustomProperties; class Document; -class PropertyBrowser; +class GroupProperty; +class ObjectProperties; +class PropertiesView; /** - * The PropertiesWidget combines the PropertyBrowser with some controls that + * The PropertiesWidget combines the PropertiesView with some controls that * allow adding and removing properties. It also implements cut, copy and paste * actions and the context menu. */ @@ -47,6 +55,9 @@ class PropertiesWidget : public QWidget */ void setDocument(Document *document); + GroupProperty *customPropertiesGroup() const; + PropertiesView *propertiesView() const { return mPropertiesView; } + signals: void bringToFront(); @@ -64,17 +75,26 @@ public slots: void cutProperties(); bool copyProperties(); void pasteProperties(); - void openAddPropertyDialog(); + void showAddValueProperty(); void addProperty(const QString &name, const QVariant &value); void removeProperties(); - void renameProperty(); - void renamePropertyTo(const QString &name); + void renameSelectedProperty(); + void renameProperty(const QString &name); void showContextMenu(const QPoint &pos); void retranslateUi(); - Document *mDocument; - PropertyBrowser *mPropertyBrowser; + QIcon mResetIcon; + QIcon mRemoveIcon; + QIcon mAddIcon; + QIcon mRenameIcon; + Document *mDocument = nullptr; + GroupProperty *mRootProperty = nullptr; + ObjectProperties *mPropertiesObject = nullptr; + CustomProperties *mCustomProperties = nullptr; + QPointer mAddValueProperty; + QMap mExpandedStates; + PropertiesView *mPropertiesView; QAction *mActionAddProperty; QAction *mActionRemoveProperty; QAction *mActionRenameProperty; diff --git a/src/tiled/propertybrowser.cpp b/src/tiled/propertybrowser.cpp deleted file mode 100644 index 511a33eee1..0000000000 --- a/src/tiled/propertybrowser.cpp +++ /dev/null @@ -1,2243 +0,0 @@ -/* - * propertybrowser.cpp - * Copyright 2013-2022, Thorbjørn Lindeijer - * - * This file is part of Tiled. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#include "propertybrowser.h" - -#include "changeimagelayerproperty.h" -#include "changelayer.h" -#include "changemapobject.h" -#include "changemapproperty.h" -#include "changeobjectgroupproperties.h" -#include "changeproperties.h" -#include "changetile.h" -#include "changetileimagesource.h" -#include "changewangcolordata.h" -#include "changewangsetdata.h" -#include "compression.h" -#include "documentmanager.h" -#include "flipmapobjects.h" -#include "grouplayer.h" -#include "imagelayer.h" -#include "map.h" -#include "mapdocument.h" -#include "mapobject.h" -#include "objectgroup.h" -#include "objecttemplate.h" -#include "preferences.h" -#include "properties.h" -#include "replacetileset.h" -#include "stylehelper.h" -#include "tile.h" -#include "tilelayer.h" -#include "tilesetchanges.h" -#include "tilesetdocument.h" -#include "tilesetformat.h" -#include "tilesetmanager.h" -#include "tilesetwangsetmodel.h" -#include "utils.h" -#include "varianteditorfactory.h" -#include "variantpropertymanager.h" -#include "wangcolormodel.h" -#include "wangoverlay.h" -#include "wangset.h" - -#include - -#include -#include -#include -#include -#include - -#include - -namespace Tiled { - -namespace { - -/** - * A helper class instantiated while properties are updated. - * - * Makes sure the resize mode is set to Fixed during its lifetime. Used to work - * around performance issues caused by the view continuously making sure its - * name column is adjusted to the contents. - * - * Also restores the scroll position, which gets reset when properties are - * removed and then added back. - */ -class UpdatingProperties -{ -public: - UpdatingProperties(QtTreePropertyBrowser *browser, bool &isUpdating, bool force = false) - : mBrowser(browser) - , mForced(force) - , mWasUpdating(isUpdating) - , mIsUpdating(isUpdating) - { - if (!isUpdating || force) { - isUpdating = true; - mPreviousResizeMode = browser->resizeMode(); - mPreviousScrollPosition = browser->scrollPosition(); - mBrowser->setResizeMode(QtTreePropertyBrowser::Fixed); - } - } - - ~UpdatingProperties() - { - if (!mWasUpdating || mForced) { - mBrowser->setResizeMode(mPreviousResizeMode); - mBrowser->setScrollPosition(mPreviousScrollPosition); - mIsUpdating = mWasUpdating; - } - } - -private: - QtTreePropertyBrowser * const mBrowser; - bool const mForced; - bool const mWasUpdating; - bool &mIsUpdating; - QtTreePropertyBrowser::ResizeMode mPreviousResizeMode; - int mPreviousScrollPosition; -}; - -} // anonymous namespace - -PropertyBrowser::PropertyBrowser(QWidget *parent) - : QtTreePropertyBrowser(parent) - , mVariantManager(new VariantPropertyManager(this)) - , mGroupManager(new QtGroupPropertyManager(this)) - , mCustomPropertiesGroup(nullptr) - , mCustomPropertiesHelper(this) -{ - VariantEditorFactory *variantEditorFactory = new VariantEditorFactory(this); - - setFactoryForManager(mVariantManager, variantEditorFactory); - setResizeMode(ResizeToContents); - setRootIsDecorated(false); - setPropertiesWithoutValueMarked(true); - setAllowMultiSelection(true); - - retranslateUi(); - - mWangSetIcons.insert(WangSet::Corner, wangSetIcon(WangSet::Corner)); - mWangSetIcons.insert(WangSet::Edge, wangSetIcon(WangSet::Edge)); - mWangSetIcons.insert(WangSet::Mixed, wangSetIcon(WangSet::Mixed)); - - connect(mVariantManager, &QtVariantPropertyManager::valueChanged, - this, &PropertyBrowser::valueChanged); - - connect(&mCustomPropertiesHelper, &CustomPropertiesHelper::propertyMemberValueChanged, - this, &PropertyBrowser::customPropertyValueChanged); - - connect(&mCustomPropertiesHelper, &CustomPropertiesHelper::recreateProperty, - this, &PropertyBrowser::recreateProperty); - - connect(variantEditorFactory, &VariantEditorFactory::resetProperty, - this, &PropertyBrowser::resetProperty); - - connect(Preferences::instance(), &Preferences::propertyTypesChanged, - this, &PropertyBrowser::propertyTypesChanged); - - connect(StyleHelper::instance(), &StyleHelper::styleApplied, - this, &PropertyBrowser::updateCustomPropertyColors); -} - -/** - * Sets the \a object for which to display the properties. - */ -void PropertyBrowser::setObject(Object *object) -{ - if (mObject == object) - return; - - UpdatingProperties updatingProperties(this, mUpdating); - removeProperties(); - mObject = object; - addProperties(); -} - -/** - * Sets the \a document, used for keeping track of changes and for - * undo/redo support. - */ -void PropertyBrowser::setDocument(Document *document) -{ - MapDocument *mapDocument = qobject_cast(document); - TilesetDocument *tilesetDocument = qobject_cast(document); - - if (mDocument == document) - return; - - if (mDocument) { - mDocument->disconnect(this); - if (mTilesetDocument) { - mTilesetDocument->wangSetModel()->disconnect(this); - } - } - - mDocument = document; - mMapDocument = mapDocument; - mTilesetDocument = tilesetDocument; - mCustomPropertiesHelper.setMapDocument(mapDocument); - - if (mapDocument) { - connect(mapDocument, &MapDocument::mapChanged, - this, &PropertyBrowser::mapChanged); - - connect(mapDocument, &MapDocument::selectedObjectsChanged, - this, &PropertyBrowser::selectedObjectsChanged); - connect(mapDocument, &MapDocument::selectedLayersChanged, - this, &PropertyBrowser::selectedLayersChanged); - } - - if (tilesetDocument) { - connect(tilesetDocument, &TilesetDocument::tilesetNameChanged, - this, &PropertyBrowser::tilesetChanged); - connect(tilesetDocument, &TilesetDocument::tilesetTileOffsetChanged, - this, &PropertyBrowser::tilesetChanged); - connect(tilesetDocument, &TilesetDocument::tilesetObjectAlignmentChanged, - this, &PropertyBrowser::tilesetChanged); - connect(tilesetDocument, &TilesetDocument::tilesetChanged, - this, &PropertyBrowser::tilesetChanged); - - connect(tilesetDocument, &TilesetDocument::tileProbabilityChanged, - this, &PropertyBrowser::tileChanged); - connect(tilesetDocument, &TilesetDocument::tileImageSourceChanged, - this, &PropertyBrowser::tileChanged); - - connect(tilesetDocument, &TilesetDocument::selectedTilesChanged, - this, &PropertyBrowser::selectedTilesChanged); - - TilesetWangSetModel *wangSetModel = tilesetDocument->wangSetModel(); - connect(wangSetModel, &TilesetWangSetModel::wangSetChanged, - this, &PropertyBrowser::wangSetChanged); - } - - if (document) { - connect(document, &Document::changed, - this, &PropertyBrowser::documentChanged); - - // For custom properties: - connect(document, &Document::propertyAdded, - this, &PropertyBrowser::propertyAdded); - connect(document, &Document::propertyRemoved, - this, &PropertyBrowser::propertyRemoved); - connect(document, &Document::propertyChanged, - this, &PropertyBrowser::propertyChanged); - connect(document, &Document::propertiesChanged, - this, &PropertyBrowser::propertiesChanged); - } -} - -/** - * Returns whether the given \a item displays a custom property. - */ -bool PropertyBrowser::isCustomPropertyItem(const QtBrowserItem *item) const -{ - return mCustomPropertiesHelper.hasProperty(item->property()); -} - -/** - * Returns whether the given list of \a items are all custom properties. - */ -bool PropertyBrowser::allCustomPropertyItems(const QList &items) const -{ - return std::all_of(items.begin(), items.end(), [this] (QtBrowserItem *item) { - return isCustomPropertyItem(item); - }); -} - -/** - * Selects the custom property with the given \a name, if it exists. - */ -void PropertyBrowser::selectCustomProperty(const QString &name) -{ - QtVariantProperty *property = mCustomPropertiesHelper.property(name); - if (!property) - return; - - const QList propertyItems = items(property); - if (!propertyItems.isEmpty()) - setCurrentItem(propertyItems.first()); -} - -/** - * Makes the custom property with the \a name the currently edited one, - * if it exists. - */ -void PropertyBrowser::editCustomProperty(const QString &name) -{ - QtVariantProperty *property = mCustomPropertiesHelper.property(name); - if (!property) - return; - - const QList propertyItems = items(property); - if (!propertyItems.isEmpty()) - editItem(propertyItems.first()); -} - -QSize PropertyBrowser::sizeHint() const -{ - return Utils::dpiScaled(QSize(260, 100)); -} - -bool PropertyBrowser::event(QEvent *event) -{ - if (event->type() == QEvent::LanguageChange) - retranslateUi(); - - if (event->type() == QEvent::ShortcutOverride) { - if (static_cast(event)->key() == Qt::Key_Tab) { - if (editedItem()) { - event->accept(); - return true; - } - } - } - - return QtTreePropertyBrowser::event(event); -} - -void PropertyBrowser::documentChanged(const ChangeEvent &change) -{ - if (!mObject) - return; - - switch (change.type) { - case ChangeEvent::ObjectsChanged: { - auto &objectsChange = static_cast(change); - - if (objectsChange.properties & ObjectsChangeEvent::ClassProperty) { - if (objectsChange.objects.contains(mObject)) { - updateProperties(); - updateCustomProperties(); - } else if (mObject->typeId() == Object::MapObjectType) { - auto mapObject = static_cast(mObject); - if (auto tile = mapObject->cell().tile()) { - if (mapObject->className().isEmpty() && objectsChange.objects.contains(tile)) { - updateProperties(); - updateCustomProperties(); - } - } - } - } - - break; - } - case ChangeEvent::LayerChanged: - case ChangeEvent::TileLayerChanged: - case ChangeEvent::ImageLayerChanged: - if (mObject == static_cast(change).layer) - updateProperties(); - break; - case ChangeEvent::MapObjectsChanged: - mapObjectsChanged(static_cast(change)); - break; - case ChangeEvent::ObjectGroupChanged: - if (mObject == static_cast(change).objectGroup) - updateProperties(); - break; - case ChangeEvent::TilesetChanged: - if (mObject == static_cast(change).tileset) - updateProperties(); - break; - case ChangeEvent::WangSetChanged: - if (mObject == static_cast(change).wangSet) - updateProperties(); - break; - default: - break; - } -} - -void PropertyBrowser::mapChanged() -{ - if (mObject == mMapDocument->map()) - updateProperties(); -} - -void PropertyBrowser::mapObjectsChanged(const MapObjectsChangeEvent &mapObjectsChange) -{ - if (!mObject || mObject->typeId() != Object::MapObjectType) - return; - if (!mapObjectsChange.mapObjects.contains(static_cast(mObject))) - return; - - updateProperties(); - - if (mapObjectsChange.properties & MapObject::CustomProperties) - updateCustomProperties(); -} - -void PropertyBrowser::tilesetChanged(Tileset *tileset) -{ - if (mObject == tileset) { - updateProperties(); - updateCustomProperties(); // Tileset may have been swapped - } -} - -void PropertyBrowser::tileChanged(Tile *tile) -{ - if (mObject == tile) - updateProperties(); -} - -void PropertyBrowser::tileTypeChanged(Tile *tile) -{ - if (mObject == tile) { - updateProperties(); - updateCustomProperties(); - } else if (mObject && mObject->typeId() == Object::MapObjectType) { - auto mapObject = static_cast(mObject); - if (mapObject->cell().tile() == tile && mapObject->className().isEmpty()) - updateProperties(); - } -} - -void PropertyBrowser::wangSetChanged(WangSet *wangSet) -{ - if (mObject == wangSet) - updateProperties(); -} - -static bool isAutomappingRulesMap(const MapDocument *mapDocument) -{ - if (!mapDocument) - return false; - - bool hasInputLayer = false; - bool hasOutputLayer = false; - - for (const Layer *layer : mapDocument->map()->allLayers()) { - if (layer->name().startsWith(QLatin1String("input"), Qt::CaseInsensitive)) - hasInputLayer |= layer->isTileLayer(); - else if (layer->name().startsWith(QLatin1String("output"), Qt::CaseInsensitive)) - hasOutputLayer = true; - } - - return hasInputLayer && hasOutputLayer; -} - -static void addAutomappingProperties(Properties &properties, const Object *object) -{ - auto addRuleOptions = [&] { - mergeProperties(properties, QVariantMap { - { QStringLiteral("Probability"), 1.0 }, - { QStringLiteral("ModX"), 1 }, - { QStringLiteral("ModY"), 1 }, - { QStringLiteral("OffsetX"), 0 }, - { QStringLiteral("OffsetY"), 0 }, - { QStringLiteral("NoOverlappingOutput"), false }, - { QStringLiteral("Disabled"), false }, - { QStringLiteral("IgnoreLock"), false }, - }); - }; - - switch (object->typeId()) { - case Object::LayerType: { - auto layer = static_cast(object); - - if (layer->name().startsWith(QLatin1String("input"), Qt::CaseInsensitive)) { - mergeProperties(properties, QVariantMap { - { QStringLiteral("AutoEmpty"), false }, - { QStringLiteral("IgnoreHorizontalFlip"), false }, - { QStringLiteral("IgnoreVerticalFlip"), false }, - { QStringLiteral("IgnoreDiagonalFlip"), false }, - // { QStringLiteral("IgnoreHexRotate120"), false }, - }); - } else if (layer->name().startsWith(QLatin1String("output"), Qt::CaseInsensitive)) { - mergeProperties(properties, QVariantMap { - { QStringLiteral("Probability"), 1.0 }, - }); - } - break; - } - case Object::MapType: - mergeProperties(properties, QVariantMap { - { QStringLiteral("DeleteTiles"), false }, - { QStringLiteral("MatchOutsideMap"), false }, - { QStringLiteral("OverflowBorder"), false }, - { QStringLiteral("WrapBorder"), false }, - { QStringLiteral("AutomappingRadius"), 0 }, - { QStringLiteral("NoOverlappingOutput"), false }, - { QStringLiteral("MatchInOrder"), false }, - }); - addRuleOptions(); - break; - case Object::MapObjectType: { - if (auto objectGroup = static_cast(object)->objectGroup()) - if (objectGroup->name().compare(QLatin1String("rule_options"), Qt::CaseInsensitive) == 0) - addRuleOptions(); - break; - } - default: - break; - } -} - -static bool checkAutomappingProperty(const Object *object, - const QString &name, - QVariant &value) -{ - Properties properties; - addAutomappingProperties(properties, object); - value = properties.value(name); - return value.isValid(); -} - -static bool anyObjectHasProperty(const QList &objects, const QString &name) -{ - for (Object *obj : objects) { - if (obj->hasProperty(name)) - return true; - } - return false; -} - -static bool propertyValueAffected(Object *currentObject, - Object *changedObject, - const QString &propertyName) -{ - if (currentObject == changedObject) - return true; - - // Changed property may be inherited - if (currentObject && currentObject->typeId() == Object::MapObjectType && changedObject->typeId() == Object::TileType) { - auto tile = static_cast(currentObject)->cell().tile(); - if (tile == changedObject && !currentObject->hasProperty(propertyName)) - return true; - } - - return false; -} - -static bool objectPropertiesRelevant(Document *document, Object *object) -{ - auto currentObject = document->currentObject(); - if (!currentObject) - return false; - - if (currentObject == object) - return true; - - if (currentObject->typeId() == Object::MapObjectType) - if (static_cast(currentObject)->cell().tile() == object) - return true; - - if (document->currentObjects().contains(object)) - return true; - - return false; -} - -static QStringList classNamesFor(const Object &object) -{ - QStringList names; - for (const auto type : Object::propertyTypes()) - if (type->isClass()) - if (static_cast(type)->isClassFor(object)) - names.append(type->name); - return names; -} - -void PropertyBrowser::propertyAdded(Object *object, const QString &name) -{ - if (!objectPropertiesRelevant(mDocument, object)) - return; - if (QtVariantProperty *property = mCustomPropertiesHelper.property(name)) { - if (propertyValueAffected(mObject, object, name)) - setCustomPropertyValue(property, object->property(name)); - } else { - const QVariant value = mObject->resolvedProperty(name); - addCustomProperty(name, value); - } - updateCustomPropertyColor(name); -} - -void PropertyBrowser::propertyRemoved(Object *object, const QString &name) -{ - auto property = mCustomPropertiesHelper.property(name); - if (!property) - return; - if (!objectPropertiesRelevant(mDocument, object)) - return; - - QVariant resolvedValue = mObject->resolvedProperty(name); - - if (!resolvedValue.isValid() && - !(isAutomappingRulesMap(mMapDocument) && checkAutomappingProperty(object, name, resolvedValue)) && - !anyObjectHasProperty(mDocument->currentObjects(), name)) { - // It's not a predefined property and no selected object has this - // property, so delete it. - - // First move up or down the currently selected item - QtBrowserItem *item = currentItem(); - if (item && item->property() == property) { - const QList siblings = item->parent()->children(); - if (siblings.count() > 1) { - int currentItemIndex = siblings.indexOf(item); - if (item == siblings.last()) { - setCurrentItem(siblings.at(currentItemIndex - 1)); - } else { - setCurrentItem(siblings.at(currentItemIndex + 1)); - } - } - } - - mCustomPropertiesHelper.deleteProperty(property); - return; - } - - if (propertyValueAffected(mObject, object, name)) { - // Property deleted from the current object, so reset the value. - setCustomPropertyValue(property, resolvedValue); - } - - updateCustomPropertyColor(name); -} - -void PropertyBrowser::propertyChanged(Object *object, const QString &name) -{ - auto property = mCustomPropertiesHelper.property(name); - if (!property) - return; - - if (propertyValueAffected(mObject, object, name)) - setCustomPropertyValue(property, object->property(name)); - - if (mDocument->currentObjects().contains(object)) - updateCustomPropertyColor(name); -} - -void PropertyBrowser::propertiesChanged(Object *object) -{ - if (objectPropertiesRelevant(mDocument, object)) - updateCustomProperties(); -} - -void PropertyBrowser::selectedObjectsChanged() -{ - updateCustomProperties(); -} - -void PropertyBrowser::selectedLayersChanged() -{ - updateCustomProperties(); -} - -void PropertyBrowser::selectedTilesChanged() -{ - updateCustomProperties(); -} - -void PropertyBrowser::propertyTypesChanged() -{ - if (!mObject) - return; - - if (auto classProperty = mIdToProperty.value(ClassProperty)) { - classProperty->setAttribute(QStringLiteral("suggestions"), - classNamesFor(*mObject)); - } - - // Don't do anything if there can't be any properties based on the class - if (mObject->typeId() == Object::MapObjectType) { - if (static_cast(mObject)->effectiveClassName().isEmpty()) - return; - } else if (mObject->className().isEmpty()) { - return; - } - - updateCustomProperties(); -} - -void PropertyBrowser::valueChanged(QtProperty *property, const QVariant &val) -{ - if (mUpdating) - return; - if (!mObject || !mDocument) - return; - if (!mPropertyToId.contains(property)) - return; - - const PropertyId id = mPropertyToId.value(property); - - if (id == ClassProperty) { - QUndoStack *undoStack = mDocument->undoStack(); - undoStack->push(new ChangeClassName(mDocument, - mDocument->currentObjects(), - val.toString())); - return; - } - - switch (mObject->typeId()) { - case Object::MapType: applyMapValue(id, val); break; - case Object::MapObjectType: applyMapObjectValue(id, val); break; - case Object::LayerType: applyLayerValue(id, val); break; - case Object::TilesetType: applyTilesetValue(id, val); break; - case Object::TileType: applyTileValue(id, val); break; - case Object::WangSetType: applyWangSetValue(id, val); break; - case Object::WangColorType: applyWangColorValue(id, val); break; - case Object::ProjectType: break; - case Object::WorldType: break; - } -} - -void PropertyBrowser::customPropertyValueChanged(const QStringList &path, const QVariant &value) -{ - if (mUpdating) - return; - if (!mObject || !mDocument) - return; - - QUndoStack *undoStack = mDocument->undoStack(); - undoStack->push(new SetProperty(mDocument, - mDocument->currentObjects(), - path, value)); -} - -void PropertyBrowser::resetProperty(QtProperty *property) -{ - auto typeId = mVariantManager->propertyType(property); - if (typeId == QMetaType::QColor) - mVariantManager->setValue(property, QColor()); - else - qWarning() << "Resetting of property type not supported right now"; -} - -void PropertyBrowser::addMapProperties() -{ - QtProperty *groupProperty = mGroupManager->addProperty(tr("Map")); - - addClassProperty(groupProperty); - - QtVariantProperty *orientationProperty = - addProperty(OrientationProperty, - QtVariantPropertyManager::enumTypeId(), - tr("Orientation"), - groupProperty); - - orientationProperty->setAttribute(QLatin1String("enumNames"), mOrientationNames); - - addProperty(WidthProperty, QMetaType::Int, tr("Width"), groupProperty)->setEnabled(false); - addProperty(HeightProperty, QMetaType::Int, tr("Height"), groupProperty)->setEnabled(false); - auto tileWidthProperty = addProperty(TileWidthProperty, QMetaType::Int, tr("Tile Width"), groupProperty); - auto tileHeightProperty = addProperty(TileHeightProperty, QMetaType::Int, tr("Tile Height"), groupProperty); - addProperty(InfiniteProperty, QMetaType::Bool, tr("Infinite"), groupProperty); - - tileWidthProperty->setAttribute(QStringLiteral("minimum"), 1); - tileHeightProperty->setAttribute(QStringLiteral("minimum"), 1); - - addProperty(HexSideLengthProperty, QMetaType::Int, tr("Tile Side Length (Hex)"), groupProperty); - - QtVariantProperty *staggerAxisProperty = - addProperty(StaggerAxisProperty, - QtVariantPropertyManager::enumTypeId(), - tr("Stagger Axis"), - groupProperty); - - staggerAxisProperty->setAttribute(QLatin1String("enumNames"), mStaggerAxisNames); - - QtVariantProperty *staggerIndexProperty = - addProperty(StaggerIndexProperty, - QtVariantPropertyManager::enumTypeId(), - tr("Stagger Index"), - groupProperty); - - staggerIndexProperty->setAttribute(QLatin1String("enumNames"), mStaggerIndexNames); - - addProperty(ParallaxOriginProperty, QMetaType::QPointF, tr("Parallax Origin"), groupProperty); - - QtVariantProperty *layerFormatProperty = - addProperty(LayerFormatProperty, - QtVariantPropertyManager::enumTypeId(), - tr("Tile Layer Format"), - groupProperty); - - layerFormatProperty->setAttribute(QLatin1String("enumNames"), mLayerFormatNames); - - QtVariantProperty *chunkWidthProperty = addProperty(ChunkWidthProperty, QMetaType::Int, tr("Output Chunk Width"), groupProperty); - QtVariantProperty *chunkHeightProperty = addProperty(ChunkHeightProperty, QMetaType::Int, tr("Output Chunk Height"), groupProperty); - - chunkWidthProperty->setAttribute(QLatin1String("minimum"), CHUNK_SIZE_MIN); - chunkHeightProperty->setAttribute(QLatin1String("minimum"), CHUNK_SIZE_MIN); - - QtVariantProperty *renderOrderProperty = - addProperty(RenderOrderProperty, - QtVariantPropertyManager::enumTypeId(), - tr("Tile Render Order"), - groupProperty); - - addProperty(CompressionLevelProperty, QMetaType::Int, tr("Compression Level"), groupProperty); - - renderOrderProperty->setAttribute(QLatin1String("enumNames"), mRenderOrderNames); - - addProperty(BackgroundColorProperty, QMetaType::QColor, tr("Background Color"), groupProperty); - addProperty(groupProperty); -} - -enum MapObjectFlags { - ObjectHasDimensions = 0x1, - ObjectHasTile = 0x2, - ObjectIsText = 0x4 -}; - -static int mapObjectFlags(const MapObject *mapObject) -{ - int flags = 0; - if (mapObject->hasDimensions()) - flags |= ObjectHasDimensions; - if (!mapObject->cell().isEmpty()) - flags |= ObjectHasTile; - if (mapObject->shape() == MapObject::Text) - flags |= ObjectIsText; - return flags; -} - -void PropertyBrowser::addMapObjectProperties() -{ - QtProperty *groupProperty = mGroupManager->addProperty(tr("Object")); - - addProperty(IdProperty, QMetaType::Int, tr("ID"), groupProperty)->setEnabled(false); - addProperty(TemplateProperty, filePathTypeId(), tr("Template"), groupProperty)->setEnabled(false); - addProperty(NameProperty, QMetaType::QString, tr("Name"), groupProperty); - - addClassProperty(groupProperty); - - if (mMapDocument->allowHidingObjects()) - addProperty(VisibleProperty, QMetaType::Bool, tr("Visible"), groupProperty); - - addProperty(XProperty, QMetaType::Double, tr("X"), groupProperty); - addProperty(YProperty, QMetaType::Double, tr("Y"), groupProperty); - - auto mapObject = static_cast(mObject); - mMapObjectFlags = mapObjectFlags(mapObject); - - if (mMapObjectFlags & ObjectHasDimensions) { - addProperty(WidthProperty, QMetaType::Double, tr("Width"), groupProperty); - addProperty(HeightProperty, QMetaType::Double, tr("Height"), groupProperty); - } - - bool isPoint = mapObject->shape() == MapObject::Point; - addProperty(RotationProperty, QMetaType::Double, tr("Rotation"), groupProperty)->setEnabled(!isPoint); - - if (mMapObjectFlags & ObjectHasTile) { - QtVariantProperty *flippingProperty = - addProperty(FlippingProperty, VariantPropertyManager::flagTypeId(), - tr("Flipping"), groupProperty); - - flippingProperty->setAttribute(QLatin1String("flagNames"), mFlippingFlagNames); - } - - if (mMapObjectFlags & ObjectIsText) { - addProperty(TextProperty, QMetaType::QString, tr("Text"), groupProperty)->setAttribute(QLatin1String("multiline"), true); - addProperty(TextAlignmentProperty, VariantPropertyManager::alignmentTypeId(), tr("Alignment"), groupProperty); - addProperty(FontProperty, QMetaType::QFont, tr("Font"), groupProperty); - addProperty(WordWrapProperty, QMetaType::Bool, tr("Word Wrap"), groupProperty); - addProperty(ColorProperty, QMetaType::QColor, tr("Color"), groupProperty); - } - - addProperty(groupProperty); -} - -void PropertyBrowser::addLayerProperties(QtProperty *parent) -{ - addProperty(IdProperty, QMetaType::Int, tr("ID"), parent)->setEnabled(false); - addProperty(NameProperty, QMetaType::QString, tr("Name"), parent); - addClassProperty(parent); - addProperty(VisibleProperty, QMetaType::Bool, tr("Visible"), parent); - addProperty(LockedProperty, QMetaType::Bool, tr("Locked"), parent); - - QtVariantProperty *opacityProperty = - addProperty(OpacityProperty, QMetaType::Double, tr("Opacity"), parent); - opacityProperty->setAttribute(QLatin1String("minimum"), 0.0); - opacityProperty->setAttribute(QLatin1String("maximum"), 1.0); - opacityProperty->setAttribute(QLatin1String("singleStep"), 0.1); - addProperty(TintColorProperty, QMetaType::QColor, tr("Tint Color"), parent); - - addProperty(OffsetXProperty, QMetaType::Double, tr("Horizontal Offset"), parent); - addProperty(OffsetYProperty, QMetaType::Double, tr("Vertical Offset"), parent); - - QtVariantProperty *parallaxProperty = - addProperty(ParallaxFactorProperty, QMetaType::QPointF, tr("Parallax Factor"), parent); - parallaxProperty->setAttribute(QLatin1String("singleStep"), 0.1); -} - -void PropertyBrowser::addTileLayerProperties() -{ - QtProperty *groupProperty = mGroupManager->addProperty(tr("Tile Layer")); - addLayerProperties(groupProperty); - addProperty(groupProperty); -} - -void PropertyBrowser::addObjectGroupProperties() -{ - QtProperty *groupProperty = mGroupManager->addProperty(tr("Object Layer")); - addLayerProperties(groupProperty); - - addProperty(ColorProperty, QMetaType::QColor, tr("Color"), groupProperty); - - QtVariantProperty *drawOrderProperty = - addProperty(DrawOrderProperty, - QtVariantPropertyManager::enumTypeId(), - tr("Drawing Order"), - groupProperty); - - drawOrderProperty->setAttribute(QLatin1String("enumNames"), mDrawOrderNames); - - addProperty(groupProperty); -} - -void PropertyBrowser::addImageLayerProperties() -{ - QtProperty *groupProperty = mGroupManager->addProperty(tr("Image Layer")); - addLayerProperties(groupProperty); - - QtVariantProperty *imageSourceProperty = addProperty(ImageSourceProperty, - filePathTypeId(), - tr("Image"), groupProperty); - - imageSourceProperty->setAttribute(QLatin1String("filter"), - Utils::readableImageFormatsFilter()); - - addProperty(ColorProperty, QMetaType::QColor, tr("Transparent Color"), groupProperty); - - addProperty(RepeatXProperty, QMetaType::Bool, tr("Repeat X"), groupProperty); - addProperty(RepeatYProperty, QMetaType::Bool, tr("Repeat Y"), groupProperty); - - addProperty(groupProperty); -} - -void PropertyBrowser::addGroupLayerProperties() -{ - QtProperty *groupProperty = mGroupManager->addProperty(tr("Group Layer")); - addLayerProperties(groupProperty); - addProperty(groupProperty); -} - -void PropertyBrowser::addTilesetProperties() -{ - const Tileset *tileset = static_cast(mObject); - - QtProperty *groupProperty = mGroupManager->addProperty(tr("Tileset")); - - if (mMapDocument) { - auto property = addProperty(FileNameProperty, filePathTypeId(), tr("Filename"), groupProperty); - - QString filter = QCoreApplication::translate("MainWindow", "All Files (*)"); - FormatHelper helper(FileFormat::Read, filter); - - property->setAttribute(QStringLiteral("filter"), helper.filter()); - } - - QtVariantProperty *nameProperty = addProperty(NameProperty, QMetaType::QString, tr("Name"), groupProperty); - nameProperty->setEnabled(mTilesetDocument); - - addClassProperty(groupProperty); - - QtVariantProperty *alignmentProperty = - addProperty(ObjectAlignmentProperty, - QtVariantPropertyManager::enumTypeId(), - tr("Object Alignment"), - groupProperty); - alignmentProperty->setAttribute(QLatin1String("enumNames"), mAlignmentNames); - alignmentProperty->setEnabled(mTilesetDocument); - - QtVariantProperty *tileOffsetProperty = addProperty(TileOffsetProperty, QMetaType::QPoint, tr("Drawing Offset"), groupProperty); - tileOffsetProperty->setEnabled(mTilesetDocument); - - QtVariantProperty *tileRenderSizeProperty = - addProperty(TileRenderSizeProperty, - QtVariantPropertyManager::enumTypeId(), - tr("Tile Render Size"), - groupProperty); - tileRenderSizeProperty->setAttribute(QLatin1String("enumNames"), mTileRenderSizeNames); - tileRenderSizeProperty->setEnabled(mTilesetDocument); - - QtVariantProperty *fillModeProperty = - addProperty(FillModeProperty, - QtVariantPropertyManager::enumTypeId(), - tr("Fill Mode"), - groupProperty); - fillModeProperty->setAttribute(QLatin1String("enumNames"), mFillModeNames); - fillModeProperty->setEnabled(mTilesetDocument); - - QtVariantProperty *backgroundProperty = addProperty(BackgroundColorProperty, QMetaType::QColor, tr("Background Color"), groupProperty); - backgroundProperty->setEnabled(mTilesetDocument); - - QtVariantProperty *orientationProperty = - addProperty(OrientationProperty, - QtVariantPropertyManager::enumTypeId(), - tr("Orientation"), - groupProperty); - orientationProperty->setAttribute(QLatin1String("enumNames"), mTilesetOrientationNames); - - QtVariantProperty *gridWidthProperty = addProperty(GridWidthProperty, QMetaType::Int, tr("Grid Width"), groupProperty); - gridWidthProperty->setEnabled(mTilesetDocument); - gridWidthProperty->setAttribute(QLatin1String("minimum"), 1); - QtVariantProperty *gridHeightProperty = addProperty(GridHeightProperty, QMetaType::Int, tr("Grid Height"), groupProperty); - gridHeightProperty->setEnabled(mTilesetDocument); - gridHeightProperty->setAttribute(QLatin1String("minimum"), 1); - - QtVariantProperty *columnsProperty = addProperty(ColumnCountProperty, QMetaType::Int, tr("Columns"), groupProperty); - columnsProperty->setAttribute(QLatin1String("minimum"), 1); - - QtVariantProperty *transformationsGroupProperty = mVariantManager->addProperty(VariantPropertyManager::unstyledGroupTypeId(), tr("Allowed Transformations")); - - QtVariantProperty *flipHorizontallyProperty = addProperty(AllowFlipHorizontallyProperty, QMetaType::Bool, tr("Flip Horizontally"), transformationsGroupProperty); - QtVariantProperty *flipVerticallyProperty = addProperty(AllowFlipVerticallyProperty, QMetaType::Bool, tr("Flip Vertically"), transformationsGroupProperty); - QtVariantProperty *rotateProperty = addProperty(AllowRotateProperty, QMetaType::Bool, tr("Rotate"), transformationsGroupProperty); - QtVariantProperty *randomProperty = addProperty(PreferUntransformedProperty, QMetaType::Bool, tr("Prefer Untransformed Tiles"), transformationsGroupProperty); - flipHorizontallyProperty->setEnabled(mTilesetDocument); - flipVerticallyProperty->setEnabled(mTilesetDocument); - rotateProperty->setEnabled(mTilesetDocument); - randomProperty->setEnabled(mTilesetDocument); - - groupProperty->addSubProperty(transformationsGroupProperty); - - // Next properties we should add only for non 'Collection of Images' tilesets - if (!tileset->isCollection()) { - QtVariantProperty *parametersProperty = - addProperty(TilesetImageParametersProperty, VariantPropertyManager::tilesetParametersTypeId(), tr("Image"), groupProperty); - - parametersProperty->setEnabled(mTilesetDocument); - - QtVariantProperty *imageSourceProperty = addProperty(ImageSourceProperty, QMetaType::QString, tr("Source"), parametersProperty); - QtVariantProperty *tileWidthProperty = addProperty(TileWidthProperty, QMetaType::Int, tr("Tile Width"), parametersProperty); - QtVariantProperty *tileHeightProperty = addProperty(TileHeightProperty, QMetaType::Int, tr("Tile Height"), parametersProperty); - QtVariantProperty *marginProperty = addProperty(MarginProperty, QMetaType::Int, tr("Margin"), parametersProperty); - QtVariantProperty *spacingProperty = addProperty(SpacingProperty, QMetaType::Int, tr("Spacing"), parametersProperty); - QtVariantProperty *colorProperty = addProperty(ColorProperty, QMetaType::QColor, tr("Transparent Color"), parametersProperty); - - // These properties can't be directly edited. To change the parameters, - // the TilesetParametersEdit is used. - imageSourceProperty->setEnabled(false); - tileWidthProperty->setEnabled(false); - tileHeightProperty->setEnabled(false); - marginProperty->setEnabled(false); - spacingProperty->setEnabled(false); - colorProperty->setEnabled(false); - } - addProperty(groupProperty); -} - -void PropertyBrowser::addTileProperties() -{ - QtProperty *groupProperty = mGroupManager->addProperty(tr("Tile")); - addProperty(IdProperty, QMetaType::Int, tr("ID"), groupProperty)->setEnabled(false); - - addClassProperty(groupProperty)->setEnabled(mTilesetDocument); - - addProperty(WidthProperty, QMetaType::Int, tr("Width"), groupProperty)->setEnabled(false); - addProperty(HeightProperty, QMetaType::Int, tr("Height"), groupProperty)->setEnabled(false); - - QtVariantProperty *probabilityProperty = addProperty(TileProbabilityProperty, - QMetaType::Double, - tr("Probability"), - groupProperty); - probabilityProperty->setAttribute(QLatin1String("decimals"), 3); - probabilityProperty->setToolTip(tr("Relative chance this tile will be picked")); - probabilityProperty->setEnabled(mTilesetDocument); - - const Tile *tile = static_cast(mObject); - if (!tile->imageSource().isEmpty()) { - QtVariantProperty *imageSourceProperty = addProperty(ImageSourceProperty, - filePathTypeId(), - tr("Image"), groupProperty); - imageSourceProperty->setAttribute(QLatin1String("filter"), - Utils::readableImageFormatsFilter()); - imageSourceProperty->setEnabled(mTilesetDocument); - } - - QtVariantProperty *imageRectProperty = addProperty(ImageRectProperty, - QMetaType::QRect, - tr("Image Rect"), groupProperty); - imageRectProperty->setEnabled(mTilesetDocument && tile->tileset()->isCollection()); - imageRectProperty->setAttribute(QLatin1String("constraint"), tile->image().rect()); - - addProperty(groupProperty); -} - -void PropertyBrowser::addWangSetProperties() -{ - QtProperty *groupProperty = mGroupManager->addProperty(tr("Terrain Set")); - QtVariantProperty *nameProperty = addProperty(NameProperty, QMetaType::QString, tr("Name"), groupProperty); - QtVariantProperty *classProperty = addClassProperty(groupProperty); - QtVariantProperty *typeProperty = addProperty(WangSetTypeProperty, - QtVariantPropertyManager::enumTypeId(), - tr("Type"), - groupProperty); - QtVariantProperty *colorCountProperty = addProperty(ColorCountProperty, QMetaType::Int, tr("Terrain Count"), groupProperty); - - typeProperty->setAttribute(QLatin1String("enumNames"), mWangSetTypeNames); - typeProperty->setAttribute(QLatin1String("enumIcons"), QVariant::fromValue(mWangSetIcons)); - - colorCountProperty->setAttribute(QLatin1String("minimum"), 0); - colorCountProperty->setAttribute(QLatin1String("maximum"), WangId::MAX_COLOR_COUNT); - - nameProperty->setEnabled(mTilesetDocument); - classProperty->setEnabled(mTilesetDocument); - typeProperty->setEnabled(mTilesetDocument); - colorCountProperty->setEnabled(mTilesetDocument); - - addProperty(groupProperty); -} - -void PropertyBrowser::addWangColorProperties() -{ - QtProperty *groupProperty = mGroupManager->addProperty(tr("Terrain")); - QtVariantProperty *nameProperty = addProperty(NameProperty, - QMetaType::QString, - tr("Name"), - groupProperty); - QtVariantProperty *classProperty = addClassProperty(groupProperty); - QtVariantProperty *colorProperty = addProperty(ColorProperty, - QMetaType::QColor, - tr("Color"), - groupProperty); - QtVariantProperty *probabilityProperty = addProperty(WangColorProbabilityProperty, - QMetaType::Double, - tr("Probability"), - groupProperty); - - probabilityProperty->setAttribute(QLatin1String("minimum"), 0.01); - - nameProperty->setEnabled(mTilesetDocument); - classProperty->setEnabled(mTilesetDocument); - colorProperty->setEnabled(mTilesetDocument); - probabilityProperty->setEnabled(mTilesetDocument); - - addProperty(groupProperty); -} - -QtVariantProperty *PropertyBrowser::addClassProperty(QtProperty *parent) -{ - QtVariantProperty *classProperty = addProperty(ClassProperty, - QMetaType::QString, - tr("Class"), - parent); - - classProperty->setAttribute(QLatin1String("suggestions"), - classNamesFor(*mObject)); - - return classProperty; -} - -void PropertyBrowser::applyMapValue(PropertyId id, const QVariant &val) -{ - QUndoCommand *command = nullptr; - - switch (id) { - case TileWidthProperty: - command = new ChangeMapProperty(mMapDocument, Map::TileWidthProperty, - val.toInt()); - break; - case TileHeightProperty: - command = new ChangeMapProperty(mMapDocument, Map::TileHeightProperty, - val.toInt()); - break; - case InfiniteProperty: { - bool infinite = val.toInt(); - - auto changePropertyCommand = new ChangeMapProperty(mMapDocument, Map::InfiniteProperty, - val.toInt()); - - QUndoStack *undoStack = mDocument->undoStack(); - undoStack->beginMacro(changePropertyCommand->text()); - - if (!infinite) { - QRect mapBounds(QPoint(0, 0), mMapDocument->map()->size()); - - LayerIterator iterator(mMapDocument->map()); - while (Layer *layer = iterator.next()) { - if (TileLayer *tileLayer = dynamic_cast(layer)) - mapBounds = mapBounds.united(tileLayer->region().boundingRect()); - } - - if (mapBounds.size() == QSize(0, 0)) - mapBounds.setSize(QSize(1, 1)); - - mMapDocument->resizeMap(mapBounds.size(), -mapBounds.topLeft(), false); - } - - undoStack->push(changePropertyCommand); - undoStack->endMacro(); - break; - } - case OrientationProperty: { - Map::Orientation orientation = static_cast(val.toInt() + 1); - command = new ChangeMapProperty(mMapDocument, orientation); - break; - } - case HexSideLengthProperty: { - command = new ChangeMapProperty(mMapDocument, Map::HexSideLengthProperty, - val.toInt()); - break; - } - case StaggerAxisProperty: { - Map::StaggerAxis staggerAxis = static_cast(val.toInt()); - command = new ChangeMapProperty(mMapDocument, staggerAxis); - break; - } - case StaggerIndexProperty: { - Map::StaggerIndex staggerIndex = static_cast(val.toInt()); - command = new ChangeMapProperty(mMapDocument, staggerIndex); - break; - } - case ParallaxOriginProperty: { - command = new ChangeMapProperty(mMapDocument, val.value()); - break; - } - case LayerFormatProperty: { - Map::LayerDataFormat format = mLayerFormatValues.at(val.toInt()); - command = new ChangeMapProperty(mMapDocument, format); - break; - } - case RenderOrderProperty: { - Map::RenderOrder renderOrder = static_cast(val.toInt()); - command = new ChangeMapProperty(mMapDocument, renderOrder); - break; - } - case BackgroundColorProperty: - command = new ChangeMapProperty(mMapDocument, val.value()); - break; - case CompressionLevelProperty: - command = new ChangeMapProperty(mMapDocument, Map::CompressionLevelProperty, val.toInt()); - break; - case ChunkWidthProperty: { - QSize chunkSize = mMapDocument->map()->chunkSize(); - chunkSize.setWidth(val.toInt()); - command = new ChangeMapProperty(mMapDocument, chunkSize); - break; - } - case ChunkHeightProperty: { - QSize chunkSize = mMapDocument->map()->chunkSize(); - chunkSize.setHeight(val.toInt()); - command = new ChangeMapProperty(mMapDocument, chunkSize); - break; - } - default: - break; - } - - if (command) - mDocument->undoStack()->push(command); -} - -QUndoCommand *PropertyBrowser::applyMapObjectValueTo(PropertyId id, const QVariant &val, MapObject *mapObject) -{ - QUndoCommand *command = nullptr; - - switch (id) { - default: { - MapObject::Property property; - - switch (id) { - case NameProperty: property = MapObject::NameProperty; break; - case VisibleProperty: property = MapObject::VisibleProperty; break; - case TextProperty: property = MapObject::TextProperty; break; - case FontProperty: property = MapObject::TextFontProperty; break; - case TextAlignmentProperty: property = MapObject::TextAlignmentProperty; break; - case WordWrapProperty: property = MapObject::TextWordWrapProperty; break; - case ColorProperty: property = MapObject::TextColorProperty; break; - default: - return nullptr; // unrecognized property - } - - command = new ChangeMapObject(mDocument, mapObject, property, val); - break; - } - case XProperty: { - command = new ChangeMapObject(mDocument, mapObject, - MapObject::PositionProperty, - QPointF(val.toReal(), mapObject->y())); - break; - } - case YProperty: { - command = new ChangeMapObject(mDocument, mapObject, - MapObject::PositionProperty, - QPointF(mapObject->x(), val.toReal())); - break; - } - case WidthProperty: { - command = new ChangeMapObject(mDocument, mapObject, - MapObject::SizeProperty, - QSizeF(val.toReal(), mapObject->height())); - break; - } - case HeightProperty: { - command = new ChangeMapObject(mDocument, mapObject, - MapObject::SizeProperty, - QSizeF(mapObject->width(), val.toReal())); - break; - } - case RotationProperty: - if (mapObject->canRotate()) { - command = new ChangeMapObject(mDocument, mapObject, - MapObject::RotationProperty, - val.toDouble()); - } - break; - case FlippingProperty: { - const int flippingFlags = val.toInt(); - - MapObjectCell mapObjectCell; - mapObjectCell.object = mapObject; - mapObjectCell.cell = mapObject->cell(); - mapObjectCell.cell.setFlippedHorizontally(flippingFlags & 1); - mapObjectCell.cell.setFlippedVertically(flippingFlags & 2); - - command = new ChangeMapObjectCells(mDocument, { mapObjectCell }); - - command->setText(QCoreApplication::translate("Undo Commands", - "Flip %n Object(s)", - nullptr, - mMapDocument->selectedObjects().size())); - break; - } - } - - return command; -} - -void PropertyBrowser::applyMapObjectValue(PropertyId id, const QVariant &val) -{ - MapObject *mapObject = static_cast(mObject); - - QUndoCommand *command = applyMapObjectValueTo(id, val, mapObject); - if (!command) - return; - - if (mMapDocument->selectedObjects().size() == 1) { - mDocument->undoStack()->push(command); - return; - } - - mDocument->undoStack()->beginMacro(command->text()); - mDocument->undoStack()->push(command); - - for (MapObject *obj : mMapDocument->selectedObjects()) { - if (obj != mapObject) { - if (QUndoCommand *cmd = applyMapObjectValueTo(id, val, obj)) - mDocument->undoStack()->push(cmd); - } - } - - mDocument->undoStack()->endMacro(); -} - -template -QList layersOfType(const QList &layers, Layer::TypeFlag typeFlag) -{ - QList result; - for (Layer *layer : layers) - if (layer->layerType() == typeFlag) - result.append(static_cast(layer)); - return result; -} - -void PropertyBrowser::applyLayerValue(PropertyId id, const QVariant &val) -{ - const auto &layers = mMapDocument->selectedLayers(); - if (layers.isEmpty()) - return; - - QUndoCommand *command = nullptr; - - switch (id) { - case NameProperty: - command = new SetLayerName(mMapDocument, layers, val.toString()); - break; - case VisibleProperty: - command = new SetLayerVisible(mMapDocument, layers, val.toBool()); - break; - case LockedProperty: - command = new SetLayerLocked(mMapDocument, layers, val.toBool()); - break; - case OpacityProperty: - command = new SetLayerOpacity(mMapDocument, layers, val.toDouble()); - break; - case TintColorProperty: - command = new SetLayerTintColor(mMapDocument, layers, val.value()); - break; - case OffsetXProperty: - case OffsetYProperty: { - QVector offsets; - for (const Layer *layer : layers) - offsets.append(layer->offset()); - - if (id == OffsetXProperty) { - for (QPointF &offset : offsets) - offset.setX(val.toDouble()); - } else { - for (QPointF &offset : offsets) - offset.setY(val.toDouble()); - } - - command = new SetLayerOffset(mMapDocument, layers, offsets); - break; - } - case ParallaxFactorProperty: - command = new SetLayerParallaxFactor(mMapDocument, layers, val.toPointF()); - break; - default: { - Layer *currentLayer = static_cast(mObject); - switch (currentLayer->layerType()) { - case Layer::TileLayerType: - command = applyTileLayerValueTo(id, val, layersOfType(layers, Layer::TileLayerType)); - break; - case Layer::ObjectGroupType: - command = applyObjectGroupValueTo(id, val, layersOfType(layers, Layer::ObjectGroupType)); - break; - case Layer::ImageLayerType: - command = applyImageLayerValueTo(id, val, layersOfType(layers, Layer::ImageLayerType)); - break; - case Layer::GroupLayerType: - command = applyGroupLayerValueTo(id, val, layersOfType(layers, Layer::GroupLayerType)); - break; - } - break; - } - } - - if (command) - mDocument->undoStack()->push(command); -} - -QUndoCommand *PropertyBrowser::applyTileLayerValueTo(PropertyId id, const QVariant &val, QList tileLayers) -{ - Q_UNUSED(id) - Q_UNUSED(val) - Q_UNUSED(tileLayers) - - return nullptr; -} - -QUndoCommand *PropertyBrowser::applyObjectGroupValueTo(PropertyId id, const QVariant &val, QList objectGroups) -{ - if (objectGroups.isEmpty()) - return nullptr; - - switch (id) { - case ColorProperty: { - const QColor color = val.value(); - return new ChangeObjectGroupColor(mMapDocument, - std::move(objectGroups), - color); - } - case DrawOrderProperty: { - ObjectGroup::DrawOrder drawOrder = static_cast(val.toInt()); - return new ChangeObjectGroupDrawOrder(mMapDocument, - std::move(objectGroups), - drawOrder); - } - default: - return nullptr; - } -} - -QUndoCommand *PropertyBrowser::applyImageLayerValueTo(PropertyId id, const QVariant &val, QList imageLayers) -{ - if (imageLayers.isEmpty()) - return nullptr; - - switch (id) { - case ImageSourceProperty: - return new ChangeImageLayerImageSource(mMapDocument, std::move(imageLayers), - val.value().url); - case ColorProperty: - return new ChangeImageLayerTransparentColor(mMapDocument, std::move(imageLayers), - val.value()); - case RepeatXProperty: - return new ChangeImageLayerRepeatX(mMapDocument, std::move(imageLayers), val.toBool()); - case RepeatYProperty: - return new ChangeImageLayerRepeatY(mMapDocument, std::move(imageLayers), val.toBool()); - default: - return nullptr; - } -} - -QUndoCommand *PropertyBrowser::applyGroupLayerValueTo(PropertyId id, const QVariant &val, QList groupLayers) -{ - Q_UNUSED(id) - Q_UNUSED(val) - Q_UNUSED(groupLayers) - - return nullptr; -} - -void PropertyBrowser::applyTilesetValue(PropertyId id, const QVariant &val) -{ - Tileset *tileset = static_cast(mObject); - QUndoStack *undoStack = mDocument->undoStack(); - - switch (id) { - case FileNameProperty: { - FilePath filePath = val.value(); - QString error; - SharedTileset newTileset = TilesetManager::instance()->loadTileset(filePath.url.toLocalFile(), &error); - if (!newTileset) { - QMessageBox::critical(window(), tr("Error Reading Tileset"), error); - return; - } - - int index = mMapDocument->map()->tilesets().indexOf(tileset->sharedFromThis()); - if (index != -1) - undoStack->push(new ReplaceTileset(mMapDocument, index, newTileset)); - - break; - } - case NameProperty: - Q_ASSERT(mTilesetDocument); - undoStack->push(new RenameTileset(mTilesetDocument, val.toString())); - break; - case ObjectAlignmentProperty: { - Q_ASSERT(mTilesetDocument); - const auto objectAlignment = static_cast(val.toInt()); - undoStack->push(new ChangeTilesetObjectAlignment(mTilesetDocument, - objectAlignment)); - break; - } - case TileRenderSizeProperty: { - Q_ASSERT(mTilesetDocument); - const auto tileRenderSize = static_cast(val.toInt()); - undoStack->push(new ChangeTilesetTileRenderSize(mTilesetDocument, - tileRenderSize)); - break; - } - case FillModeProperty: { - Q_ASSERT(mTilesetDocument); - const auto fillMode = static_cast(val.toInt()); - undoStack->push(new ChangeTilesetFillMode(mTilesetDocument, - fillMode)); - break; - } - case TileOffsetProperty: - Q_ASSERT(mTilesetDocument); - undoStack->push(new ChangeTilesetTileOffset(mTilesetDocument, - val.toPoint())); - break; - case OrientationProperty: { - Q_ASSERT(mTilesetDocument); - auto orientation = static_cast(val.toInt()); - undoStack->push(new ChangeTilesetOrientation(mTilesetDocument, - orientation)); - break; - } - case GridWidthProperty: { - Q_ASSERT(mTilesetDocument); - QSize gridSize = tileset->gridSize(); - gridSize.setWidth(val.toInt()); - undoStack->push(new ChangeTilesetGridSize(mTilesetDocument, - gridSize)); - break; - } - case GridHeightProperty: { - Q_ASSERT(mTilesetDocument); - QSize gridSize = tileset->gridSize(); - gridSize.setHeight(val.toInt()); - undoStack->push(new ChangeTilesetGridSize(mTilesetDocument, - gridSize)); - break; - } - case ColumnCountProperty: - Q_ASSERT(mTilesetDocument); - undoStack->push(new ChangeTilesetColumnCount(mTilesetDocument, - val.toInt())); - break; - case BackgroundColorProperty: - Q_ASSERT(mTilesetDocument); - undoStack->push(new ChangeTilesetBackgroundColor(mTilesetDocument, - val.value())); - break; - case AllowFlipHorizontallyProperty: - case AllowFlipVerticallyProperty: - case AllowRotateProperty: - case PreferUntransformedProperty: { - Q_ASSERT(mTilesetDocument); - - Tileset::TransformationFlag flag = Tileset::NoTransformation; - switch (id) { - case AllowFlipHorizontallyProperty: - flag = Tileset::AllowFlipHorizontally; - break; - case AllowFlipVerticallyProperty: - flag = Tileset::AllowFlipVertically; - break; - case AllowRotateProperty: - flag = Tileset::AllowRotate; - break; - case PreferUntransformedProperty: - flag = Tileset::PreferUntransformed; - break; - default: - return; - } - - auto flags = tileset->transformationFlags(); - flags.setFlag(flag, val.toBool()); - - undoStack->push(new ChangeTilesetTransformationFlags(mTilesetDocument, flags)); - break; - } - default: - break; - } -} - -void PropertyBrowser::applyTileValue(PropertyId id, const QVariant &val) -{ - Q_ASSERT(mTilesetDocument); - - Tile *tile = static_cast(mObject); - QUndoStack *undoStack = mDocument->undoStack(); - - switch (id) { - case TileProbabilityProperty: - undoStack->push(new ChangeTileProbability(mTilesetDocument, - mTilesetDocument->selectedTiles(), - val.toFloat())); - break; - case ImageRectProperty: - undoStack->push(new ChangeTileImageRect(mTilesetDocument, - { tile }, { val.toRect() })); - break; - case ImageSourceProperty: { - const FilePath filePath = val.value(); - undoStack->push(new ChangeTileImageSource(mTilesetDocument, - tile, filePath.url)); - break; - } - default: - break; - } -} - -void PropertyBrowser::applyWangSetValue(PropertyId id, const QVariant &val) -{ - Q_ASSERT(mTilesetDocument); - - WangSet *wangSet = static_cast(mObject); - - switch (id) { - case NameProperty: - mDocument->undoStack()->push(new RenameWangSet(mTilesetDocument, - wangSet, - val.toString())); - break; - case WangSetTypeProperty: { - auto type = static_cast(val.toInt()); - mDocument->undoStack()->push(new ChangeWangSetType(mTilesetDocument, - wangSet, - type)); - break; - } - case ColorCountProperty: - mDocument->undoStack()->push(new ChangeWangSetColorCount(mTilesetDocument, - wangSet, - val.toInt())); - break; - default: - break; - } -} - -void PropertyBrowser::applyWangColorValue(PropertyId id, const QVariant &val) -{ - Q_ASSERT(mTilesetDocument); - - WangColor *wangColor = static_cast(mObject); - - switch (id) { - case NameProperty: - mDocument->undoStack()->push(new ChangeWangColorName(mTilesetDocument, - wangColor, - val.toString())); - break; - case ColorProperty: - mDocument->undoStack()->push(new ChangeWangColorColor(mTilesetDocument, - wangColor, - val.value())); - break; - case WangColorProbabilityProperty: - mDocument->undoStack()->push(new ChangeWangColorProbability(mTilesetDocument, - wangColor, - val.toDouble())); - break; - default: - break; - } -} - -/** - * @warning This function does not add the property to the view. - */ -QtVariantProperty *PropertyBrowser::createProperty(PropertyId id, int type, - const QString &name) -{ - Q_ASSERT(!mIdToProperty.contains(id)); - - QtVariantProperty *property = mVariantManager->addProperty(type, name); - if (!property) { - // fall back to string property for unsupported property types - property = mVariantManager->addProperty(QMetaType::QString, name); - } - - if (type == QMetaType::Bool) - property->setAttribute(QLatin1String("textVisible"), false); - - mPropertyToId.insert(property, id); - mIdToProperty.insert(id, property); - - return property; -} - -QtVariantProperty *PropertyBrowser::createCustomProperty(const QString &name, - const QVariant &value) -{ - Q_ASSERT(mObject); - - QtVariantProperty *property = mCustomPropertiesHelper.createProperty(name, value); - - if (mObject->isPartOfTileset()) - property->setEnabled(mTilesetDocument); - - return property; -} - -QtVariantProperty *PropertyBrowser::addProperty(PropertyId id, int type, - const QString &name, - QtProperty *parent) -{ - QtVariantProperty *property = createProperty(id, type, name); - parent->addSubProperty(property); - return property; -} - -QtVariantProperty *PropertyBrowser::addCustomProperty(const QString &name, const QVariant &value) -{ - // Determine the property preceding the new property, if any - const QList properties = mCustomPropertiesGroup->subProperties(); - QtProperty *precedingProperty = nullptr; - for (int i = 0; i < properties.size(); ++i) { - if (properties.at(i)->propertyName() < name) - precedingProperty = properties.at(i); - else - break; - } - - QScopedValueRollback updating(mUpdating, true); - QtVariantProperty *property = createCustomProperty(name, value); - mCustomPropertiesGroup->insertSubProperty(property, precedingProperty); - - // Collapse custom color properties, to save space - if (value.userType() == QMetaType::QColor) - setExpanded(items(property).constFirst(), false); - - return property; -} - -void PropertyBrowser::setCustomPropertyValue(QtVariantProperty *property, - const QVariant &value) -{ - const QVariant displayValue = toDisplayValue(value); - - if (displayValue.userType() != property->valueType()) { - // Re-creating the property is necessary to change its type - recreateProperty(property, value); - } else { - QScopedValueRollback updating(mUpdating, true); - property->setValue(displayValue); - } -} - -void PropertyBrowser::recreateProperty(QtVariantProperty *property, const QVariant &value) -{ - const QString name = property->propertyName(); - const bool wasCurrent = currentItem() && currentItem()->property() == property; - - mCustomPropertiesHelper.deleteProperty(property); - property = addCustomProperty(name, value); - updateCustomPropertyColor(name); - - if (wasCurrent) - setCurrentItem(items(property).constFirst()); -} - -void PropertyBrowser::addProperties() -{ - if (!mObject) - return; - - Q_ASSERT(mUpdating); - - // Add the built-in properties for each object type - switch (mObject->typeId()) { - case Object::MapType: addMapProperties(); break; - case Object::MapObjectType: addMapObjectProperties(); break; - case Object::LayerType: - switch (static_cast(mObject)->layerType()) { - case Layer::TileLayerType: addTileLayerProperties(); break; - case Layer::ObjectGroupType: addObjectGroupProperties(); break; - case Layer::ImageLayerType: addImageLayerProperties(); break; - case Layer::GroupLayerType: addGroupLayerProperties(); break; - } - break; - case Object::TilesetType: addTilesetProperties(); break; - case Object::TileType: addTileProperties(); break; - case Object::WangSetType: addWangSetProperties(); break; - case Object::WangColorType: addWangColorProperties(); break; - case Object::ProjectType: break; - case Object::WorldType: break; - } - - // Make sure certain properties are collapsed, to save space - for (const PropertyId id : { - ColorProperty, - BackgroundColorProperty, - FontProperty, - TintColorProperty, - ImageRectProperty }) { - if (QtProperty *property = mIdToProperty.value(id)) - setExpanded(items(property).constFirst(), false); - } - - // Add a node for the custom properties - mCustomPropertiesGroup = mGroupManager->addProperty(tr("Custom Properties")); - addProperty(mCustomPropertiesGroup); - - updateProperties(); - updateCustomProperties(); -} - -void PropertyBrowser::removeProperties() -{ - Q_ASSERT(mUpdating); - - mCustomPropertiesHelper.clear(); - mVariantManager->clear(); - mGroupManager->clear(); - mPropertyToId.clear(); - mIdToProperty.clear(); - mCustomPropertiesGroup = nullptr; -} - -void PropertyBrowser::updateProperties() -{ - Q_ASSERT(mObject); - - QScopedValueRollback updating(mUpdating, true); - - if (auto classProperty = mIdToProperty.value(ClassProperty)) - classProperty->setValue(mObject->className()); - - switch (mObject->typeId()) { - case Object::MapType: { - const Map *map = static_cast(mObject); - mIdToProperty[WidthProperty]->setValue(map->width()); - mIdToProperty[HeightProperty]->setValue(map->height()); - mIdToProperty[TileWidthProperty]->setValue(map->tileWidth()); - mIdToProperty[TileHeightProperty]->setValue(map->tileHeight()); - mIdToProperty[InfiniteProperty]->setValue(map->infinite()); - mIdToProperty[OrientationProperty]->setValue(map->orientation() - 1); - mIdToProperty[HexSideLengthProperty]->setValue(map->hexSideLength()); - mIdToProperty[StaggerAxisProperty]->setValue(map->staggerAxis()); - mIdToProperty[StaggerIndexProperty]->setValue(map->staggerIndex()); - mIdToProperty[ParallaxOriginProperty]->setValue(map->parallaxOrigin()); - mIdToProperty[LayerFormatProperty]->setValue(mLayerFormatValues.indexOf(map->layerDataFormat())); - mIdToProperty[CompressionLevelProperty]->setValue(map->compressionLevel()); - mIdToProperty[RenderOrderProperty]->setValue(map->renderOrder()); - mIdToProperty[BackgroundColorProperty]->setValue(map->backgroundColor()); - mIdToProperty[ChunkWidthProperty]->setValue(map->chunkSize().width()); - mIdToProperty[ChunkHeightProperty]->setValue(map->chunkSize().height()); - break; - } - case Object::MapObjectType: { - const MapObject *mapObject = static_cast(mObject); - const int flags = mapObjectFlags(mapObject); - - if (mMapObjectFlags != flags) { - UpdatingProperties updatingProperties(this, mUpdating, true); - removeProperties(); - addProperties(); - return; - } - - const QString &className = mapObject->effectiveClassName(); - const auto classColorGroup = mapObject->className().isEmpty() ? QPalette::Disabled - : QPalette::Active; - - FilePath templateFilePath; - if (auto objectTemplate = mapObject->objectTemplate()) - templateFilePath.url = QUrl::fromLocalFile(objectTemplate->fileName()); - - mIdToProperty[IdProperty]->setValue(mapObject->id()); - mIdToProperty[TemplateProperty]->setValue(QVariant::fromValue(templateFilePath)); - mIdToProperty[NameProperty]->setValue(mapObject->name()); - mIdToProperty[ClassProperty]->setValue(className); - mIdToProperty[ClassProperty]->setValueColor(palette().color(classColorGroup, QPalette::WindowText)); - if (auto visibleProperty = mIdToProperty[VisibleProperty]) - visibleProperty->setValue(mapObject->isVisible()); - mIdToProperty[XProperty]->setValue(mapObject->x()); - mIdToProperty[YProperty]->setValue(mapObject->y()); - - if (flags & ObjectHasDimensions) { - mIdToProperty[WidthProperty]->setValue(mapObject->width()); - mIdToProperty[HeightProperty]->setValue(mapObject->height()); - } - - mIdToProperty[RotationProperty]->setValue(mapObject->rotation()); - - if (flags & ObjectHasTile) { - int flippingFlags = 0; - if (mapObject->cell().flippedHorizontally()) - flippingFlags |= 1; - if (mapObject->cell().flippedVertically()) - flippingFlags |= 2; - mIdToProperty[FlippingProperty]->setValue(flippingFlags); - } - - if (flags & ObjectIsText) { - const auto& textData = mapObject->textData(); - mIdToProperty[TextProperty]->setValue(textData.text); - mIdToProperty[FontProperty]->setValue(textData.font); - mIdToProperty[TextAlignmentProperty]->setValue(QVariant::fromValue(textData.alignment)); - mIdToProperty[WordWrapProperty]->setValue(textData.wordWrap); - mIdToProperty[ColorProperty]->setValue(textData.color); - } - break; - } - case Object::LayerType: { - const Layer *layer = static_cast(mObject); - - mIdToProperty[IdProperty]->setValue(layer->id()); - mIdToProperty[NameProperty]->setValue(layer->name()); - mIdToProperty[VisibleProperty]->setValue(layer->isVisible()); - mIdToProperty[LockedProperty]->setValue(layer->isLocked()); - mIdToProperty[OpacityProperty]->setValue(layer->opacity()); - mIdToProperty[TintColorProperty]->setValue(layer->tintColor()); - mIdToProperty[OffsetXProperty]->setValue(layer->offset().x()); - mIdToProperty[OffsetYProperty]->setValue(layer->offset().y()); - mIdToProperty[ParallaxFactorProperty]->setValue(layer->parallaxFactor()); - - switch (layer->layerType()) { - case Layer::TileLayerType: - break; - case Layer::ObjectGroupType: { - const ObjectGroup *objectGroup = static_cast(layer); - const QColor color = objectGroup->color(); - mIdToProperty[ColorProperty]->setValue(color); - mIdToProperty[DrawOrderProperty]->setValue(objectGroup->drawOrder()); - break; - } - case Layer::ImageLayerType: { - const ImageLayer *imageLayer = static_cast(layer); - mIdToProperty[ImageSourceProperty]->setValue(QVariant::fromValue(FilePath { imageLayer->imageSource() })); - mIdToProperty[ColorProperty]->setValue(imageLayer->transparentColor()); - mIdToProperty[RepeatXProperty]->setValue(imageLayer->repeatX()); - mIdToProperty[RepeatYProperty]->setValue(imageLayer->repeatY()); - break; - } - case Layer::GroupLayerType: - break; - } - break; - } - case Object::TilesetType: { - Tileset *tileset = static_cast(mObject); - - if (QtVariantProperty *fileNameProperty = mIdToProperty.value(FileNameProperty)) - fileNameProperty->setValue(QVariant::fromValue(FilePath { QUrl::fromLocalFile(tileset->fileName()) })); - - mIdToProperty[BackgroundColorProperty]->setValue(tileset->backgroundColor()); - - mIdToProperty[NameProperty]->setValue(tileset->name()); - mIdToProperty[ObjectAlignmentProperty]->setValue(tileset->objectAlignment()); - mIdToProperty[TileRenderSizeProperty]->setValue(tileset->tileRenderSize()); - mIdToProperty[FillModeProperty]->setValue(tileset->fillMode()); - mIdToProperty[TileOffsetProperty]->setValue(tileset->tileOffset()); - mIdToProperty[OrientationProperty]->setValue(tileset->orientation()); - mIdToProperty[GridWidthProperty]->setValue(tileset->gridSize().width()); - mIdToProperty[GridHeightProperty]->setValue(tileset->gridSize().height()); - mIdToProperty[ColumnCountProperty]->setValue(tileset->columnCount()); - mIdToProperty[ColumnCountProperty]->setEnabled(mTilesetDocument && tileset->isCollection()); - - if (!tileset->isCollection()) { - mIdToProperty[TilesetImageParametersProperty]->setValue(QVariant::fromValue(mTilesetDocument)); - mIdToProperty[ImageSourceProperty]->setValue(tileset->imageSource().toString(QUrl::PreferLocalFile)); - mIdToProperty[TileWidthProperty]->setValue(tileset->tileWidth()); - mIdToProperty[TileHeightProperty]->setValue(tileset->tileHeight()); - mIdToProperty[MarginProperty]->setValue(tileset->margin()); - mIdToProperty[SpacingProperty]->setValue(tileset->tileSpacing()); - mIdToProperty[ColorProperty]->setValue(tileset->transparentColor()); - } - - const auto flags = tileset->transformationFlags(); - mIdToProperty[AllowFlipHorizontallyProperty]->setValue(flags.testFlag(Tileset::AllowFlipHorizontally)); - mIdToProperty[AllowFlipVerticallyProperty]->setValue(flags.testFlag(Tileset::AllowFlipVertically)); - mIdToProperty[AllowRotateProperty]->setValue(flags.testFlag(Tileset::AllowRotate)); - mIdToProperty[PreferUntransformedProperty]->setValue(flags.testFlag(Tileset::PreferUntransformed)); - break; - } - case Object::TileType: { - const Tile *tile = static_cast(mObject); - const QSize tileSize = tile->size(); - mIdToProperty[IdProperty]->setValue(tile->id()); - mIdToProperty[WidthProperty]->setValue(tileSize.width()); - mIdToProperty[HeightProperty]->setValue(tileSize.height()); - mIdToProperty[TileProbabilityProperty]->setValue(tile->probability()); - if (QtVariantProperty *imageSourceProperty = mIdToProperty.value(ImageSourceProperty)) - imageSourceProperty->setValue(QVariant::fromValue(FilePath { tile->imageSource() })); - mIdToProperty[ImageRectProperty]->setValue(tile->imageRect()); - break; - } - case Object::WangSetType: { - const WangSet *wangSet = static_cast(mObject); - mIdToProperty[NameProperty]->setValue(wangSet->name()); - mIdToProperty[WangSetTypeProperty]->setValue(wangSet->type()); - mIdToProperty[ColorCountProperty]->setValue(wangSet->colorCount()); - break; - } - case Object::WangColorType: { - const WangColor *wangColor = static_cast(mObject); - mIdToProperty[NameProperty]->setValue(wangColor->name()); - mIdToProperty[ColorProperty]->setValue(wangColor->color()); - mIdToProperty[WangColorProbabilityProperty]->setValue(wangColor->probability()); - break; - } - case Object::ProjectType: - break; - case Object::WorldType: - break; - } -} - -Properties PropertyBrowser::combinedProperties() const -{ - Properties combinedProperties; - - // Add properties from selected objects which mObject does not contain to mCombinedProperties. - const auto currentObjects = mDocument->currentObjects(); - for (Object *obj : currentObjects) { - if (obj != mObject) - mergeProperties(combinedProperties, obj->properties()); - } - - if (isAutomappingRulesMap(mMapDocument)) - addAutomappingProperties(combinedProperties, mObject); - - const QString &className = mObject->typeId() == Object::MapObjectType ? static_cast(mObject)->effectiveClassName() - : mObject->className(); - - // Inherit properties from the class - if (auto type = Object::propertyTypes().findClassFor(className, *mObject)) - mergeProperties(combinedProperties, type->members); - - if (mObject->typeId() == Object::MapObjectType) { - auto mapObject = static_cast(mObject); - - // Inherit properties from the tile - if (const Tile *tile = mapObject->cell().tile()) - mergeProperties(combinedProperties, tile->properties()); - - // Inherit properties from the template - if (const MapObject *templateObject = mapObject->templateObject()) - mergeProperties(combinedProperties, templateObject->properties()); - } - - mergeProperties(combinedProperties, mObject->properties()); - - return combinedProperties; -} - -void PropertyBrowser::updateCustomProperties() -{ - if (!mObject) - return; - - UpdatingProperties updatingProperties(this, mUpdating); - - mCustomPropertiesHelper.clear(); - - QMapIterator it(combinedProperties()); - while (it.hasNext()) { - it.next(); - - QtVariantProperty *property = createCustomProperty(it.key(), it.value()); - mCustomPropertiesGroup->addSubProperty(property); - - // Collapse custom color properties, to save space - if (property->valueType() == QMetaType::QColor) - setExpanded(items(property).constFirst(), false); - - updateCustomPropertyColor(it.key()); - } -} - -void PropertyBrowser::updateCustomPropertyColor(const QString &name) -{ - if (QtVariantProperty *property = mCustomPropertiesHelper.property(name)) - updateCustomPropertyColor(property); -} - -void PropertyBrowser::updateCustomPropertyColors() -{ - for (QtVariantProperty *property : mCustomPropertiesHelper.properties()) - updateCustomPropertyColor(property); -} - -// If there are other objects selected check if their properties are equal. If not give them a gray color. -void PropertyBrowser::updateCustomPropertyColor(QtVariantProperty *property) -{ - if (!property->isEnabled()) - return; - - const QString propertyName = property->propertyName(); - const QString propertyValue = property->valueText(); - - const auto &objects = mDocument->currentObjects(); - - const QPalette palette = QGuiApplication::palette(); - const QColor textColor = palette.color(QPalette::Active, QPalette::WindowText); - const QColor disabledTextColor = palette.color(QPalette::Disabled, QPalette::WindowText); - - // If one of the objects doesn't have this property then gray out the name and value. - for (Object *obj : objects) { - if (!obj->hasProperty(propertyName)) { - property->setNameColor(disabledTextColor); - property->setValueColor(disabledTextColor); - return; - } - } - - // If one of the objects doesn't have the same property value then gray out the value. - for (Object *obj : objects) { - if (obj == mObject) - continue; - if (obj->property(propertyName) != propertyValue) { - property->setNameColor(textColor); - property->setValueColor(disabledTextColor); - return; - } - } - - property->setNameColor(textColor); - property->setValueColor(textColor); -} - -QVariant PropertyBrowser::toDisplayValue(QVariant value) const -{ - return mCustomPropertiesHelper.toDisplayValue(value); -} - -QVariant PropertyBrowser::fromDisplayValue(QtProperty *property, QVariant value) const -{ - return mCustomPropertiesHelper.fromDisplayValue(property, value); -} - -void PropertyBrowser::retranslateUi() -{ - mStaggerAxisNames.clear(); - mStaggerAxisNames.append(tr("X")); - mStaggerAxisNames.append(tr("Y")); - - mStaggerIndexNames.clear(); - mStaggerIndexNames.append(tr("Odd")); - mStaggerIndexNames.append(tr("Even")); - - mOrientationNames.clear(); - mOrientationNames.append(QCoreApplication::translate("Tiled::NewMapDialog", "Orthogonal")); - mOrientationNames.append(QCoreApplication::translate("Tiled::NewMapDialog", "Isometric")); - mOrientationNames.append(QCoreApplication::translate("Tiled::NewMapDialog", "Isometric (Staggered)")); - mOrientationNames.append(QCoreApplication::translate("Tiled::NewMapDialog", "Hexagonal (Staggered)")); - - mTilesetOrientationNames.clear(); - mTilesetOrientationNames.append(mOrientationNames.at(0)); - mTilesetOrientationNames.append(mOrientationNames.at(1)); - - mTileRenderSizeNames.clear(); - mTileRenderSizeNames.append(tr("Tile Size")); - mTileRenderSizeNames.append(tr("Map Grid Size")); - - mFillModeNames.clear(); - mFillModeNames.append(tr("Stretch")); - mFillModeNames.append(tr("Preserve Aspect Ratio")); - - mLayerFormatNames.clear(); - mLayerFormatValues.clear(); - - mLayerFormatNames.append(QCoreApplication::translate("PreferencesDialog", "XML (deprecated)")); - mLayerFormatNames.append(QCoreApplication::translate("PreferencesDialog", "Base64 (uncompressed)")); - mLayerFormatNames.append(QCoreApplication::translate("PreferencesDialog", "Base64 (gzip compressed)")); - mLayerFormatNames.append(QCoreApplication::translate("PreferencesDialog", "Base64 (zlib compressed)")); - - mLayerFormatValues.append(Map::XML); - mLayerFormatValues.append(Map::Base64); - mLayerFormatValues.append(Map::Base64Gzip); - mLayerFormatValues.append(Map::Base64Zlib); - - if (compressionSupported(Zstandard)) { - mLayerFormatNames.append(QCoreApplication::translate("PreferencesDialog", "Base64 (Zstandard compressed)")); - mLayerFormatValues.append(Map::Base64Zstandard); - } - - mLayerFormatNames.append(QCoreApplication::translate("PreferencesDialog", "CSV")); - mLayerFormatValues.append(Map::CSV); - - mRenderOrderNames.clear(); - mRenderOrderNames.append(QCoreApplication::translate("PreferencesDialog", "Right Down")); - mRenderOrderNames.append(QCoreApplication::translate("PreferencesDialog", "Right Up")); - mRenderOrderNames.append(QCoreApplication::translate("PreferencesDialog", "Left Down")); - mRenderOrderNames.append(QCoreApplication::translate("PreferencesDialog", "Left Up")); - - mAlignmentNames.clear(); - mAlignmentNames.append(tr("Unspecified")); - mAlignmentNames.append(tr("Top Left")); - mAlignmentNames.append(tr("Top")); - mAlignmentNames.append(tr("Top Right")); - mAlignmentNames.append(tr("Left")); - mAlignmentNames.append(tr("Center")); - mAlignmentNames.append(tr("Right")); - mAlignmentNames.append(tr("Bottom Left")); - mAlignmentNames.append(tr("Bottom")); - mAlignmentNames.append(tr("Bottom Right")); - - mFlippingFlagNames.clear(); - mFlippingFlagNames.append(tr("Horizontal")); - mFlippingFlagNames.append(tr("Vertical")); - - mDrawOrderNames.clear(); - mDrawOrderNames.append(tr("Top Down")); - mDrawOrderNames.append(tr("Manual")); - - mWangSetTypeNames.clear(); - mWangSetTypeNames.append(tr("Corner")); - mWangSetTypeNames.append(tr("Edge")); - mWangSetTypeNames.append(tr("Mixed")); - - UpdatingProperties updatingProperties(this, mUpdating); - removeProperties(); - addProperties(); -} - -} // namespace Tiled - -#include "moc_propertybrowser.cpp" diff --git a/src/tiled/propertybrowser.h b/src/tiled/propertybrowser.h deleted file mode 100644 index ead7b6f2aa..0000000000 --- a/src/tiled/propertybrowser.h +++ /dev/null @@ -1,259 +0,0 @@ -/* - * propertybrowser.h - * Copyright 2013-2021, Thorbjørn Lindeijer - * - * This file is part of Tiled. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#pragma once - -#include "changeevents.h" -#include "custompropertieshelper.h" -#include "map.h" -#include "properties.h" - -#include - -#include - -class QUndoCommand; - -class QtGroupPropertyManager; -class QtVariantProperty; -class QtVariantPropertyManager; - -namespace Tiled { - -class GroupLayer; -class ImageLayer; -class MapObject; -class ObjectGroup; -class Tile; -class TileLayer; -class Tileset; - -class Document; -class MapDocument; -class TilesetDocument; - -class PropertyBrowser : public QtTreePropertyBrowser -{ - Q_OBJECT - -public: - explicit PropertyBrowser(QWidget *parent = nullptr); - - void setObject(Object *object); - Object *object() const; - - void setDocument(Document *document); - - bool isCustomPropertyItem(const QtBrowserItem *item) const; - bool allCustomPropertyItems(const QList &items) const; - - void selectCustomProperty(const QString &name); - void editCustomProperty(const QString &name); - - QSize sizeHint() const override; - -protected: - bool event(QEvent *event) override; - -private: - void documentChanged(const ChangeEvent &change); - void mapChanged(); - void mapObjectsChanged(const MapObjectsChangeEvent &mapObjectsChange); - void tilesetChanged(Tileset *tileset); - void tileChanged(Tile *tile); - void tileTypeChanged(Tile *tile); - void wangSetChanged(WangSet *wangSet); - - void propertyAdded(Object *object, const QString &name); - void propertyRemoved(Object *object, const QString &name); - void propertyChanged(Object *object, const QString &name); - void propertiesChanged(Object *object); - void selectedObjectsChanged(); - void selectedLayersChanged(); - void selectedTilesChanged(); - - void propertyTypesChanged(); - - void valueChanged(QtProperty *property, const QVariant &val); - void customPropertyValueChanged(const QStringList &path, const QVariant &value); - - void resetProperty(QtProperty *property); - - enum PropertyId { - NameProperty, - ClassProperty, - XProperty, - YProperty, - WidthProperty, - HeightProperty, - RotationProperty, - VisibleProperty, - LockedProperty, - OpacityProperty, - TextProperty, - TextAlignmentProperty, - FontProperty, - WordWrapProperty, - OffsetXProperty, - OffsetYProperty, - ParallaxFactorProperty, - RepeatXProperty, - RepeatYProperty, - ColorProperty, - BackgroundColorProperty, - TileWidthProperty, - TileHeightProperty, - GridWidthProperty, - GridHeightProperty, - OrientationProperty, - HexSideLengthProperty, - StaggerAxisProperty, - StaggerIndexProperty, - ParallaxOriginProperty, - RenderOrderProperty, - LayerFormatProperty, - ImageSourceProperty, - ImageRectProperty, - TilesetImageParametersProperty, - FlippingProperty, - DrawOrderProperty, - FileNameProperty, - ObjectAlignmentProperty, - TileRenderSizeProperty, - FillModeProperty, - TileOffsetProperty, - MarginProperty, - SpacingProperty, - TileProbabilityProperty, - ColumnCountProperty, - IdProperty, - ColorCountProperty, - WangColorProbabilityProperty, - WangSetTypeProperty, - InfiniteProperty, - TemplateProperty, - CompressionLevelProperty, - ChunkWidthProperty, - ChunkHeightProperty, - TintColorProperty, - AllowFlipHorizontallyProperty, - AllowFlipVerticallyProperty, - AllowRotateProperty, - PreferUntransformedProperty, - }; - - void addMapProperties(); - void addMapObjectProperties(); - void addLayerProperties(QtProperty *parent); - void addTileLayerProperties(); - void addObjectGroupProperties(); - void addImageLayerProperties(); - void addGroupLayerProperties(); - void addTilesetProperties(); - void addTileProperties(); - void addWangSetProperties(); - void addWangColorProperties(); - - QtVariantProperty *addClassProperty(QtProperty *parent); - - void applyMapValue(PropertyId id, const QVariant &val); - void applyMapObjectValue(PropertyId id, const QVariant &val); - QUndoCommand *applyMapObjectValueTo(PropertyId id, const QVariant &val, MapObject *mapObject); - void applyLayerValue(PropertyId id, const QVariant &val); - QUndoCommand *applyTileLayerValueTo(PropertyId id, const QVariant &val, QList tileLayers); - QUndoCommand *applyObjectGroupValueTo(PropertyId id, const QVariant &val, QList objectGroups); - QUndoCommand *applyImageLayerValueTo(PropertyId id, const QVariant &val, QList imageLayers); - QUndoCommand *applyGroupLayerValueTo(PropertyId id, const QVariant &val, QList groupLayers); - void applyTilesetValue(PropertyId id, const QVariant &val); - void applyTileValue(PropertyId id, const QVariant &val); - void applyWangSetValue(PropertyId id, const QVariant &val); - void applyWangColorValue(PropertyId id, const QVariant &val); - - QtVariantProperty *createProperty(PropertyId id, - int type, - const QString &name); - QtVariantProperty *createCustomProperty(const QString &name, - const QVariant &value); - - using QtTreePropertyBrowser::addProperty; - QtVariantProperty *addProperty(PropertyId id, - int type, - const QString &name, - QtProperty *parent); - - QtVariantProperty *addCustomProperty(const QString &name, const QVariant &value); - void setCustomPropertyValue(QtVariantProperty *property, const QVariant &value); - void recreateProperty(QtVariantProperty *property, const QVariant &value); - - void addProperties(); - void removeProperties(); - void updateProperties(); - Properties combinedProperties() const; - void updateCustomProperties(); - - void updateCustomPropertyColor(const QString &name); - void updateCustomPropertyColors(); - void updateCustomPropertyColor(QtVariantProperty *property); - - QVariant toDisplayValue(QVariant value) const; - QVariant fromDisplayValue(QtProperty *property, QVariant value) const; - - void retranslateUi(); - - bool mUpdating = false; - int mMapObjectFlags = 0; - Object *mObject = nullptr; - Document *mDocument = nullptr; - MapDocument *mMapDocument = nullptr; - TilesetDocument *mTilesetDocument = nullptr; - - QtVariantPropertyManager *mVariantManager; - QtGroupPropertyManager *mGroupManager; - QtProperty *mCustomPropertiesGroup; - - QHash mPropertyToId; - QHash mIdToProperty; - CustomPropertiesHelper mCustomPropertiesHelper; - - QStringList mStaggerAxisNames; - QStringList mStaggerIndexNames; - QStringList mOrientationNames; - QStringList mTilesetOrientationNames; - QStringList mTileRenderSizeNames; - QStringList mFillModeNames; - QStringList mLayerFormatNames; - QList mLayerFormatValues; - QStringList mRenderOrderNames; - QStringList mAlignmentNames; - QStringList mFlippingFlagNames; - QStringList mDrawOrderNames; - QStringList mWangSetTypeNames; - QMap mWangSetIcons; -}; - -/** - * Returns the object for which the properties are displayed. - */ -inline Object *PropertyBrowser::object() const -{ - return mObject; -} - -} // namespace Tiled diff --git a/src/tiled/propertyeditorwidgets.cpp b/src/tiled/propertyeditorwidgets.cpp new file mode 100644 index 0000000000..c7f794a562 --- /dev/null +++ b/src/tiled/propertyeditorwidgets.cpp @@ -0,0 +1,940 @@ +/* + * propertyeditorwidgets.cpp + * Copyright 2024, Thorbjørn Lindeijer + * + * This file is part of Tiled. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "propertyeditorwidgets.h" + +#include "propertiesview.h" +#include "utils.h" + +#include +#include +#include +#include +#include +#include + +namespace Tiled { + +/** + * A layout for label/widget pairs, wrapping them either two per row or each on + * their own row, depending on the available space. + * + * The labels are forced to width of the widest label, while the widgets share + * the remaining space. + */ +class PairwiseWrappingLayout : public QLayout +{ + Q_OBJECT + +public: + struct WidgetPair { + QLabel *label; + QWidget *widget; + }; + + PairwiseWrappingLayout(const QVector &widgetPairs, + QWidget *parent); + ~PairwiseWrappingLayout(); + + void addItem(QLayoutItem *item) override + { m_items.append(item); } + + Qt::Orientations expandingDirections() const override + { return {}; } + + bool hasHeightForWidth() const override + { return true; } + + int heightForWidth(int width) const override + { return doLayout(QRect(0, 0, width, 0), true); } + + int count() const override + { return m_items.size(); } + + QLayoutItem *itemAt(int index) const override + { return m_items.value(index); } + + QSize minimumSize() const override; + void setGeometry(const QRect &rect) override; + + QSize sizeHint() const override + { return minimumSize(); } + + QLayoutItem *takeAt(int index) override; + +private: + int doLayout(const QRect &rect, bool testOnly) const; + int minimumTwoColumnWidth() const; + + QList m_items; +}; + +PairwiseWrappingLayout::PairwiseWrappingLayout(const QVector &widgetPairs, + QWidget *parent) + : QLayout(parent) +{ + setContentsMargins(QMargins()); + setSpacing(Utils::dpiScaled(2) * 2); + + const int horizontalMargin = Utils::dpiScaled(3); + + for (auto &pair : widgetPairs) { + pair.label->setAlignment(Qt::AlignCenter); + pair.label->setContentsMargins(horizontalMargin, 0, horizontalMargin, 0); + addWidget(pair.label); + addWidget(pair.widget); + } +} + +PairwiseWrappingLayout::~PairwiseWrappingLayout() +{ + while (QLayoutItem *item = takeAt(0)) + delete item; +} + +QLayoutItem *PairwiseWrappingLayout::takeAt(int index) +{ + if (index >= 0 && index < m_items.size()) + return m_items.takeAt(index); + return nullptr; +} + +void PairwiseWrappingLayout::setGeometry(const QRect &rect) +{ + QLayout::setGeometry(rect); + doLayout(rect, false); +} + +QSize PairwiseWrappingLayout::minimumSize() const +{ + QSize size; + size.setWidth(minimumTwoColumnWidth()); + size.setHeight(doLayout(QRect(0, 0, size.width(), 0), true)); + +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) + const auto margins = contentsMargins(); + return QSize(size.width() + margins.left() + margins.right(), + size.height() + margins.top() + margins.bottom()); +#else + return size.grownBy(contentsMargins()); +#endif +} + +int PairwiseWrappingLayout::doLayout(const QRect &rect, bool testOnly) const +{ + const auto margins = contentsMargins(); + const QRect effectiveRect = rect.marginsRemoved(margins); + const int spacing = QLayout::spacing(); + const int columns = effectiveRect.width() < minimumTwoColumnWidth() ? 1 : 2; + + // For simplicity, all lines will have the same height. Even columns will + // get their width from the widest label, whereas odd columns will share + // the remaining space. + int lineHeight = 0; + int maxLabelWidth = 0; + for (qsizetype i = 0; i < m_items.size(); ++i) { + const auto sizeHint = m_items.at(i)->minimumSize(); + lineHeight = qMax(lineHeight, sizeHint.height()); + if (i % 2 == 0) + maxLabelWidth = qMax(maxLabelWidth, sizeHint.width()); + } + + if (testOnly) { + const int lines = (m_items.size() / 2 + columns - 1) / columns; + return margins.top() + margins.bottom() + + lines * (lineHeight + spacing) - spacing; + } + + int totalWidgetWidth = (effectiveRect.width() - + maxLabelWidth * columns - + spacing * (columns * 2 - 1)); + QList widgetWidths; + for (int i = columns; i > 0; --i) { + widgetWidths.append(totalWidgetWidth / i); + totalWidgetWidth -= widgetWidths.last(); + } + + int x = effectiveRect.x(); + int y = effectiveRect.y(); + for (qsizetype i = 0; i < m_items.size(); ++i) { + const int column = i / 2 % columns; + const QSize size((i % 2 == 0) ? maxLabelWidth + : widgetWidths.at(column), + lineHeight); + + m_items.at(i)->setGeometry(QRect(QPoint(x, y), size)); + x += size.width() + spacing; + + if (column == columns - 1 && (i % 2 == 1)) { + x = effectiveRect.x(); + y += lineHeight + spacing; + } + } + + return 0; +} + +int PairwiseWrappingLayout::minimumTwoColumnWidth() const +{ + const int spacing = QLayout::spacing(); + int sum = 0; + int minimum = 0; + int index = 0; + + for (qsizetype i = 0; i < m_items.size() - 1; i += 2) { + sum += (m_items.at(i)->minimumSize().width() + + m_items.at(i + 1)->minimumSize().width() + + spacing * 2); + + if (++index % 2 == 0) { + minimum = std::max(sum - spacing, minimum); + sum = 0; + } + } + + return minimum; +} + + +/** + * Returns whether the given event is a shortcut override event for the undo or + * redo shortcuts. We generally want to use the global undo and redo shortcuts + * instead. + */ +static bool isUndoRedoShortcutOverride(QEvent *event) +{ + if (event->type() == QEvent::ShortcutOverride) { + auto ke = static_cast(event); + return (ke == QKeySequence::Redo || ke == QKeySequence::Undo); + } + return false; +} + +/** + * Strips a floating point number representation of redundant trailing zeros. + * Examples: + * + * 0.01000 -> 0.01 + * 3.000 -> 3.0 + */ +static QString removeRedundantTrialingZeros(const QString &text) +{ + const QString decimalPoint = QLocale::system().decimalPoint(); + const auto decimalPointIndex = text.lastIndexOf(decimalPoint); + if (decimalPointIndex < 0) // return if there is no decimal point + return text; + + const auto afterDecimalPoint = decimalPointIndex + decimalPoint.length(); + int redundantZeros = 0; + + for (int i = text.length() - 1; i > afterDecimalPoint && text.at(i) == QLatin1Char('0'); --i) + ++redundantZeros; + + return text.left(text.length() - redundantZeros); +} + + +void Slider::wheelEvent(QWheelEvent *event) +{ + if (!hasFocus()) + event->ignore(); + else + QSlider::wheelEvent(event); +} + + +bool LineEdit::event(QEvent *event) +{ + if (isUndoRedoShortcutOverride(event)) + return false; + + return QLineEdit::event(event); +} + + +ComboBox::ComboBox(QWidget *parent) + : QComboBox(parent) +{ + // Combo boxes in properties view don't adjust to their contents + setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); + + // Don't take focus by mouse wheel + if (focusPolicy() == Qt::WheelFocus) + setFocusPolicy(Qt::StrongFocus); +} + +bool ComboBox::event(QEvent *event) +{ + if (isUndoRedoShortcutOverride(event)) // relevant when editable + return false; + + return QComboBox::event(event); +} + +void ComboBox::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Enter: + case Qt::Key_Return: + emit returnPressed(); + return; + } + + QComboBox::keyPressEvent(event); +} + +void ComboBox::wheelEvent(QWheelEvent *event) +{ + if (!hasFocus()) + event->ignore(); + else + QComboBox::wheelEvent(event); +} + + +SpinBox::SpinBox(QWidget *parent) + : QSpinBox(parent) +{ + // Allow the full range by default. + setRange(std::numeric_limits::lowest(), + std::numeric_limits::max()); + + // Don't take focus by mouse wheel + setFocusPolicy(Qt::StrongFocus); + + // Allow the widget to shrink horizontally. + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); +} + +QSize SpinBox::minimumSizeHint() const +{ + // Don't adjust the horizontal size hint based on the maximum value. + auto hint = QSpinBox::minimumSizeHint(); + hint.setWidth(Utils::dpiScaled(50)); + return hint; +} + +bool SpinBox::event(QEvent *event) +{ + if (isUndoRedoShortcutOverride(event)) // relevant when editable + return false; + + return QSpinBox::event(event); +} + +void SpinBox::wheelEvent(QWheelEvent *event) +{ + if (!hasFocus()) + event->ignore(); + else + QSpinBox::wheelEvent(event); +} + + +DoubleSpinBox::DoubleSpinBox(QWidget *parent) + : QDoubleSpinBox(parent) +{ + // Allow the full range by default. + setRange(std::numeric_limits::lowest(), + std::numeric_limits::max()); + + // Increase possible precision. + setDecimals(9); + + // Don't take focus by mouse wheel + setFocusPolicy(Qt::StrongFocus); + + // Allow the widget to shrink horizontally. + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); +} + +QSize DoubleSpinBox::minimumSizeHint() const +{ + // Don't adjust the horizontal size hint based on the maximum value. + auto hint = QDoubleSpinBox::minimumSizeHint(); + hint.setWidth(Utils::dpiScaled(65)); + return hint; +} + +QString DoubleSpinBox::textFromValue(double val) const +{ + auto text = QDoubleSpinBox::textFromValue(val); + + // remove redundant trailing 0's in case of high precision + if (decimals() > 3) + return removeRedundantTrialingZeros(text); + + return text; +} + +bool DoubleSpinBox::event(QEvent *event) +{ + if (isUndoRedoShortcutOverride(event)) // relevant when editable + return false; + + return QDoubleSpinBox::event(event); +} + +void DoubleSpinBox::wheelEvent(QWheelEvent *event) +{ + if (!hasFocus()) + event->ignore(); + else + QDoubleSpinBox::wheelEvent(event); +} + + +SizeEdit::SizeEdit(QWidget *parent) + : QWidget(parent) + , m_widthLabel(new QLabel(QStringLiteral("W"), this)) + , m_heightLabel(new QLabel(QStringLiteral("H"), this)) + , m_widthSpinBox(new SpinBox(this)) + , m_heightSpinBox(new SpinBox(this)) +{ + new PairwiseWrappingLayout({ + { m_widthLabel, m_widthSpinBox }, + { m_heightLabel, m_heightSpinBox }, + }, this); + + connect(m_widthSpinBox, qOverload(&QSpinBox::valueChanged), this, &SizeEdit::valueChanged); + connect(m_heightSpinBox, qOverload(&QSpinBox::valueChanged), this, &SizeEdit::valueChanged); +} + +void SizeEdit::setValue(const QSize &size) +{ + m_widthSpinBox->setValue(size.width()); + m_heightSpinBox->setValue(size.height()); +} + +QSize SizeEdit::value() const +{ + return QSize(m_widthSpinBox->value(), + m_heightSpinBox->value()); +} + +void SizeEdit::setMinimum(int minimum) +{ + m_widthSpinBox->setMinimum(minimum); + m_heightSpinBox->setMinimum(minimum); +} + +void SizeEdit::setSuffix(const QString &suffix) +{ + m_widthSpinBox->setSuffix(suffix); + m_heightSpinBox->setSuffix(suffix); +} + + +SizeFEdit::SizeFEdit(QWidget *parent) + : QWidget(parent) + , m_widthLabel(new QLabel(QStringLiteral("W"), this)) + , m_heightLabel(new QLabel(QStringLiteral("H"), this)) + , m_widthSpinBox(new DoubleSpinBox(this)) + , m_heightSpinBox(new DoubleSpinBox(this)) +{ + new PairwiseWrappingLayout({ + { m_widthLabel, m_widthSpinBox }, + { m_heightLabel, m_heightSpinBox }, + }, this); + + connect(m_widthSpinBox, qOverload(&QDoubleSpinBox::valueChanged), this, &SizeFEdit::valueChanged); + connect(m_heightSpinBox, qOverload(&QDoubleSpinBox::valueChanged), this, &SizeFEdit::valueChanged); +} + +void SizeFEdit::setValue(const QSizeF &size) +{ + m_widthSpinBox->setValue(size.width()); + m_heightSpinBox->setValue(size.height()); +} + +QSizeF SizeFEdit::value() const +{ + return QSizeF(m_widthSpinBox->value(), + m_heightSpinBox->value()); +} + + +PointEdit::PointEdit(QWidget *parent) + : QWidget(parent) + , m_xLabel(new QLabel(QStringLiteral("X"), this)) + , m_yLabel(new QLabel(QStringLiteral("Y"), this)) + , m_xSpinBox(new SpinBox(this)) + , m_ySpinBox(new SpinBox(this)) +{ + new PairwiseWrappingLayout({ + { m_xLabel, m_xSpinBox }, + { m_yLabel, m_ySpinBox }, + }, this); + + connect(m_xSpinBox, qOverload(&QSpinBox::valueChanged), this, &PointEdit::valueChanged); + connect(m_ySpinBox, qOverload(&QSpinBox::valueChanged), this, &PointEdit::valueChanged); +} + +void PointEdit::setValue(const QPoint &point) +{ + m_xSpinBox->setValue(point.x()); + m_ySpinBox->setValue(point.y()); +} + +QPoint PointEdit::value() const +{ + return QPoint(m_xSpinBox->value(), + m_ySpinBox->value()); +} + +void PointEdit::setSuffix(const QString &suffix) +{ + m_xSpinBox->setSuffix(suffix); + m_ySpinBox->setSuffix(suffix); +} + + +PointFEdit::PointFEdit(QWidget *parent) + : QWidget(parent) + , m_xLabel(new QLabel(QStringLiteral("X"), this)) + , m_yLabel(new QLabel(QStringLiteral("Y"), this)) + , m_xSpinBox(new DoubleSpinBox(this)) + , m_ySpinBox(new DoubleSpinBox(this)) +{ + new PairwiseWrappingLayout({ + { m_xLabel, m_xSpinBox }, + { m_yLabel, m_ySpinBox }, + }, this); + + connect(m_xSpinBox, qOverload(&QDoubleSpinBox::valueChanged), this, &PointFEdit::valueChanged); + connect(m_ySpinBox, qOverload(&QDoubleSpinBox::valueChanged), this, &PointFEdit::valueChanged); +} + +void PointFEdit::setValue(const QPointF &point) +{ + m_xSpinBox->setValue(point.x()); + m_ySpinBox->setValue(point.y()); +} + +QPointF PointFEdit::value() const +{ + return QPointF(m_xSpinBox->value(), + m_ySpinBox->value()); +} + +void PointFEdit::setSingleStep(double step) +{ + m_xSpinBox->setSingleStep(step); + m_ySpinBox->setSingleStep(step); +} + + +RectEdit::RectEdit(QWidget *parent) + : QWidget(parent) + , m_xLabel(new QLabel(QStringLiteral("X"), this)) + , m_yLabel(new QLabel(QStringLiteral("Y"), this)) + , m_widthLabel(new QLabel(QStringLiteral("W"), this)) + , m_heightLabel(new QLabel(QStringLiteral("H"), this)) + , m_xSpinBox(new SpinBox(this)) + , m_ySpinBox(new SpinBox(this)) + , m_widthSpinBox(new SpinBox(this)) + , m_heightSpinBox(new SpinBox(this)) +{ + new PairwiseWrappingLayout({ + { m_xLabel, m_xSpinBox }, + { m_yLabel, m_ySpinBox }, + { m_widthLabel, m_widthSpinBox }, + { m_heightLabel, m_heightSpinBox }, + }, this); + + m_widthSpinBox->setMinimum(0); + m_heightSpinBox->setMinimum(0); + + connect(m_xSpinBox, qOverload(&QSpinBox::valueChanged), this, &RectEdit::valueChanged); + connect(m_ySpinBox, qOverload(&QSpinBox::valueChanged), this, &RectEdit::valueChanged); + connect(m_widthSpinBox, qOverload(&QSpinBox::valueChanged), this, &RectEdit::valueChanged); + connect(m_heightSpinBox, qOverload(&QSpinBox::valueChanged), this, &RectEdit::valueChanged); +} + +void RectEdit::setValue(const QRect &rect) +{ + m_xSpinBox->setValue(rect.x()); + m_ySpinBox->setValue(rect.y()); + m_widthSpinBox->setValue(rect.width()); + m_heightSpinBox->setValue(rect.height()); +} + +QRect RectEdit::value() const +{ + return QRect(m_xSpinBox->value(), + m_ySpinBox->value(), + m_widthSpinBox->value(), + m_heightSpinBox->value()); +} + +void RectEdit::setConstraint(const QRect &constraint) +{ + if (constraint.isNull()) { + m_xSpinBox->setRange(std::numeric_limits::lowest(), + std::numeric_limits::max()); + m_ySpinBox->setRange(std::numeric_limits::lowest(), + std::numeric_limits::max()); + m_widthSpinBox->setRange(0, std::numeric_limits::max()); + m_heightSpinBox->setRange(0, std::numeric_limits::max()); + } else { + m_xSpinBox->setRange(constraint.left(), constraint.right() + 1); + m_ySpinBox->setRange(constraint.top(), constraint.bottom() + 1); + m_widthSpinBox->setRange(0, constraint.width()); + m_heightSpinBox->setRange(0, constraint.height()); + } +} + + +RectFEdit::RectFEdit(QWidget *parent) + : QWidget(parent) + , m_xLabel(new QLabel(QStringLiteral("X"), this)) + , m_yLabel(new QLabel(QStringLiteral("Y"), this)) + , m_widthLabel(new QLabel(QStringLiteral("W"), this)) + , m_heightLabel(new QLabel(QStringLiteral("H"), this)) + , m_xSpinBox(new DoubleSpinBox(this)) + , m_ySpinBox(new DoubleSpinBox(this)) + , m_widthSpinBox(new DoubleSpinBox(this)) + , m_heightSpinBox(new DoubleSpinBox(this)) +{ + new PairwiseWrappingLayout({ + { m_xLabel, m_xSpinBox }, + { m_yLabel, m_ySpinBox }, + { m_widthLabel, m_widthSpinBox }, + { m_heightLabel, m_heightSpinBox }, + }, this); + + connect(m_xSpinBox, qOverload(&QDoubleSpinBox::valueChanged), this, &RectFEdit::valueChanged); + connect(m_ySpinBox, qOverload(&QDoubleSpinBox::valueChanged), this, &RectFEdit::valueChanged); + connect(m_widthSpinBox, qOverload(&QDoubleSpinBox::valueChanged), this, &RectFEdit::valueChanged); + connect(m_heightSpinBox, qOverload(&QDoubleSpinBox::valueChanged), this, &RectFEdit::valueChanged); +} + +void RectFEdit::setValue(const QRectF &rect) +{ + m_xSpinBox->setValue(rect.x()); + m_ySpinBox->setValue(rect.y()); + m_widthSpinBox->setValue(rect.width()); + m_heightSpinBox->setValue(rect.height()); +} + +QRectF RectFEdit::value() const +{ + return QRectF(m_xSpinBox->value(), + m_ySpinBox->value(), + m_widthSpinBox->value(), + m_heightSpinBox->value()); +} + + +ElidingLabel::ElidingLabel(QWidget *parent) + : ElidingLabel(QString(), parent) +{} + +ElidingLabel::ElidingLabel(const QString &text, QWidget *parent) + : QLabel(text, parent) +{ + setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed)); +} + +/** + * Sets a tool tip on the label. + * + * When a tool tip is set, it will be shown instead of the on-demand tool tip + * that shows the full text when the text is elided. + */ +void ElidingLabel::setToolTip(const QString &toolTip) +{ + if (m_toolTip == toolTip) + return; + + m_toolTip = toolTip; + + if (m_toolTip.isEmpty()) + QLabel::setToolTip(m_isElided ? text() : QString()); + else + QLabel::setToolTip(m_toolTip); +} + +void ElidingLabel::setSelected(bool selected) +{ + if (m_selected == selected) + return; + + m_selected = selected; + update(); +} + +QSize ElidingLabel::minimumSizeHint() const +{ + auto hint = QLabel::minimumSizeHint(); + hint.setWidth(std::min(hint.width(), Utils::dpiScaled(30))); + return hint; +} + +void ElidingLabel::paintEvent(QPaintEvent *) +{ + QStyleOption opt; + opt.initFrom(this); + + const int m = margin(); + const QRect cr = contentsRect().adjusted(m, m, -m, -m); + const int align = QStyle::visualAlignment(opt.direction, alignment()); + const int flags = align | (opt.direction == Qt::LeftToRight ? Qt::TextForceLeftToRight + : Qt::TextForceRightToLeft); + + const auto elidedText = opt.fontMetrics.elidedText(text(), Qt::ElideRight, cr.width()); + const bool isElided = elidedText != text(); + + if (isElided != m_isElided) { + m_isElided = isElided; + + if (m_toolTip.isEmpty()) + QLabel::setToolTip(m_isElided ? text() : QString()); + } + + QStylePainter p(this); + QPalette::ColorRole role = m_selected ? QPalette::HighlightedText : foregroundRole(); + p.drawItemText(cr, flags, opt.palette, isEnabled(), elidedText, role); +} + + +PropertyLabel::PropertyLabel(QWidget *parent) + : ElidingLabel(parent) +{ + setMinimumWidth(Utils::dpiScaled(50)); + updateContentMargins(); +} + +void PropertyLabel::setLevel(int level) +{ + if (m_level == level) + return; + + m_level = level; + updateContentMargins(); +} + +void PropertyLabel::setHeader(bool header) +{ + if (m_header == header) + return; + + m_header = header; + setBackgroundRole(header ? QPalette::Dark : QPalette::NoRole); + setForegroundRole(header ? QPalette::BrightText : QPalette::NoRole); + setAutoFillBackground(header); + updateContentMargins(); +} + +void PropertyLabel::setExpandable(bool expandable) +{ + if (m_expandable == expandable) + return; + + m_expandable = expandable; + update(); +} + +void PropertyLabel::setExpanded(bool expanded) +{ + if (m_expanded == expanded) + return; + + m_expanded = expanded; + update(); + emit toggled(m_expanded); +} + +void PropertyLabel::setModified(bool modified) +{ + auto f = font(); + f.setBold(modified); + setFont(f); +} + +bool PropertyLabel::event(QEvent *event) +{ + switch (event->type()) { + // Handled here instead of in mousePressEvent because we want it to be + // expandable also when the label is disabled. + case QEvent::MouseButtonPress: { + const auto pos = static_cast(event)->pos(); + if (!isHeader() && !branchIndicatorRect().contains(pos)) + break; + } + [[fallthrough]]; + case QEvent::MouseButtonDblClick: + if (m_expandable) { + if (static_cast(event)->button() == Qt::LeftButton) { + setExpanded(!m_expanded); + return true; + } + } + break; + + case QEvent::LayoutDirectionChange: + updateContentMargins(); + break; + + default: + break; + } + + return ElidingLabel::event(event); +} + +void PropertyLabel::paintEvent(QPaintEvent *event) +{ + ElidingLabel::paintEvent(event); + + QStyleOption branchOption; + branchOption.initFrom(this); + branchOption.rect = branchIndicatorRect(); + + if (isSelected()) + branchOption.state |= QStyle::State_Selected; + if (m_expandable) + branchOption.state |= QStyle::State_Children; + if (m_expanded) + branchOption.state |= QStyle::State_Open; + + QStylePainter p(this); + p.drawPrimitive(QStyle::PE_IndicatorBranch, branchOption); + + if (m_header) { + const QColor color = static_cast(p.style()->styleHint(QStyle::SH_Table_GridLineColor, &branchOption)); + p.save(); + p.setPen(QPen(color)); + p.drawLine(0, height() - 1, width(), height() - 1); + p.restore(); + } +} + +void PropertyLabel::updateContentMargins() +{ + const int spacing = Utils::dpiScaled(3); + const int branchIndicatorWidth = Utils::dpiScaled(14); + const int verticalSpacing = m_header ? spacing : 0; + const int indent = branchIndicatorWidth * (m_level + 1); + + if (isLeftToRight()) + setContentsMargins(spacing + indent, verticalSpacing, spacing, verticalSpacing); + else + setContentsMargins(spacing, verticalSpacing, spacing + indent, verticalSpacing); +} + +QRect PropertyLabel::branchIndicatorRect() const +{ + const int spacing = Utils::dpiScaled(3); + const int branchIndicatorWidth = Utils::dpiScaled(14); + const int indent = branchIndicatorWidth * m_level; + + if (layoutDirection() == Qt::LeftToRight) { + return QRect(indent, 0, + branchIndicatorWidth + spacing, height()); + } else { + return QRect(width() - indent - branchIndicatorWidth - spacing, 0, + branchIndicatorWidth + spacing, height()); + } +} + +/** + * To fit better alongside other widgets without vertical centering, the size + * hint is adjusted to match that of a QLineEdit. + */ +QSize PropertyLabel::sizeHint() const +{ + constexpr int QLineEditPrivate_verticalMargin = 1; + constexpr int QLineEditPrivate_horizontalMargin = 2; + + auto fm = fontMetrics(); + auto cm = contentsMargins(); + const int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, this); + int h = qMax(fm.height(), qMax(14, iconSize - 2)) + 2 * QLineEditPrivate_verticalMargin + + cm.top() + cm.bottom(); + int w = fm.horizontalAdvance(u'x') * 17 + 2 * QLineEditPrivate_horizontalMargin + + cm.left() + cm.right(); + QStyleOptionFrame opt; + initStyleOption(&opt); + return style()->sizeFromContents(QStyle::CT_LineEdit, &opt, QSize(w, h), this); +} + + +PropertyWidget::PropertyWidget(Property *property, QWidget *parent) + : QWidget(parent) + , m_property(property) +{ + setSelected(property->isSelected()); + + connect(property, &Property::selectedChanged, this, &PropertyWidget::setSelected); +} + +void PropertyWidget::setSelectable(bool selectable) +{ + if (m_selectable == selectable) + return; + + m_selectable = selectable; + + if (!selectable) + setSelected(false); +} + +void PropertyWidget::setSelected(bool selected) +{ + if (m_selected == selected) + return; + + m_selected = selected; + update(); +} + +void PropertyWidget::paintEvent(QPaintEvent *event) +{ + QWidget::paintEvent(event); + + const auto halfSpacing = Utils::dpiScaled(2); + const QRect r = rect().adjusted(halfSpacing, 0, -halfSpacing, 0); + QStylePainter painter(this); + + if (isSelected()) + painter.fillRect(r, palette().highlight()); + + if (hasFocus()) { + QStyleOptionFocusRect option; + option.initFrom(this); + option.rect = r; + option.backgroundColor = palette().color(backgroundRole()); + option.state |= QStyle::State_KeyboardFocusChange; + + painter.drawPrimitive(QStyle::PE_FrameFocusRect, option); + } +} + +void PropertyWidget::mousePressEvent(QMouseEvent *event) +{ + setFocus(Qt::MouseFocusReason); + emit mousePressed(event->button(), event->modifiers()); +} + +} // namespace Tiled + +#include "moc_propertyeditorwidgets.cpp" +#include "propertyeditorwidgets.moc" diff --git a/src/tiled/propertyeditorwidgets.h b/src/tiled/propertyeditorwidgets.h new file mode 100644 index 0000000000..d28e6a4e29 --- /dev/null +++ b/src/tiled/propertyeditorwidgets.h @@ -0,0 +1,391 @@ +/* + * propertyeditorwidgets.h + * Copyright 2024, Thorbjørn Lindeijer + * + * This file is part of Tiled. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#pragma once + +#include +#include +#include +#include +#include + +class QLabel; + +namespace Tiled { + +class Property; + +/** + * A slider that doesn't respond to wheel events when not focused. + */ +class Slider : public QSlider +{ + Q_OBJECT + +public: + using QSlider::QSlider; + +protected: + void wheelEvent(QWheelEvent *event) override; +}; + +/** + * A line edit that doesn't override global undo/redo shortcuts. + */ +class LineEdit : public QLineEdit +{ + Q_OBJECT + +public: + using QLineEdit::QLineEdit; + +protected: + bool event(QEvent *event) override; +}; + +/** + * A combo box that doesn't respond to wheel events when not focused and + * doesn't override global undo/redo shortcuts. + */ +class ComboBox : public QComboBox +{ + Q_OBJECT + +public: + ComboBox(QWidget *parent = nullptr); + +signals: + /** This signal is emitted when the Return or Enter key is pressed. */ + void returnPressed(); + +protected: + bool event(QEvent *event) override; + void keyPressEvent(QKeyEvent *event) override; + void wheelEvent(QWheelEvent *event) override; +}; + +/** + * A spin box that allows the full range by default and shrinks horizontally. + * It also doesn't adjust the horizontal size hint based on the maximum value + * and doesn't respond to wheel events when not focused. + */ +class SpinBox : public QSpinBox +{ + Q_OBJECT + +public: + SpinBox(QWidget *parent = nullptr); + + QSize minimumSizeHint() const override; + +protected: + bool event(QEvent *event) override; + void wheelEvent(QWheelEvent *event) override; +}; + +/** + * A double spin box that allows the full range by default and shrinks + * horizontally. It also doesn't adjust the horizontal size hint based on the + * maximum value and doesn't respond to wheel events when not focused. + * + * The precision is increased to 9 decimal places. Redundant trailing 0's are + * removed. + */ +class DoubleSpinBox : public QDoubleSpinBox +{ + Q_OBJECT + +public: + DoubleSpinBox(QWidget *parent = nullptr); + + QSize minimumSizeHint() const override; + QString textFromValue(double val) const override; + +protected: + bool event(QEvent *event) override; + void wheelEvent(QWheelEvent *event) override; +}; + +/** + * A widget for editing a QSize value. + */ +class SizeEdit : public QWidget +{ + Q_OBJECT + Q_PROPERTY(QSize value READ value WRITE setValue NOTIFY valueChanged FINAL) + +public: + SizeEdit(QWidget *parent = nullptr); + + void setValue(const QSize &size); + QSize value() const; + + void setMinimum(int minimum); + void setSuffix(const QString &suffix); + +signals: + void valueChanged(); + +private: + QLabel *m_widthLabel; + QLabel *m_heightLabel; + SpinBox *m_widthSpinBox; + SpinBox *m_heightSpinBox; +}; + +/** + * A widget for editing a QSizeF value. + */ +class SizeFEdit : public QWidget +{ + Q_OBJECT + Q_PROPERTY(QSizeF value READ value WRITE setValue NOTIFY valueChanged FINAL) + +public: + SizeFEdit(QWidget *parent = nullptr); + + void setValue(const QSizeF &size); + QSizeF value() const; + +signals: + void valueChanged(); + +private: + QLabel *m_widthLabel; + QLabel *m_heightLabel; + DoubleSpinBox *m_widthSpinBox; + DoubleSpinBox *m_heightSpinBox; +}; + +/** + * A widget for editing a QPoint value. + */ +class PointEdit : public QWidget +{ + Q_OBJECT + Q_PROPERTY(QPoint value READ value WRITE setValue NOTIFY valueChanged FINAL) + +public: + PointEdit(QWidget *parent = nullptr); + + void setValue(const QPoint &size); + QPoint value() const; + + void setSuffix(const QString &suffix); + +signals: + void valueChanged(); + +private: + QLabel *m_xLabel; + QLabel *m_yLabel; + SpinBox *m_xSpinBox; + SpinBox *m_ySpinBox; +}; + +/** + * A widget for editing a QPointF value. + */ +class PointFEdit : public QWidget +{ + Q_OBJECT + Q_PROPERTY(QPointF value READ value WRITE setValue NOTIFY valueChanged FINAL) + +public: + PointFEdit(QWidget *parent = nullptr); + + void setValue(const QPointF &size); + QPointF value() const; + + void setSingleStep(double step); + +signals: + void valueChanged(); + +private: + QLabel *m_xLabel; + QLabel *m_yLabel; + DoubleSpinBox *m_xSpinBox; + DoubleSpinBox *m_ySpinBox; +}; + +/** + * A widget for editing a QRect value. + */ +class RectEdit : public QWidget +{ + Q_OBJECT + Q_PROPERTY(QRect value READ value WRITE setValue NOTIFY valueChanged FINAL) + +public: + RectEdit(QWidget *parent = nullptr); + + void setValue(const QRect &size); + QRect value() const; + + void setConstraint(const QRect &constraint); + +signals: + void valueChanged(); + +private: + QLabel *m_xLabel; + QLabel *m_yLabel; + QLabel *m_widthLabel; + QLabel *m_heightLabel; + SpinBox *m_xSpinBox; + SpinBox *m_ySpinBox; + SpinBox *m_widthSpinBox; + SpinBox *m_heightSpinBox; +}; + +/** + * A widget for editing a QRectF value. + */ +class RectFEdit : public QWidget +{ + Q_OBJECT + Q_PROPERTY(QRectF value READ value WRITE setValue NOTIFY valueChanged FINAL) + +public: + RectFEdit(QWidget *parent = nullptr); + + void setValue(const QRectF &size); + QRectF value() const; + +signals: + void valueChanged(); + +private: + QLabel *m_xLabel; + QLabel *m_yLabel; + QLabel *m_widthLabel; + QLabel *m_heightLabel; + DoubleSpinBox *m_xSpinBox; + DoubleSpinBox *m_ySpinBox; + DoubleSpinBox *m_widthSpinBox; + DoubleSpinBox *m_heightSpinBox; +}; + +/** + * A label that elides its text if there is not enough space. + * + * The elided text is shown as a tooltip. + */ +class ElidingLabel : public QLabel +{ + Q_OBJECT + +public: + explicit ElidingLabel(QWidget *parent = nullptr); + ElidingLabel(const QString &text, QWidget *parent = nullptr); + + void setToolTip(const QString &toolTip); + + void setSelected(bool selected); + bool isSelected() const { return m_selected; } + + QSize minimumSizeHint() const override; + +protected: + void paintEvent(QPaintEvent *) override; + +private: + QString m_toolTip; + bool m_isElided = false; + bool m_selected = false; +}; + +/** + * A property label widget, which can be a header or just be expandable. + */ +class PropertyLabel : public ElidingLabel +{ + Q_OBJECT + +public: + PropertyLabel(QWidget *parent = nullptr); + + void setLevel(int level); + + void setHeader(bool header); + bool isHeader() const { return m_header; } + + void setExpandable(bool expandable); + bool isExpandable() const { return m_expandable; } + + void setExpanded(bool expanded); + bool isExpanded() const { return m_expanded; } + + void setModified(bool modified); + + QSize sizeHint() const override; + +signals: + void toggled(bool expanded); + +protected: + bool event(QEvent *event) override; + void paintEvent(QPaintEvent *) override; + +private: + void updateContentMargins(); + QRect branchIndicatorRect() const; + + int m_level = 0; + bool m_header = false; + bool m_expandable = false; + bool m_expanded = false; +}; + +/** + * A widget that represents a single property. + */ +class PropertyWidget : public QWidget +{ + Q_OBJECT + +public: + PropertyWidget(Property *property, QWidget *parent = nullptr); + + Property *property() const { return m_property; } + + void setSelectable(bool selectable); + bool isSelectable() const { return m_selectable; } + + void setSelected(bool selected); + bool isSelected() const { return m_selected; } + +signals: + void mousePressed(Qt::MouseButton button, Qt::KeyboardModifiers modifiers); + +protected: + void paintEvent(QPaintEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + +private: + // Protected by QPointer because PropertyWidget might outlive the Property + // for a short moment, due to delayed widget deletion. + QPointer m_property; + bool m_selectable = false; + bool m_selected = false; +}; + +} // namespace Tiled diff --git a/src/tiled/propertytypeseditor.cpp b/src/tiled/propertytypeseditor.cpp index 945519389f..54ab4e7dc6 100644 --- a/src/tiled/propertytypeseditor.cpp +++ b/src/tiled/propertytypeseditor.cpp @@ -21,17 +21,17 @@ #include "propertytypeseditor.h" #include "ui_propertytypeseditor.h" -#include "addpropertydialog.h" #include "colorbutton.h" -#include "custompropertieshelper.h" #include "objecttypes.h" #include "preferences.h" #include "project.h" #include "projectmanager.h" +#include "propertiesview.h" #include "propertytypesmodel.h" #include "savefile.h" #include "session.h" #include "utils.h" +#include "variantmapproperty.h" #include #include @@ -50,9 +50,6 @@ #endif #include -#include -#include - namespace Tiled { static QToolBar *createSmallToolBar(QWidget *parent) @@ -225,7 +222,7 @@ PropertyTypesEditor::PropertyTypesEditor(QWidget *parent) connect(mRemoveMemberAction, &QAction::triggered, this, &PropertyTypesEditor::removeMember); connect(mRenameMemberAction, &QAction::triggered, - this, &PropertyTypesEditor::renameMember); + this, &PropertyTypesEditor::renameSelectedMember); connect(mPropertyTypesModel, &PropertyTypesModel::nameChanged, this, &PropertyTypesEditor::propertyTypeNameChanged); @@ -370,10 +367,12 @@ ClassPropertyType *PropertyTypesEditor::selectedClassPropertyType() const return static_cast(propertyType); } -void PropertyTypesEditor::currentMemberItemChanged(QtBrowserItem *item) +void PropertyTypesEditor::selectedMembersChanged() { - mRemoveMemberAction->setEnabled(item); - mRenameMemberAction->setEnabled(item); + const auto properties = mMembersView->selectedProperties(); + const bool singlePropertySelected = properties.size() == 1; + mRemoveMemberAction->setEnabled(singlePropertySelected); + mRenameMemberAction->setEnabled(singlePropertySelected); } void PropertyTypesEditor::propertyTypeNameChanged(const QModelIndex &index, const PropertyType &type) @@ -568,11 +567,23 @@ void PropertyTypesEditor::openAddMemberDialog() if (!propertyType || !propertyType->isClass()) return; - AddPropertyDialog dialog(static_cast(propertyType), this); - dialog.setWindowTitle(tr("Add Member")); + if (!mAddValueProperty) { + mAddValueProperty = new AddValueProperty(mMembersProperty); + mAddValueProperty->setPlaceholderText(tr("Member name")); + mAddValueProperty->setParentClassType(static_cast(propertyType)); + + connect(mAddValueProperty, &Property::addRequested, this, [this] { + addMember(mAddValueProperty->name(), mAddValueProperty->value()); + mMembersProperty->deleteProperty(mAddValueProperty); + }); + connect(mAddValueProperty, &Property::removeRequested, this, [this] { + mMembersProperty->deleteProperty(mAddValueProperty); + }); + + mMembersProperty->addProperty(mAddValueProperty); + } - if (dialog.exec() == AddPropertyDialog::Accepted) - addMember(dialog.propertyName(), QVariant(dialog.propertyValue())); + mMembersView->focusProperty(mAddValueProperty, PropertiesView::FocusLabel); } void PropertyTypesEditor::addMember(const QString &name, const QVariant &value) @@ -594,31 +605,24 @@ void PropertyTypesEditor::addMember(const QString &name, const QVariant &value) applyMemberToSelectedType(name, value); updateDetails(); - editMember(name); -} - -void PropertyTypesEditor::editMember(const QString &name) -{ - QtVariantProperty *property = mPropertiesHelper->property(name); - if (!property) - return; - const QList propertyItems = mMembersView->items(property); - if (!propertyItems.isEmpty()) - mMembersView->editItem(propertyItems.first()); + if (auto property = mMembersProperty->property(name)) { + mMembersView->focusProperty(property); + mMembersView->setSelectedProperties({ property }); + } } void PropertyTypesEditor::removeMember() { - QtBrowserItem *item = mMembersView->currentItem(); - if (!item) - return; - PropertyType *propertyType = selectedPropertyType(); if (!propertyType || !propertyType->isClass()) return; - const QString name = item->property()->propertyName(); + const auto properties = mMembersView->selectedProperties(); + if (properties.size() != 1) + return; + + const QString name = properties.first()->name(); if (!confirm(tr("Remove Member"), tr("Are you sure you want to remove '%1' from class '%2'? This action cannot be undone.") @@ -627,51 +631,45 @@ void PropertyTypesEditor::removeMember() } // Select a different item before removing the current one - QList items = mMembersView->topLevelItems(); - if (items.count() > 1) { - const int currentItemIndex = items.indexOf(item); - if (item == items.last()) - mMembersView->setCurrentItem(items.at(currentItemIndex - 1)); + const auto &subProperties = mMembersProperty->subProperties(); + if (subProperties.size() > 1) { + const int currentIndex = subProperties.indexOf(properties.first()); + if (currentIndex == subProperties.size() - 1) + subProperties[currentIndex - 1]->setSelected(true); else - mMembersView->setCurrentItem(items.at(currentItemIndex + 1)); + subProperties[currentIndex + 1]->setSelected(true); } - mPropertiesHelper->deleteProperty(item->property()); - - static_cast(*propertyType).members.remove(name); - - applyPropertyTypes(); + mMembersProperty->removeMember(name); } -void PropertyTypesEditor::renameMember() +void PropertyTypesEditor::renameSelectedMember() { - QtBrowserItem *item = mMembersView->currentItem(); - if (!item) + const auto properties = mMembersView->selectedProperties(); + if (properties.size() != 1) return; - const QString oldName = item->property()->propertyName(); + renameMember(properties.first()->name()); +} +void PropertyTypesEditor::renameMember(const QString &name) +{ QInputDialog *dialog = new QInputDialog(mMembersView); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->setInputMode(QInputDialog::TextInput); dialog->setLabelText(tr("Name:")); - dialog->setTextValue(oldName); + dialog->setTextValue(name); dialog->setWindowTitle(tr("Rename Member")); - connect(dialog, &QInputDialog::textValueSelected, this, &PropertyTypesEditor::renameMemberTo); + connect(dialog, &QInputDialog::textValueSelected, this, [=] (const QString &newName) { + renameMemberTo(name, newName); + }); + dialog->open(); } -void PropertyTypesEditor::renameMemberTo(const QString &name) +void PropertyTypesEditor::renameMemberTo(const QString &oldName, const QString &name) { - if (name.isEmpty()) - return; - - QtBrowserItem *item = mMembersView->currentItem(); - if (!item) - return; - - const QString oldName = item->property()->propertyName(); - if (oldName == name) + if (name.isEmpty() || oldName == name) return; auto propertyType = selectedPropertyType(); @@ -838,18 +836,7 @@ void PropertyTypesEditor::updateDetails() mDrawFillCheckBox->setChecked(classType.drawFill); updateClassUsageDetails(classType); - mPropertiesHelper->clear(); - - QMapIterator it(classType.members); - while (it.hasNext()) { - it.next(); - - const QString &name = it.key(); - const QVariant &value = it.value(); - - QtProperty *property = mPropertiesHelper->createProperty(name, value); - mMembersView->addProperty(property); - } + mMembersProperty->setValue(classType.members); break; } case PropertyType::PT_Enum: { @@ -902,8 +889,8 @@ void PropertyTypesEditor::setCurrentPropertyType(PropertyType::Type type) mCurrentPropertyType = type; - delete mPropertiesHelper; - mPropertiesHelper = nullptr; + delete mMembersProperty; + mMembersProperty = nullptr; while (mDetailsLayout->rowCount() > 0) mDetailsLayout->removeRow(0); @@ -956,14 +943,19 @@ void PropertyTypesEditor::addClassProperties() nameAndColor->addWidget(mColorButton); nameAndColor->addWidget(mDrawFillCheckBox); - mMembersView = new QtTreePropertyBrowser(this); - mPropertiesHelper = new CustomPropertiesHelper(mMembersView, this); + mMembersView = new PropertiesView(this); + + const auto halfSpacing = Utils::dpiScaled(2); + mMembersView->widget()->setContentsMargins(0, halfSpacing, 0, halfSpacing); + + mMembersProperty = new VariantMapProperty(QString(), this); + mMembersView->setRootProperty(mMembersProperty); - connect(mPropertiesHelper, &CustomPropertiesHelper::propertyMemberValueChanged, - this, &PropertyTypesEditor::memberValueChanged); + connect(mMembersProperty, &VariantMapProperty::valueChanged, + this, &PropertyTypesEditor::classMembersChanged); - connect(mMembersView, &QtTreePropertyBrowser::currentItemChanged, - this, &PropertyTypesEditor::currentMemberItemChanged); + connect(mMembersView, &PropertiesView::selectedPropertiesChanged, + this, &PropertyTypesEditor::selectedMembersChanged); mUseAsPropertyCheckBox = new QCheckBox(tr("Property value")); @@ -1124,7 +1116,7 @@ void PropertyTypesEditor::setUsageFlags(int flags, bool value) } } -void PropertyTypesEditor::memberValueChanged(const QStringList &path, const QVariant &value) +void PropertyTypesEditor::classMembersChanged() { if (mUpdatingDetails) return; @@ -1133,18 +1125,7 @@ void PropertyTypesEditor::memberValueChanged(const QStringList &path, const QVar if (!classType) return; - if (!setPropertyMemberValue(classType->members, path, value)) - return; - - // When a nested property was changed, we need to update the value of the - // top-level property to match. - if (path.size() > 1) { - auto &topLevelName = path.first(); - if (auto property = mPropertiesHelper->property(topLevelName)) { - QScopedValueRollback updatingDetails(mUpdatingDetails, true); - property->setValue(mPropertiesHelper->toDisplayValue(classType->members.value(topLevelName))); - } - } + classType->members = mMembersProperty->value(); applyPropertyTypes(); } diff --git a/src/tiled/propertytypeseditor.h b/src/tiled/propertytypeseditor.h index 1f853b98ad..b4db664506 100644 --- a/src/tiled/propertytypeseditor.h +++ b/src/tiled/propertytypeseditor.h @@ -23,6 +23,7 @@ #include "propertytype.h" #include +#include class QCheckBox; class QComboBox; @@ -33,7 +34,6 @@ class QStringListModel; class QTreeView; class QtBrowserItem; -class QtTreePropertyBrowser; namespace Ui { class PropertyTypesEditor; @@ -41,9 +41,11 @@ class PropertyTypesEditor; namespace Tiled { +class AddValueProperty; class ColorButton; -class CustomPropertiesHelper; +class PropertiesView; class PropertyTypesModel; +class VariantMapProperty; struct PropertyTypesFilter { @@ -79,7 +81,7 @@ class PropertyTypesEditor : public QDialog PropertyType *selectedPropertyType() const; ClassPropertyType *selectedClassPropertyType() const; - void currentMemberItemChanged(QtBrowserItem *item); + void selectedMembersChanged(); void propertyTypeNameChanged(const QModelIndex &index, const PropertyType &type); @@ -104,10 +106,10 @@ class PropertyTypesEditor : public QDialog void openClassOfPopup(); void openAddMemberDialog(); void addMember(const QString &name, const QVariant &value = QVariant()); - void editMember(const QString &name); void removeMember(); - void renameMember(); - void renameMemberTo(const QString &name); + void renameSelectedMember(); + void renameMember(const QString &name); + void renameMemberTo(const QString &oldName, const QString &name); void importPropertyTypes(); void exportPropertyTypes(); @@ -119,7 +121,7 @@ class PropertyTypesEditor : public QDialog void colorChanged(const QColor &color); void setDrawFill(bool value); void setUsageFlags(int flags, bool value); - void memberValueChanged(const QStringList &path, const QVariant &value); + void classMembersChanged(); void retranslateUi(); @@ -144,8 +146,9 @@ class PropertyTypesEditor : public QDialog QCheckBox *mDrawFillCheckBox = nullptr; QCheckBox *mClassOfCheckBox = nullptr; QPushButton *mClassOfButton = nullptr; - QtTreePropertyBrowser *mMembersView = nullptr; - CustomPropertiesHelper *mPropertiesHelper = nullptr; + PropertiesView *mMembersView = nullptr; + VariantMapProperty *mMembersProperty = nullptr; + QPointer mAddValueProperty; bool mSettingPrefPropertyTypes = false; bool mSettingName = false; diff --git a/src/tiled/resizemap.cpp b/src/tiled/resizemap.cpp index 9cb289207f..3469dc8ecd 100644 --- a/src/tiled/resizemap.cpp +++ b/src/tiled/resizemap.cpp @@ -56,7 +56,7 @@ void ResizeMap::swapSize() map->setHeight(mSize.height()); mSize = oldSize; - emit mMapDocument->mapChanged(); + emit mMapDocument->mapResized(); } } // namespace Tiled diff --git a/src/tiled/resources/images/scalable/text-bold-symbolic.svg b/src/tiled/resources/images/scalable/text-bold-symbolic.svg new file mode 100644 index 0000000000..bdbddea8d2 --- /dev/null +++ b/src/tiled/resources/images/scalable/text-bold-symbolic.svg @@ -0,0 +1,2 @@ + + diff --git a/src/tiled/resources/images/scalable/text-italic-symbolic.svg b/src/tiled/resources/images/scalable/text-italic-symbolic.svg new file mode 100644 index 0000000000..9fa6e67de6 --- /dev/null +++ b/src/tiled/resources/images/scalable/text-italic-symbolic.svg @@ -0,0 +1,2 @@ + + diff --git a/src/tiled/resources/images/scalable/text-strikethrough-symbolic.svg b/src/tiled/resources/images/scalable/text-strikethrough-symbolic.svg new file mode 100644 index 0000000000..6df152de47 --- /dev/null +++ b/src/tiled/resources/images/scalable/text-strikethrough-symbolic.svg @@ -0,0 +1,2 @@ + + diff --git a/src/tiled/resources/images/scalable/text-underline-symbolic.svg b/src/tiled/resources/images/scalable/text-underline-symbolic.svg new file mode 100644 index 0000000000..ff520eb3c7 --- /dev/null +++ b/src/tiled/resources/images/scalable/text-underline-symbolic.svg @@ -0,0 +1,2 @@ + + diff --git a/src/tiled/scriptdialog.cpp b/src/tiled/scriptdialog.cpp index 0c8b64afb3..b92a993ac0 100644 --- a/src/tiled/scriptdialog.cpp +++ b/src/tiled/scriptdialog.cpp @@ -26,6 +26,7 @@ #include "mainwindow.h" #include "scriptimage.h" #include "scriptmanager.h" +#include "utils.h" #include #include @@ -41,8 +42,6 @@ #include #include -#include - static const int leftColumnStretch = 0; // stretch as much as we can so that the left column looks as close to zero width as possible when there is no content static const int rightColumnStretch = 1; @@ -51,18 +50,6 @@ namespace Tiled { QSet ScriptDialog::sDialogInstances; -static void deleteAllFromLayout(QLayout *layout) -{ - while (QLayoutItem *item = layout->takeAt(0)) { - delete item->widget(); - - if (QLayout *layout = item->layout()) - deleteAllFromLayout(layout); - - delete item; - } -} - ScriptImageWidget::ScriptImageWidget(Tiled::ScriptImage *image, QWidget *parent) : QLabel(parent) { @@ -144,7 +131,7 @@ void ScriptDialog::initializeLayout() void ScriptDialog::clear() { - deleteAllFromLayout(layout()); + Utils::deleteAllFromLayout(layout()); initializeLayout(); } diff --git a/src/tiled/scriptmodule.cpp b/src/tiled/scriptmodule.cpp index bc70d8edba..b60c6bf519 100644 --- a/src/tiled/scriptmodule.cpp +++ b/src/tiled/scriptmodule.cpp @@ -74,8 +74,8 @@ ScriptModule::ScriptModule(QObject *parent) ScriptModule::~ScriptModule() { - for (const auto &pair : mRegisteredActions) - ActionManager::unregisterAction(pair.second.get(), pair.first); + for (const auto &[id, action] : mRegisteredActions) + ActionManager::unregisterAction(action.get(), id); ActionManager::clearMenuExtensions(); diff --git a/src/tiled/stylehelper.cpp b/src/tiled/stylehelper.cpp index ea44724c64..43e4489754 100644 --- a/src/tiled/stylehelper.cpp +++ b/src/tiled/stylehelper.cpp @@ -29,8 +29,6 @@ #include #include -#include - namespace Tiled { StyleHelper *StyleHelper::mInstance; @@ -163,8 +161,6 @@ void StyleHelper::apply() style->setPalette(desiredPalette); } - QtBoolPropertyManager::resetIcons(); - emit styleApplied(); } diff --git a/src/tiled/textpropertyedit.cpp b/src/tiled/textpropertyedit.cpp index 147852cc22..85c131ebab 100644 --- a/src/tiled/textpropertyedit.cpp +++ b/src/tiled/textpropertyedit.cpp @@ -117,7 +117,7 @@ TextPropertyEdit::TextPropertyEdit(QWidget *parent) setFocusProxy(mLineEdit); QToolButton *button = new QToolButton(this); - button->setText(QStringLiteral("...")); + button->setText(QStringLiteral("…")); button->setAutoRaise(true); // Set a validator that replaces newline characters by literal "\\n". diff --git a/src/tiled/textpropertyedit.h b/src/tiled/textpropertyedit.h index 085a096ae7..a509ab38fc 100644 --- a/src/tiled/textpropertyedit.h +++ b/src/tiled/textpropertyedit.h @@ -38,12 +38,15 @@ QString escapeNewlines(const QString &string); class TextPropertyEdit : public QWidget { Q_OBJECT + Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged FINAL) public: explicit TextPropertyEdit(QWidget *parent = nullptr); QString text() const; + QLineEdit *lineEdit() const { return mLineEdit; } + public slots: void setText(const QString &text); diff --git a/src/tiled/tilesetdocument.cpp b/src/tiled/tilesetdocument.cpp index f378489189..5f74d7bd77 100644 --- a/src/tiled/tilesetdocument.cpp +++ b/src/tiled/tilesetdocument.cpp @@ -371,6 +371,9 @@ void TilesetDocument::setSelectedTiles(const QList &selectedTiles) { mSelectedTiles = selectedTiles; emit selectedTilesChanged(); + + if (currentObject() && currentObject()->typeId() == Object::TileType) + emit currentObjectsChanged(); } QList TilesetDocument::currentObjects() const diff --git a/src/tiled/tilesetparametersedit.cpp b/src/tiled/tilesetparametersedit.cpp index a5138da7d0..82700fb74b 100644 --- a/src/tiled/tilesetparametersedit.cpp +++ b/src/tiled/tilesetparametersedit.cpp @@ -44,7 +44,7 @@ TilesetParametersEdit::TilesetParametersEdit(QWidget *parent) QToolButton *button = new QToolButton(this); button->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred)); - button->setText(tr("Edit...")); + button->setText(tr("Edit Tileset")); layout->addWidget(mLabel); layout->addWidget(button); diff --git a/src/tiled/tilesetview.cpp b/src/tiled/tilesetview.cpp index 9693a45d6a..ac15fce3c2 100644 --- a/src/tiled/tilesetview.cpp +++ b/src/tiled/tilesetview.cpp @@ -831,7 +831,7 @@ void TilesetView::onChange(const ChangeEvent &change) case ChangeEvent::WangSetChanged: { auto &wangSetChange = static_cast(change); if (mEditWangSet && wangSetChange.wangSet == mWangSet && - (wangSetChange.properties & WangSetChangeEvent::TypeProperty)) { + (wangSetChange.property == WangSetChangeEvent::TypeProperty)) { viewport()->update(); } break; diff --git a/src/tiled/tilesetwangsetmodel.cpp b/src/tiled/tilesetwangsetmodel.cpp index 5a6d6f5a6d..76ccbf1a8a 100644 --- a/src/tiled/tilesetwangsetmodel.cpp +++ b/src/tiled/tilesetwangsetmodel.cpp @@ -22,6 +22,7 @@ #include "changeevents.h" #include "changewangsetdata.h" +#include "mapdocument.h" #include "tile.h" #include "tileset.h" #include "tilesetdocument.h" @@ -159,13 +160,14 @@ void TilesetWangSetModel::setWangSetName(WangSet *wangSet, const QString &name) Q_ASSERT(wangSet->tileset() == mTilesetDocument->tileset().data()); wangSet->setName(name); emitWangSetChange(wangSet); + emitToTilesetAndMaps(WangSetChangeEvent(wangSet, WangSetChangeEvent::NameProperty)); } void TilesetWangSetModel::setWangSetType(WangSet *wangSet, WangSet::Type type) { Q_ASSERT(wangSet->tileset() == mTilesetDocument->tileset().data()); wangSet->setType(type); - emit mTilesetDocument->changed(WangSetChangeEvent(wangSet, WangSetChangeEvent::TypeProperty)); + emitToTilesetAndMaps(WangSetChangeEvent(wangSet, WangSetChangeEvent::TypeProperty)); } void TilesetWangSetModel::setWangSetColorCount(WangSet *wangSet, int value) @@ -173,6 +175,7 @@ void TilesetWangSetModel::setWangSetColorCount(WangSet *wangSet, int value) Q_ASSERT(wangSet->tileset() == mTilesetDocument->tileset().data()); wangSet->setColorCount(value); emitWangSetChange(wangSet); + emitToTilesetAndMaps(WangSetChangeEvent(wangSet, WangSetChangeEvent::ColorCountProperty)); } void TilesetWangSetModel::setWangSetImage(WangSet *wangSet, int tileId) @@ -187,6 +190,7 @@ void TilesetWangSetModel::insertWangColor(WangSet *wangSet, const QSharedPointer Q_ASSERT(wangSet->tileset() == mTilesetDocument->tileset().data()); wangSet->insertWangColor(wangColor); emitWangSetChange(wangSet); + emitToTilesetAndMaps(WangSetChangeEvent(wangSet, WangSetChangeEvent::ColorCountProperty)); } QSharedPointer TilesetWangSetModel::takeWangColorAt(WangSet *wangSet, int color) @@ -196,6 +200,7 @@ QSharedPointer TilesetWangSetModel::takeWangColorAt(WangSet *wangSet, auto wangColor = wangSet->takeWangColorAt(color); emit wangColorRemoved(wangColor.data()); emitWangSetChange(wangSet); + emitToTilesetAndMaps(WangSetChangeEvent(wangSet, WangSetChangeEvent::ColorCountProperty)); return wangColor; } @@ -206,6 +211,17 @@ void TilesetWangSetModel::emitWangSetChange(WangSet *wangSet) emit wangSetChanged(wangSet); } +void TilesetWangSetModel::emitToTilesetAndMaps(const ChangeEvent &event) +{ + emit mTilesetDocument->changed(event); + + // todo: this doesn't work reliably because it only reaches maps that use + // the tileset, whereas the Properties view can be showing stuff from any + // tileset. + for (MapDocument *mapDocument : mTilesetDocument->mapDocuments()) + emit mapDocument->changed(event); +} + void TilesetWangSetModel::documentChanged(const ChangeEvent &event) { switch (event.type) { diff --git a/src/tiled/tilesetwangsetmodel.h b/src/tiled/tilesetwangsetmodel.h index 3a61c2acd4..6675acb3be 100644 --- a/src/tiled/tilesetwangsetmodel.h +++ b/src/tiled/tilesetwangsetmodel.h @@ -98,6 +98,7 @@ class TilesetWangSetModel : public QAbstractListModel void documentChanged(const ChangeEvent &event); void emitWangSetChange(WangSet *wangSet); + void emitToTilesetAndMaps(const ChangeEvent &event); TilesetDocument *mTilesetDocument; }; diff --git a/src/tiled/undocommands.h b/src/tiled/undocommands.h index 3af2985d35..2627662510 100644 --- a/src/tiled/undocommands.h +++ b/src/tiled/undocommands.h @@ -39,8 +39,20 @@ enum UndoCommands { Cmd_ChangeLayerParallaxFactor, Cmd_ChangeLayerTintColor, Cmd_ChangeLayerVisible, + Cmd_ChangeMapBackgroundColor, + Cmd_ChangeMapChunkSize, + Cmd_ChangeMapCompressionLevel, + Cmd_ChangeMapHexSideLength, + Cmd_ChangeMapInfinite, + Cmd_ChangeMapLayerDataFormat, Cmd_ChangeMapObject, Cmd_ChangeMapObjectTransform, + Cmd_ChangeMapOrientation, + Cmd_ChangeMapParallaxOrigin, + Cmd_ChangeMapRenderOrder, + Cmd_ChangeMapStaggerAxis, + Cmd_ChangeMapStaggerIndex, + Cmd_ChangeMapTileSize, Cmd_ChangeSelectedArea, Cmd_ChangeTileImageRect, Cmd_ChangeTileProbability, diff --git a/src/tiled/utils.cpp b/src/tiled/utils.cpp index be6ae66ad6..a33c256869 100644 --- a/src/tiled/utils.cpp +++ b/src/tiled/utils.cpp @@ -41,6 +41,8 @@ #include #include #include +#include +#include #include #include #include @@ -310,6 +312,9 @@ QIcon themeIcon(const QString &name) QIcon colorIcon(const QColor &color, QSize size) { + if (!color.isValid()) + return QIcon(); + QPixmap pixmap(size); pixmap.fill(color); @@ -607,5 +612,20 @@ QString Error::jsonParseError(QJsonParseError error) } +/** + * Recursively deletes all items and their widgets from the given layout. + */ +void deleteAllFromLayout(QLayout *layout) +{ + while (QLayoutItem *item = layout->takeAt(0)) { + delete item->widget(); + + if (QLayout *layout = item->layout()) + deleteAllFromLayout(layout); + + delete item; + } +} + } // namespace Utils } // namespace Tiled diff --git a/src/tiled/utils.h b/src/tiled/utils.h index 3e73500b3a..e7c9721015 100644 --- a/src/tiled/utils.h +++ b/src/tiled/utils.h @@ -33,6 +33,7 @@ class QAction; class QKeyEvent; +class QLayout; class QMenu; namespace Tiled { @@ -111,5 +112,7 @@ namespace Error { QString jsonParseError(QJsonParseError error); } // namespace Error +void deleteAllFromLayout(QLayout *layout); + } // namespace Utils } // namespace Tiled diff --git a/src/tiled/varianteditorfactory.cpp b/src/tiled/varianteditorfactory.cpp deleted file mode 100644 index e63040dedb..0000000000 --- a/src/tiled/varianteditorfactory.cpp +++ /dev/null @@ -1,378 +0,0 @@ -/* - * varianteditorfactory.cpp - * Copyright (C) 2006 Trolltech ASA. All rights reserved. (GPLv2) - * Copyright 2013-2021, Thorbjørn Lindeijer - * - * This file is part of Tiled. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#include "varianteditorfactory.h" - -#include "fileedit.h" -#include "objectrefedit.h" -#include "textpropertyedit.h" -#include "tilesetdocument.h" -#include "tilesetparametersedit.h" -#include "utils.h" -#include "variantpropertymanager.h" - -#include -#include -#include - -namespace Tiled { - -class ResetWidget : public QWidget -{ - Q_OBJECT - -public: - ResetWidget(QtProperty *property, QWidget *editor, QWidget *parent = nullptr); - -signals: - void resetProperty(QtProperty *property); - -private: - void buttonClicked(); - - QtProperty *mProperty; -}; - -ResetWidget::ResetWidget(QtProperty *property, QWidget *editor, QWidget *parent) - : QWidget(parent) - , mProperty(property) -{ - auto layout = new QHBoxLayout(this); - - auto resetButton = new QToolButton(this); - resetButton->setIcon(QIcon(QLatin1String(":/images/16/edit-clear.png"))); - resetButton->setIconSize(Utils::smallIconSize()); - resetButton->setAutoRaise(true); - resetButton->setToolTip(tr("Reset")); - Utils::setThemeIcon(resetButton, "edit-clear"); - - layout->setContentsMargins(0, 0, 0, 0); - layout->setSpacing(0); - layout->addWidget(editor); - layout->addWidget(resetButton); - - setFocusProxy(editor); - - connect(resetButton, &QToolButton::clicked, this, &ResetWidget::buttonClicked); -} - -void ResetWidget::buttonClicked() -{ - emit resetProperty(mProperty); -} - - -VariantEditorFactory::~VariantEditorFactory() -{ - // Using QMap::keys here is important because the maps get modified in - // slotEditorDestroyed. - qDeleteAll(mFileEditToProperty.keys()); - qDeleteAll(mTilesetEditToProperty.keys()); - qDeleteAll(mTextPropertyEditToProperty.keys()); - qDeleteAll(mObjectRefEditToProperty.keys()); - qDeleteAll(mComboBoxToProperty.keys()); -} - -void VariantEditorFactory::connectPropertyManager(QtVariantPropertyManager *manager) -{ - connect(manager, &QtVariantPropertyManager::valueChanged, - this, &VariantEditorFactory::slotPropertyChanged); - connect(manager, &QtVariantPropertyManager::attributeChanged, - this, &VariantEditorFactory::slotPropertyAttributeChanged); - QtVariantEditorFactory::connectPropertyManager(manager); -} - -QWidget *VariantEditorFactory::createEditor(QtVariantPropertyManager *manager, - QtProperty *property, - QWidget *parent) -{ - const int type = manager->propertyType(property); - QWidget *editor = nullptr; - - if (type == filePathTypeId()) { - auto fileEdit = new FileEdit(parent); - FilePath filePath = manager->value(property).value(); - fileEdit->setFileUrl(filePath.url); - fileEdit->setFilter(manager->attributeValue(property, QLatin1String("filter")).toString()); - fileEdit->setIsDirectory(manager->attributeValue(property, QLatin1String("directory")).toBool()); - mCreatedFileEdits[property].append(fileEdit); - mFileEditToProperty[fileEdit] = property; - - connect(fileEdit, &FileEdit::fileUrlChanged, - this, &VariantEditorFactory::fileEditFileUrlChanged); - connect(fileEdit, &QObject::destroyed, - this, &VariantEditorFactory::slotEditorDestroyed); - - editor = fileEdit; - } else if (type == VariantPropertyManager::displayObjectRefTypeId()) { - auto objectRefEdit = new ObjectRefEdit(parent); - auto objectRef = manager->value(property).value(); - objectRefEdit->setValue(objectRef); - mCreatedObjectRefEdits[property].append(objectRefEdit); - mObjectRefEditToProperty[objectRefEdit] = property; - - connect(objectRefEdit, &ObjectRefEdit::valueChanged, - this, &VariantEditorFactory::objectRefEditValueChanged); - connect(objectRefEdit, &QObject::destroyed, - this, &VariantEditorFactory::slotEditorDestroyed); - - editor = objectRefEdit; - } else if (type == VariantPropertyManager::tilesetParametersTypeId()) { - auto tilesetEdit = new TilesetParametersEdit(parent); - tilesetEdit->setTilesetDocument(manager->value(property).value()); - mCreatedTilesetEdits[property].append(tilesetEdit); - mTilesetEditToProperty[tilesetEdit] = property; - - connect(tilesetEdit, &QObject::destroyed, - this, &VariantEditorFactory::slotEditorDestroyed); - - editor = tilesetEdit; - } else if (type == QMetaType::QString) { - bool multiline = manager->attributeValue(property, QLatin1String("multiline")).toBool(); - QStringList suggestions = manager->attributeValue(property, QLatin1String("suggestions")).toStringList(); - - if (multiline) { - auto textEdit = new TextPropertyEdit(parent); - textEdit->setText(manager->value(property).toString()); - mCreatedTextPropertyEdits[property].append(textEdit); - mTextPropertyEditToProperty[textEdit] = property; - - connect(textEdit, &TextPropertyEdit::textChanged, - this, &VariantEditorFactory::textPropertyEditTextChanged); - connect(textEdit, &QObject::destroyed, - this, &VariantEditorFactory::slotEditorDestroyed); - - editor = textEdit; - } else if (!suggestions.isEmpty()) { - auto comboBox = new QComboBox(parent); - comboBox->setEditable(true); - comboBox->addItems(suggestions); - comboBox->setCurrentText(manager->value(property).toString()); - mCreatedComboBoxes[property].append(comboBox); - mComboBoxToProperty[comboBox] = property; - - connect(comboBox, &QComboBox::currentTextChanged, - this, &VariantEditorFactory::comboBoxPropertyEditTextChanged); - connect(comboBox, &QObject::destroyed, - this, &VariantEditorFactory::slotEditorDestroyed); - - editor = comboBox; - } - } - - if (!editor) - editor = QtVariantEditorFactory::createEditor(manager, property, parent); - - if (type == QMetaType::QColor || type == VariantPropertyManager::displayObjectRefTypeId() || property->isModified()) { - // Allow resetting color and object reference properties, or allow - // unsetting a class member (todo: resolve conflict...). - auto resetWidget = new ResetWidget(property, editor, parent); - connect(resetWidget, &ResetWidget::resetProperty, - this, &VariantEditorFactory::resetProperty); - editor = resetWidget; - } - - return editor; -} - -void VariantEditorFactory::disconnectPropertyManager(QtVariantPropertyManager *manager) -{ - disconnect(manager, &QtVariantPropertyManager::valueChanged, - this, &VariantEditorFactory::slotPropertyChanged); - disconnect(manager, &QtVariantPropertyManager::attributeChanged, - this, &VariantEditorFactory::slotPropertyAttributeChanged); - QtVariantEditorFactory::disconnectPropertyManager(manager); -} - -void VariantEditorFactory::slotPropertyChanged(QtProperty *property, - const QVariant &value) -{ - if (mCreatedFileEdits.contains(property)) { - for (FileEdit *edit : std::as_const(mCreatedFileEdits)[property]) { - FilePath filePath = value.value(); - edit->setFileUrl(filePath.url); - } - } - else if (mCreatedTilesetEdits.contains(property)) { - for (TilesetParametersEdit *edit : std::as_const(mCreatedTilesetEdits)[property]) - edit->setTilesetDocument(value.value()); - } - else if (mCreatedTextPropertyEdits.contains(property)) { - for (TextPropertyEdit *edit : std::as_const(mCreatedTextPropertyEdits)[property]) - edit->setText(value.toString()); - } - else if (mCreatedComboBoxes.contains(property)) { - for (QComboBox *comboBox : std::as_const(mCreatedComboBoxes)[property]) - comboBox->setCurrentText(value.toString()); - } - else if (mCreatedObjectRefEdits.contains(property)) { - for (ObjectRefEdit *objectRefEdit : std::as_const(mCreatedObjectRefEdits)[property]) - objectRefEdit->setValue(value.value()); - } -} - -void VariantEditorFactory::slotPropertyAttributeChanged(QtProperty *property, - const QString &attribute, - const QVariant &value) -{ - if (mCreatedFileEdits.contains(property)) { - if (attribute == QLatin1String("filter")) { - for (FileEdit *edit : std::as_const(mCreatedFileEdits)[property]) - edit->setFilter(value.toString()); - } else if (attribute == QLatin1String("directory")) { - for (FileEdit *edit : std::as_const(mCreatedFileEdits)[property]) - edit->setIsDirectory(value.toBool()); - } - } - else if (mCreatedComboBoxes.contains(property)) { - if (attribute == QLatin1String("suggestions")) { - for (QComboBox *comboBox: std::as_const(mCreatedComboBoxes)[property]) { - comboBox->clear(); - comboBox->addItems(value.toStringList()); - } - } - } - // changing of "multiline" attribute currently not supported -} - -void VariantEditorFactory::fileEditFileUrlChanged(const QUrl &value) -{ - auto fileEdit = qobject_cast(sender()); - Q_ASSERT(fileEdit); - - if (QtProperty *property = mFileEditToProperty.value(fileEdit)) { - QtVariantPropertyManager *manager = propertyManager(property); - if (!manager) - return; - manager->setValue(property, QVariant::fromValue(FilePath { value })); - } -} - -void VariantEditorFactory::textPropertyEditTextChanged(const QString &value) -{ - auto textPropertyEdit = qobject_cast(sender()); - Q_ASSERT(textPropertyEdit); - - if (QtProperty *property = mTextPropertyEditToProperty.value(textPropertyEdit)) { - QtVariantPropertyManager *manager = propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - } -} - -void VariantEditorFactory::comboBoxPropertyEditTextChanged(const QString &value) -{ - auto comboBox = qobject_cast(sender()); - Q_ASSERT(comboBox); - - if (QtProperty *property = mComboBoxToProperty.value(comboBox)) { - QtVariantPropertyManager *manager = propertyManager(property); - if (!manager) - return; - manager->setValue(property, value); - } -} - -void VariantEditorFactory::objectRefEditValueChanged(const DisplayObjectRef &value) -{ - auto objectRefEdit = qobject_cast(sender()); - Q_ASSERT(objectRefEdit); - if (QtProperty *property = mObjectRefEditToProperty.value(objectRefEdit)) { - QtVariantPropertyManager *manager = propertyManager(property); - if (!manager) - return; - manager->setValue(property, QVariant::fromValue(value)); - } -} - -void VariantEditorFactory::slotEditorDestroyed(QObject *object) -{ - // Check if it was an ObjectRefEdit - { - auto objectRefEdit = static_cast(object); - - if (QtProperty *property = mObjectRefEditToProperty.value(objectRefEdit)) { - mObjectRefEditToProperty.remove(objectRefEdit); - mCreatedObjectRefEdits[property].removeAll(objectRefEdit); - if (mCreatedObjectRefEdits[property].isEmpty()) - mCreatedObjectRefEdits.remove(property); - return; - } - } - - // Check if it was a FileEdit - { - auto fileEdit = static_cast(object); - - if (QtProperty *property = mFileEditToProperty.value(fileEdit)) { - mFileEditToProperty.remove(fileEdit); - mCreatedFileEdits[property].removeAll(fileEdit); - if (mCreatedFileEdits[property].isEmpty()) - mCreatedFileEdits.remove(property); - return; - } - } - - // Check if it was a TilesetParametersEdit - { - auto tilesetEdit = static_cast(object); - - if (QtProperty *property = mTilesetEditToProperty.value(tilesetEdit)) { - mTilesetEditToProperty.remove(tilesetEdit); - mCreatedTilesetEdits[property].removeAll(tilesetEdit); - if (mCreatedTilesetEdits[property].isEmpty()) - mCreatedTilesetEdits.remove(property); - return; - } - } - - // Check if it was a TextPropertyEdit - { - auto textPropertyEdit = static_cast(object); - - if (QtProperty *property = mTextPropertyEditToProperty.value(textPropertyEdit)) { - mTextPropertyEditToProperty.remove(textPropertyEdit); - mCreatedTextPropertyEdits[property].removeAll(textPropertyEdit); - if (mCreatedTextPropertyEdits[property].isEmpty()) - mCreatedTextPropertyEdits.remove(property); - return; - } - } - - // Check if it was a QComboBox - { - auto comboBox = static_cast(object); - - if (QtProperty *property = mComboBoxToProperty.value(comboBox)) { - mComboBoxToProperty.remove(comboBox); - mCreatedComboBoxes[property].removeAll(comboBox); - if (mCreatedComboBoxes[property].isEmpty()) - mCreatedComboBoxes.remove(property); - return; - } - } -} - -} // namespace Tiled - -#include "varianteditorfactory.moc" -#include "moc_varianteditorfactory.cpp" diff --git a/src/tiled/varianteditorfactory.h b/src/tiled/varianteditorfactory.h deleted file mode 100644 index 630a83f013..0000000000 --- a/src/tiled/varianteditorfactory.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * varianteditorfactory.h - * Copyright (C) 2006 Trolltech ASA. All rights reserved. (GPLv2) - * Copyright 2013-2021, Thorbjørn Lindeijer - * - * This file is part of Tiled. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#pragma once - -#include - -class QComboBox; - -namespace Tiled { - -class DisplayObjectRef; -class FileEdit; -class ObjectRefEdit; -class TextPropertyEdit; -class TilesetParametersEdit; - -/** - * Extension of the QtVariantEditorFactory that adds support for: - * - * - An editor for editing file references - * - An editor with a button for changing tileset parameters - * - An editor for editing references to objects - * - "suggestions" and "multiline" attributes for string values. - */ -class VariantEditorFactory : public QtVariantEditorFactory -{ - Q_OBJECT - -public: - explicit VariantEditorFactory(QObject *parent = nullptr) - : QtVariantEditorFactory(parent) - {} - - ~VariantEditorFactory() override; - -signals: - void resetProperty(QtProperty *property); - -protected: - void connectPropertyManager(QtVariantPropertyManager *manager) override; - QWidget *createEditor(QtVariantPropertyManager *manager, - QtProperty *property, - QWidget *parent) override; - void disconnectPropertyManager(QtVariantPropertyManager *manager) override; - -private: - void slotPropertyChanged(QtProperty *property, const QVariant &value); - void slotPropertyAttributeChanged(QtProperty *property, - const QString &attribute, - const QVariant &value); - void fileEditFileUrlChanged(const QUrl &value); - void textPropertyEditTextChanged(const QString &value); - void comboBoxPropertyEditTextChanged(const QString &value); - void objectRefEditValueChanged(const DisplayObjectRef &value); - void slotEditorDestroyed(QObject *object); - - QMap > mCreatedFileEdits; - QMap mFileEditToProperty; - - QMap > mCreatedTilesetEdits; - QMap mTilesetEditToProperty; - - QMap > mCreatedTextPropertyEdits; - QMap mTextPropertyEditToProperty; - - QMap > mCreatedComboBoxes; - QMap mComboBoxToProperty; - - QMap > mCreatedObjectRefEdits; - QMap mObjectRefEditToProperty; -}; - -} // namespace Tiled diff --git a/src/tiled/variantmapproperty.cpp b/src/tiled/variantmapproperty.cpp new file mode 100644 index 0000000000..99b1acf215 --- /dev/null +++ b/src/tiled/variantmapproperty.cpp @@ -0,0 +1,574 @@ +/* + * variantmapproperty.cpp + * Copyright 2024, Thorbjørn Lindeijer + * + * This file is part of Tiled. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "variantmapproperty.h" + +#include "mapdocument.h" +#include "objectrefedit.h" +#include "preferences.h" +#include "propertyeditorwidgets.h" +#include "propertytypesmodel.h" +#include "session.h" +#include "utils.h" + +#include +#include +#include +#include +#include + +namespace Tiled { + +namespace session { +static SessionOption propertyType { "property.type", QStringLiteral("string") }; +} // namespace session + + +class ObjectRefProperty : public PropertyTemplate +{ + Q_OBJECT + +public: + using PropertyTemplate::PropertyTemplate; + + QWidget *createEditor(QWidget *parent) override + { + auto editor = new ObjectRefEdit(parent); + auto syncEditor = [this, editor] { + const QSignalBlocker blocker(editor); + editor->setValue(value()); + }; + syncEditor(); + connect(this, &Property::valueChanged, editor, syncEditor); + connect(editor, &ObjectRefEdit::valueChanged, + this, [this](const DisplayObjectRef &value) { + setValue(value); + }); + return editor; + } + + void addContextMenuActions(QMenu *menu) override + { + auto objectRef = value(); + menu->addAction(QCoreApplication::translate("Tiled::PropertiesDock", "Go to Object"), [=] { + if (auto object = objectRef.object()) { + objectRef.mapDocument->setSelectedObjects({object}); + emit objectRef.mapDocument->focusMapObjectRequested(object); + } + })->setEnabled(objectRef.object()); + } +}; + + +VariantMapProperty::VariantMapProperty(const QString &name, QObject *parent) + : GroupProperty(name, parent) +{ + connect(Preferences::instance(), &Preferences::propertyTypesChanged, + this, &VariantMapProperty::propertyTypesChanged); +} + +void VariantMapProperty::setValue(const QVariantMap &value, + const QVariantMap &suggestions) +{ + QVariantMap oldProperties = mSuggestions; + mergeProperties(oldProperties, mValue); + + mValue = value; + mSuggestions = suggestions; + + QVariantMap newProperties = suggestions; + mergeProperties(newProperties, value); + + // First, delete all properties that are not in allProperties + for (auto it = mPropertyMap.begin(); it != mPropertyMap.end(); ) { + if (newProperties.contains(it.key())) { + ++it; + } else { + deleteProperty(it.value()); + it = mPropertyMap.erase(it); + } + } + + int index = 0; + + QMapIterator it(newProperties); + while (it.hasNext()) { + it.next(); + const QString &name = it.key(); + const auto &newValue = it.value(); + const auto oldValue = oldProperties.value(name); + + if (createOrUpdateProperty(index, name, oldValue, newValue)) + ++index; + } + + // Don't emit valueChanged when we're just recreating properties with custom types + if (mPropertyTypesChanged) + return; + + QScopedValueRollback emittingValueChanged(mEmittingValueChanged, true); + emit valueChanged(); +} + +static bool canReuseProperty(const QVariant &a, + const QVariant &b, + bool propertyTypesChanged) +{ + if (a.userType() != b.userType()) + return false; + + // Two PropertyValue values might still have different types + if (a.userType() == propertyValueId()) { + // Trigger re-creation of the property when the types have changed + if (propertyTypesChanged) + return false; + + auto aTypeId = a.value().typeId; + auto bTypeId = b.value().typeId; + if (aTypeId != bTypeId) + return false; + } + + return true; +} + +bool VariantMapProperty::createOrUpdateProperty(int index, + const QString &name, + const QVariant &oldValue, + const QVariant &newValue) +{ + auto property = mPropertyMap.value(name); + + // If it already exists, check whether we need to delete it + if (property && !canReuseProperty(oldValue, newValue, mPropertyTypesChanged)) { + deleteProperty(property); + mPropertyMap.remove(name); + property = nullptr; + } + + // Try to create the property if necessary + if (!property) { + auto get = [=] { + return mValue.value(name, mSuggestions.value(name)); + }; + auto set = [=] (const QVariant &value) { + mValue.insert(name, value); + emitMemberValueChanged({ name }, value); + }; + + property = createProperty({ name }, std::move(get), std::move(set)); + if (property) { + connect(property, &Property::removeRequested, this, [=] { + removeMember(name); + }); + + connect(property, &Property::addRequested, this, [=] { + addMember(name, mSuggestions.value(name)); + }); + + insertProperty(index, property); + mPropertyMap.insert(name, property); + } else { + qWarning() << "Failed to create property for" << name + << "with type" << newValue.typeName(); + } + } + + if (property) { + if (mValue.contains(name)) { + property->setEnabled(true); + property->setActions(Property::Action::Select | Property::Action::Remove); + } else { + property->setEnabled(false); + property->setActions(Property::Action::Select | Property::Action::Add); + } + + updateModifiedRecursively(property, newValue); + emitValueChangedRecursively(property); + } + + return true; +} + +Property *VariantMapProperty::createProperty(const QStringList &path, + std::function get, + std::function set) +{ + Property *property = nullptr; + + const auto value = get(); + const auto type = value.userType(); + const auto &name = path.last(); + QString typeName; + + if (type == filePathTypeId()) { + auto getUrl = [get = std::move(get)] { return get().value().url; }; + auto setUrl = [set = std::move(set)] (const QUrl &value) { + set(QVariant::fromValue(FilePath { value })); + }; + property = new UrlProperty(name, std::move(getUrl), std::move(setUrl)); + } else if (type == objectRefTypeId()) { + auto getObjectRef = [get = std::move(get), this] { + return DisplayObjectRef(get().value(), + static_cast(mDocument)); // todo: shouldn't it be qobject_cast? + }; + auto setObjectRef = [set = std::move(set)](const DisplayObjectRef &value) { + set(QVariant::fromValue(value.ref)); + }; + property = new ObjectRefProperty(name, std::move(getObjectRef), std::move(setObjectRef)); + } else if (type == propertyValueId()) { + const auto propertyValue = value.value(); + if (auto propertyType = propertyValue.type()) { + switch (propertyType->type) { + case PropertyType::PT_Invalid: + break; + case PropertyType::PT_Class: { + auto classType = static_cast(*propertyType); + + auto groupProperty = new GroupProperty(name); + groupProperty->setHeader(false); + + createClassMembers(path, groupProperty, classType, std::move(get)); + + groupProperty->setExpanded(mExpandedProperties.contains(path)); + + connect(groupProperty, &GroupProperty::expandedChanged, this, [=](bool expanded) { + if (expanded) + mExpandedProperties.insert(path); + else + mExpandedProperties.remove(path); + }); + + property = groupProperty; + break; + } + case PropertyType::PT_Enum: { + auto enumProperty = new BaseEnumProperty( + name, + [get = std::move(get)] { return get().value().value.toInt(); }, + [set = std::move(set), propertyType](int value) { + set(propertyType->wrap(value)); + }); + + auto enumType = static_cast(*propertyType); + enumProperty->setEnumData(enumType.values); + enumProperty->setFlags(enumType.valuesAsFlags); + + property = enumProperty; + break; + } + } + + typeName = propertyType->name; + } else { + typeName = tr("Unknown type"); + } + } else { + property = createVariantProperty(name, std::move(get), std::move(set)); + } + + if (property) { + if (typeName.isEmpty()) + typeName = typeToName(type); + + property->setToolTip(QStringLiteral("%1 : %2") + .arg(property->name(), typeName)); + } + + return property; +} + +void VariantMapProperty::createClassMembers(const QStringList &path, + GroupProperty *groupProperty, + const ClassPropertyType &classType, + std::function get) +{ + // Create a sub-property for each member + QMapIterator it(classType.members); + while (it.hasNext()) { + it.next(); + const QString &name = it.key(); + + auto childPath = path; + childPath.append(name); + + auto getMember = [=] { + auto def = classType.members.value(name); + return get().value().value.toMap().value(name, def); + }; + auto setMember = [=] (const QVariant &value) { + setClassMember(childPath, value); + }; + + if (auto childProperty = createProperty(childPath, std::move(getMember), setMember)) { + childProperty->setActions(Property::Action::Reset); + groupProperty->addProperty(childProperty); + + connect(childProperty, &Property::resetRequested, this, [=] { + setMember(QVariant()); + emitValueChangedRecursively(childProperty); + }); + } + } +} + +void VariantMapProperty::removeMember(const QString &name) +{ + if (!mValue.contains(name)) + return; + + const auto oldValue = mValue.take(name); + + if (!mSuggestions.contains(name)) { + if (auto property = mPropertyMap.take(name)) + deleteProperty(property); + } else if (auto property = mPropertyMap.value(name)) { + const auto newValue = mSuggestions.value(name); + const int index = indexOfProperty(property); + createOrUpdateProperty(index, name, oldValue, newValue); + } + + emitMemberValueChanged({ name }, QVariant()); +} + +void VariantMapProperty::addMember(const QString &name, const QVariant &value) +{ + int index = 0; + + if (auto property = mPropertyMap.value(name)) { + index = indexOfProperty(property); + } else for (auto it = mValue.keyBegin(); it != mValue.keyEnd(); ++it) { + if (*it < name) + ++index; + else + break; + } + + const auto oldValue = mValue.value(name, mSuggestions.value(name)); + mValue.insert(name, value); + createOrUpdateProperty(index, name, oldValue, value); + + emitMemberValueChanged({ name }, value); +} + +void VariantMapProperty::setClassMember(const QStringList &path, const QVariant &value) +{ + if (!setPropertyMemberValue(mValue, path, value)) + return; + + const auto &topLevelName = path.first(); + updateModifiedRecursively(mPropertyMap.value(topLevelName), + mValue.value(topLevelName)); + + emitMemberValueChanged(path, value); +} + +void VariantMapProperty::updateModifiedRecursively(Property *property, + const QVariant &value) +{ + auto groupProperty = qobject_cast(property); + if (!groupProperty) + return; + + const QVariantMap classValue = value.value().value.toMap(); + + for (auto subProperty : groupProperty->subProperties()) { + const auto &name = subProperty->name(); + const bool isModified = classValue.contains(name); + + if (subProperty->isModified() != isModified || subProperty->isModified()) { + subProperty->setModified(isModified); + updateModifiedRecursively(subProperty, classValue.value(name)); + } + } +} + +void VariantMapProperty::emitValueChangedRecursively(Property *property) +{ + emit property->valueChanged(); + + if (auto groupProperty = qobject_cast(property)) + for (auto subProperty : groupProperty->subProperties()) + emitValueChangedRecursively(subProperty); +} + +void VariantMapProperty::propertyTypesChanged() +{ + // When this happens in response to emitting value changed, it means we + // have triggered a change in a class definition. In this case we should + // not update ourselves. + if (mEmittingValueChanged) + return; + + QScopedValueRollback propertyTypesChanged(mPropertyTypesChanged, true); + setValue(mValue, mSuggestions); +} + +void VariantMapProperty::emitMemberValueChanged(const QStringList &path, const QVariant &value) +{ + QScopedValueRollback emittingValueChanged(mEmittingValueChanged, true); + emit memberValueChanged(path, value); + emit valueChanged(); +} + + +AddValueProperty::AddValueProperty(QObject *parent) + : Property(QString(), parent) + , m_plainTypeIcon(QStringLiteral("://images/scalable/property-type-plain.svg")) + , m_placeholderText(tr("Property name")) +{ + setActions(Action::AddDisabled); +} + +void AddValueProperty::setPlaceholderText(const QString &text) +{ + if (m_placeholderText == text) + return; + + m_placeholderText = text; + emit placeholderTextChanged(text); +} + +QWidget *AddValueProperty::createLabel(int level, QWidget *parent) +{ + constexpr int QLineEditPrivate_horizontalMargin = 2; + const int spacing = Utils::dpiScaled(3); + const int branchIndicatorWidth = Utils::dpiScaled(14); + const int indent = branchIndicatorWidth * (level + 1); + + auto nameEdit = new LineEdit(parent); + nameEdit->setText(name()); + nameEdit->setPlaceholderText(m_placeholderText); + + QStyleOptionFrame option; + option.initFrom(nameEdit); + const int frameWidth = nameEdit->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &option, nameEdit); + const int nativeMargin = QLineEditPrivate_horizontalMargin + frameWidth; + + QMargins margins; + + if (parent->isLeftToRight()) + margins = QMargins(spacing + indent - nativeMargin, 0, spacing - nativeMargin, 0); + else + margins = QMargins(spacing - nativeMargin, 0, spacing + indent - nativeMargin, 0); + + nameEdit->setContentsMargins(margins); + + connect(nameEdit, &QLineEdit::textChanged, this, &Property::setName); + connect(nameEdit, &QLineEdit::returnPressed, this, [this] { + if (!name().isEmpty()) + emit addRequested(); + }); + connect(this, &Property::nameChanged, this, [=](const QString &name) { + setActions(name.isEmpty() ? Action::AddDisabled : Action::Add); + }); + connect(this, &AddValueProperty::placeholderTextChanged, + nameEdit, &QLineEdit::setPlaceholderText); + + nameEdit->installEventFilter(this); + + connect(qApp, &QApplication::focusChanged, this, [=](QWidget *, QWidget *focusWidget) { + // Ignore focus in different windows (popups, dialogs, etc.) + if (!focusWidget || focusWidget->window() != parent->window()) + return; + + // Request removal if focus moved elsewhere + if (!parent->isAncestorOf(focusWidget)) + emit removeRequested(); + }); + + return nameEdit; +} + +QWidget *AddValueProperty::createEditor(QWidget *parent) +{ + // Create combo box with property types + auto typeBox = new ComboBox(parent); + + // Add possible types from QVariant + typeBox->addItem(m_plainTypeIcon, typeToName(QMetaType::Bool), false); + typeBox->addItem(m_plainTypeIcon, typeToName(QMetaType::QColor), QColor()); + typeBox->addItem(m_plainTypeIcon, typeToName(QMetaType::Double), 0.0); + typeBox->addItem(m_plainTypeIcon, typeToName(filePathTypeId()), QVariant::fromValue(FilePath())); + typeBox->addItem(m_plainTypeIcon, typeToName(QMetaType::Int), 0); + typeBox->addItem(m_plainTypeIcon, typeToName(objectRefTypeId()), QVariant::fromValue(ObjectRef())); + typeBox->addItem(m_plainTypeIcon, typeToName(QMetaType::QString), QString()); + + for (const auto propertyType : Object::propertyTypes()) { + // Avoid suggesting the creation of circular dependencies between types + if (m_parentClassType && !m_parentClassType->canAddMemberOfType(propertyType)) + continue; + + // Avoid suggesting classes not meant to be used as property value + if (propertyType->isClass()) + if (!static_cast(propertyType)->isPropertyValueType()) + continue; + + const QVariant var = propertyType->wrap(propertyType->defaultValue()); + const QIcon icon = PropertyTypesModel::iconForPropertyType(propertyType->type); + typeBox->addItem(icon, propertyType->name, var); + } + + // Restore previously used type + typeBox->setCurrentText(session::propertyType); + if (typeBox->currentIndex() == -1) + typeBox->setCurrentIndex(typeBox->findData(QString())); + + m_value = typeBox->currentData(); + + connect(typeBox, qOverload(&QComboBox::currentIndexChanged), this, [=](int index) { + m_value = typeBox->itemData(index); + session::propertyType = typeBox->currentText(); + }); + connect(typeBox, &ComboBox::returnPressed, this, [this] { + if (!name().isEmpty()) + emit addRequested(); + }); + + typeBox->installEventFilter(this); + + return typeBox; +} + +bool AddValueProperty::eventFilter(QObject *watched, QEvent *event) +{ + switch (event->type()) { + case QEvent::KeyPress: { + // When Escape is pressed while the name edit or the type combo has + // focus, request the removal of this property. + auto keyEvent = static_cast(event); + bool isNameEdit = qobject_cast(watched); + bool isTypeCombo = qobject_cast(watched); + if ((isNameEdit || isTypeCombo) && keyEvent->key() == Qt::Key_Escape) { + emit removeRequested(); + return true; + } + break; + } + default: + break; + } + return false; +} + +} // namespace Tiled + +#include "moc_variantmapproperty.cpp" +#include "variantmapproperty.moc" diff --git a/src/tiled/variantmapproperty.h b/src/tiled/variantmapproperty.h new file mode 100644 index 0000000000..5e66c33181 --- /dev/null +++ b/src/tiled/variantmapproperty.h @@ -0,0 +1,137 @@ +/* + * variantmapproperty.h + * Copyright 2024, Thorbjørn Lindeijer + * + * This file is part of Tiled. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#pragma once + +#include "propertiesview.h" +#include "propertytype.h" + +#include + +namespace Tiled { + +class Document; + +/** + * A property that creates child properties based on a QVariantMap value. + */ +class VariantMapProperty : public GroupProperty +{ + Q_OBJECT + +public: + VariantMapProperty(const QString &name, QObject *parent = nullptr); + + void setValue(const QVariantMap &value, + const QVariantMap &suggestions = {}); + + const QVariantMap &value() const { return mValue; } + + void removeMember(const QString &name); + void addMember(const QString &name, const QVariant &value); + void setClassMember(const QStringList &path, const QVariant &value); + + Property *property(const QString &name) const; + +signals: + void memberValueChanged(const QStringList &path, const QVariant &value); + +protected: + virtual void propertyTypesChanged(); + + Document *mDocument = nullptr; + bool mPropertyTypesChanged = false; + +private: + bool createOrUpdateProperty(int index, + const QString &name, + const QVariant &oldValue, + const QVariant &newValue); + Property *createProperty(const QStringList &path, + std::function get, + std::function set); + + void createClassMembers(const QStringList &path, + GroupProperty *groupProperty, + const ClassPropertyType &classType, + std::function get); + + void updateModifiedRecursively(Property *property, const QVariant &value); + void emitValueChangedRecursively(Property *property); + + void emitMemberValueChanged(const QStringList &path, const QVariant &value); + + bool mEmittingValueChanged = false; + QVariantMap mValue; + QVariantMap mSuggestions; + QHash mPropertyMap; + QSet mExpandedProperties; +}; + +inline Property *VariantMapProperty::property(const QString &name) const +{ + return mPropertyMap.value(name); +} + + +/** + * A property that creates widgets for adding a value with a certain name and + * type. + */ +class AddValueProperty : public Property +{ + Q_OBJECT + +public: + AddValueProperty(QObject *parent = nullptr); + + void setPlaceholderText(const QString &text); + void setParentClassType(const ClassPropertyType *parentClassType); + + QVariant value() const; + + QWidget *createLabel(int level, QWidget *parent) override; + QWidget *createEditor(QWidget *parent) override; + +signals: + void placeholderTextChanged(const QString &text); + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; + +private: + QIcon m_plainTypeIcon; + QString m_placeholderText; + QVariant m_value; + bool m_hasFocus = false; + const ClassPropertyType *m_parentClassType = nullptr; +}; + +inline void AddValueProperty::setParentClassType(const ClassPropertyType *parentClassType) +{ + m_parentClassType = parentClassType; +} + +inline QVariant AddValueProperty::value() const +{ + return m_value; +} + +} // namespace Tiled diff --git a/src/tiled/variantpropertymanager.cpp b/src/tiled/variantpropertymanager.cpp deleted file mode 100644 index d54fd3c4cb..0000000000 --- a/src/tiled/variantpropertymanager.cpp +++ /dev/null @@ -1,530 +0,0 @@ -/* - * variantpropertymanager.cpp - * Copyright (C) 2006 Trolltech ASA. All rights reserved. (GPLv2) - * Copyright 2013, Thorbjørn Lindeijer - * - * This file is part of Tiled. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#include "variantpropertymanager.h" - -#include "documentmanager.h" -#include "mapdocument.h" -#include "mapobject.h" -#include "mapobjectmodel.h" -#include "objectgroup.h" -#include "textpropertyedit.h" -#include "tilesetdocument.h" - -#include - -namespace Tiled { - -class TilesetParametersPropertyType {}; - -} // namespace Tiled - -// Needs to be up here rather than at the bottom of the file to make a -// static_assert in qMetaTypeId work (as of C++11) -Q_DECLARE_METATYPE(Tiled::TilesetParametersPropertyType) - -namespace Tiled { - -MapObject *DisplayObjectRef::object() const -{ - if (!mapDocument || ref.id <= 0) - return nullptr; - return mapDocument->map()->findObjectById(ref.id); -} - - -VariantPropertyManager::VariantPropertyManager(QObject *parent) - : QtVariantPropertyManager(parent) - , mFilterAttribute(QStringLiteral("filter")) - , mDirectoryAttribute(QStringLiteral("directory")) - , mSuggestionsAttribute(QStringLiteral("suggestions")) - , mMultilineAttribute(QStringLiteral("multiline")) - , mImageMissingIcon(QStringLiteral("://images/16/image-missing.png")) -{ - mImageMissingIcon.addPixmap(QPixmap(QStringLiteral("://images/32/image-missing.png"))); - - connect(this, &QtVariantPropertyManager::valueChanged, - this, &VariantPropertyManager::slotValueChanged); - connect(this, &QtAbstractPropertyManager::propertyDestroyed, - this, &VariantPropertyManager::slotPropertyDestroyed); -} - -VariantPropertyManager::~VariantPropertyManager() -{ - // Disconnect early since these functions may be called during destruction - disconnect(this, &QtVariantPropertyManager::valueChanged, - this, &VariantPropertyManager::slotValueChanged); - disconnect(this, &QtAbstractPropertyManager::propertyDestroyed, - this, &VariantPropertyManager::slotPropertyDestroyed); -} - -QVariant VariantPropertyManager::value(const QtProperty *property) const -{ - if (mValues.contains(property)) - return mValues[property]; - if (m_alignValues.contains(property)) - return QVariant::fromValue(m_alignValues.value(property)); - return QtVariantPropertyManager::value(property); -} - -bool VariantPropertyManager::isPropertyTypeSupported(int propertyType) const -{ - if (propertyType == filePathTypeId() - || propertyType == displayObjectRefTypeId() - || propertyType == tilesetParametersTypeId() - || propertyType == alignmentTypeId() - || propertyType == unstyledGroupTypeId()) - return true; - return QtVariantPropertyManager::isPropertyTypeSupported(propertyType); -} - -int VariantPropertyManager::valueType(int propertyType) const -{ - if (propertyType == filePathTypeId()) - return propertyType; - if (propertyType == displayObjectRefTypeId()) - return propertyType; - if (propertyType == tilesetParametersTypeId()) - return qMetaTypeId(); - if (propertyType == alignmentTypeId()) - return propertyType; - if (propertyType == unstyledGroupTypeId()) - return QMetaType::QVariantMap; // allows storing any child values - return QtVariantPropertyManager::valueType(propertyType); -} - -QStringList VariantPropertyManager::attributes(int propertyType) const -{ - if (propertyType == filePathTypeId()) { - return { - mFilterAttribute, - mDirectoryAttribute - }; - } - return QtVariantPropertyManager::attributes(propertyType); -} - -int VariantPropertyManager::attributeType(int propertyType, - const QString &attribute) const -{ - if (propertyType == filePathTypeId()) { - if (attribute == mFilterAttribute) - return QMetaType::QString; - if (attribute == mDirectoryAttribute) - return QMetaType::Bool; - return 0; - } - return QtVariantPropertyManager::attributeType(propertyType, attribute); -} - -QVariant VariantPropertyManager::attributeValue(const QtProperty *property, - const QString &attribute) const -{ - if (mFilePathAttributes.contains(property)) { - if (attribute == mFilterAttribute) - return mFilePathAttributes[property].filter; - if (attribute == mDirectoryAttribute) - return mFilePathAttributes[property].directory; - return QVariant(); - } - if (mStringAttributes.contains(property)) { - if (attribute == mSuggestionsAttribute) - return mStringAttributes[property].suggestions; - if (attribute == mMultilineAttribute) - return mStringAttributes[property].multiline; - } - - return QtVariantPropertyManager::attributeValue(property, attribute); -} - -int VariantPropertyManager::tilesetParametersTypeId() -{ - return qMetaTypeId(); -} - -int VariantPropertyManager::alignmentTypeId() -{ - return qMetaTypeId(); -} - -int VariantPropertyManager::displayObjectRefTypeId() -{ - return qMetaTypeId(); -} - -int VariantPropertyManager::unstyledGroupTypeId() -{ - return qMetaTypeId(); -} - -QString VariantPropertyManager::objectRefLabel(const MapObject &object) -{ - const QString &className = object.effectiveClassName(); - - QString label = tr("%1: ").arg(object.id()); - if (!object.name().isEmpty()) { - label.append(object.name()); - if (!className.isEmpty()) - label.append(tr(" (%1)").arg(className)); - } else if (!className.isEmpty()) - label.append(tr("(%1)").arg(className)); - else - label.append(tr("Unnamed object")); - - return label; -} - -QString VariantPropertyManager::valueText(const QtProperty *property) const -{ - if (mValues.contains(property)) { - QVariant value = mValues[property]; - int typeId = propertyType(property); - - if (typeId == displayObjectRefTypeId()) { - const auto ref = value.value(); - - if (ref.id() == 0) - return tr("Unset"); - - if (auto object = ref.object()) - return objectRefLabel(*object); - - return tr("%1: Object not found").arg(QString::number(ref.id())); - } - - if (typeId == filePathTypeId()) { - FilePath filePath = value.value(); - QString fileName = filePath.url.fileName(); - if (fileName.isEmpty()) { - QString path = filePath.url.toLocalFile(); - if (path.endsWith(QLatin1Char('/'))) - path.chop(1); - fileName = QFileInfo(path).fileName(); - } - return fileName; - } - - if (typeId == tilesetParametersTypeId()) { - if (TilesetDocument *tilesetDocument = value.value()) - return tilesetDocument->tileset()->imageSource().fileName(); - } - - return value.toString(); - } - - if (m_alignValues.contains(const_cast(property))) { - const Qt::Alignment v = m_alignValues.value(const_cast(property)); - return tr("%1, %2").arg(indexHToString(alignToIndexH(v)), - indexVToString(alignToIndexV(v))); - } - - auto stringAttributesIt = mStringAttributes.find(property); - if (stringAttributesIt != mStringAttributes.end()) { - if ((*stringAttributesIt).multiline) - return escapeNewlines(value(property).toString()); - } - - return QtVariantPropertyManager::valueText(property); -} - -QIcon VariantPropertyManager::valueIcon(const QtProperty *property) const -{ - if (mValues.contains(property)) { - const QVariant value = mValues[property]; - const int typeId = propertyType(property); - - if (typeId == displayObjectRefTypeId()) { - const DisplayObjectRef ref = value.value(); - if (auto object = ref.object()) - return ObjectIconManager::instance().iconForObject(*object); - } - - if (typeId == unstyledGroupTypeId()) - return QIcon(); - - QString filePath; - - // TODO: Needs a special icon for remote files - if (typeId == filePathTypeId()) { - const FilePath fp = value.value(); - filePath = fp.url.toLocalFile(); - } - - if (typeId == tilesetParametersTypeId()) { - if (TilesetDocument *tilesetDocument = value.value()) - filePath = tilesetDocument->tileset()->imageSource().toLocalFile(); - } - - // TODO: This assumes the file path is an image reference. It should be - // replaced with a more generic icon. - if (filePath.isEmpty() || !QFile::exists(filePath)) - return QIcon::fromTheme(QLatin1String("image-missing"), mImageMissingIcon); - else - return mIconProvider.icon(QFileInfo(filePath)); - } - - return QtVariantPropertyManager::valueIcon(property); -} - -void VariantPropertyManager::setValue(QtProperty *property, const QVariant &value) -{ - if (mValues.contains(property)) { - QVariant &storedValue = mValues[property]; - if (storedValue == value) - return; - storedValue = value; - emit propertyChanged(property); - emit valueChanged(property, value); - return; - } else if (m_alignValues.contains(property)) { - if (value.userType() != qMetaTypeId() && !value.canConvert(qMetaTypeId())) - return; - - const Qt::Alignment v = value.value(); - const Qt::Alignment val = m_alignValues.value(property); - - if (val == v) - return; - - QtVariantProperty *alignH = variantProperty(m_propertyToAlignH.value(property)); - QtVariantProperty *alignV = variantProperty(m_propertyToAlignV.value(property)); - - if (alignH) - alignH->setValue(alignToIndexH(v)); - if (alignV) - alignV->setValue(alignToIndexV(v)); - - m_alignValues[property] = v; - - emit QtVariantPropertyManager::valueChanged(property, QVariant::fromValue(v)); - emit propertyChanged(property); - - return; - } - QtVariantPropertyManager::setValue(property, value); -} - -void VariantPropertyManager::setAttribute(QtProperty *property, - const QString &attribute, - const QVariant &val) -{ - if (mFilePathAttributes.contains(property)) { - FilePathAttributes &attributes = mFilePathAttributes[property]; - if (attribute == mFilterAttribute) { - if (val.userType() != QMetaType::QString && !val.canConvert(QMetaType::QString)) - return; - QString filter = val.toString(); - if (attributes.filter == filter) - return; - attributes.filter = filter; - emit attributeChanged(property, attribute, filter); - } else if (attribute == mDirectoryAttribute) { - bool directory = val.toBool(); - if (attributes.directory == directory) - return; - attributes.directory = directory; - emit attributeChanged(property, attribute, directory); - } - return; - } - - if (mStringAttributes.contains(property)) { - StringAttributes &attributes = mStringAttributes[property]; - if (attribute == mSuggestionsAttribute) { - const QStringList suggestions = val.toStringList(); - if (attributes.suggestions == suggestions) - return; - attributes.suggestions = suggestions; - emit attributeChanged(property, attribute, val); - return; - } - if (attribute == mMultilineAttribute) { - attributes.multiline = val.toBool(); - return; - } - } - - QtVariantPropertyManager::setAttribute(property, attribute, val); -} - -void VariantPropertyManager::initializeProperty(QtProperty *property) -{ - const int type = propertyType(property); - if (type == filePathTypeId() - || type == displayObjectRefTypeId() - || type == tilesetParametersTypeId() - || type == unstyledGroupTypeId()) { // for storing hash map - mValues[property] = QVariant(); - if (type == filePathTypeId()) - mFilePathAttributes[property] = FilePathAttributes(); - } else if (type == QMetaType::QString) { - mStringAttributes[property] = StringAttributes(); - } else if (type == alignmentTypeId()) { - const Qt::Alignment align = Qt::AlignLeft | Qt::AlignVCenter; - m_alignValues[property] = align; - - QtVariantProperty *alignH = addProperty(enumTypeId(), tr("Horizontal")); - QStringList namesH; - namesH << indexHToString(0) << indexHToString(1) << indexHToString(2) << indexHToString(3); - alignH->setAttribute(QStringLiteral("enumNames"), namesH); - alignH->setValue(alignToIndexH(align)); - m_propertyToAlignH[property] = alignH; - m_alignHToProperty[alignH] = property; - property->addSubProperty(alignH); - - QtVariantProperty *alignV = addProperty(enumTypeId(), tr("Vertical")); - QStringList namesV; - namesV << indexVToString(0) << indexVToString(1) << indexVToString(2); - alignV->setAttribute(QStringLiteral("enumNames"), namesV); - alignV->setValue(alignToIndexV(align)); - m_propertyToAlignV[property] = alignV; - m_alignVToProperty[alignV] = property; - property->addSubProperty(alignV); - } - - - QtVariantPropertyManager::initializeProperty(property); -} - -void VariantPropertyManager::uninitializeProperty(QtProperty *property) -{ - mValues.remove(property); - mFilePathAttributes.remove(property); - mStringAttributes.remove(property); - m_alignValues.remove(property); - - QtProperty *alignH = m_propertyToAlignH.value(property); - if (alignH) { - delete alignH; - m_alignHToProperty.remove(alignH); - } - QtProperty *alignV = m_propertyToAlignV.value(property); - if (alignV) { - delete alignV; - m_alignVToProperty.remove(alignV); - } - - QtVariantPropertyManager::uninitializeProperty(property); -} - -void VariantPropertyManager::slotValueChanged(QtProperty *property, const QVariant &value) -{ - if (QtProperty *alignProperty = m_alignHToProperty.value(property)) { - const Qt::Alignment v = m_alignValues.value(alignProperty); - const Qt::Alignment newValue = indexHToAlign(value.toInt()) | indexVToAlign(alignToIndexV(v)); - if (v == newValue) - return; - - variantProperty(alignProperty)->setValue(QVariant::fromValue(newValue)); - } else if (QtProperty *alignProperty = m_alignVToProperty.value(property)) { - const Qt::Alignment v = m_alignValues.value(alignProperty); - const Qt::Alignment newValue = indexVToAlign(value.toInt()) | indexHToAlign(alignToIndexH(v)); - if (v == newValue) - return; - - variantProperty(alignProperty)->setValue(QVariant::fromValue(newValue)); - } -} - -void VariantPropertyManager::slotPropertyDestroyed(QtProperty *property) -{ - if (QtProperty *alignProperty = m_alignHToProperty.value(property)) { - m_propertyToAlignH.remove(alignProperty); - m_alignHToProperty.remove(property); - } else if (QtProperty *alignProperty = m_alignVToProperty.value(property)) { - m_propertyToAlignV.remove(alignProperty); - m_alignVToProperty.remove(property); - } -} - -int VariantPropertyManager::alignToIndexH(Qt::Alignment align) const -{ - if (align & Qt::AlignLeft) - return 0; - if (align & Qt::AlignHCenter) - return 1; - if (align & Qt::AlignRight) - return 2; - if (align & Qt::AlignJustify) - return 3; - return 0; -} - -int VariantPropertyManager::alignToIndexV(Qt::Alignment align) const -{ - if (align & Qt::AlignTop) - return 0; - if (align & Qt::AlignVCenter) - return 1; - if (align & Qt::AlignBottom) - return 2; - return 1; -} - -Qt::Alignment VariantPropertyManager::indexHToAlign(int idx) const -{ - switch (idx) { - case 0: return Qt::AlignLeft; - case 1: return Qt::AlignHCenter; - case 2: return Qt::AlignRight; - case 3: return Qt::AlignJustify; - default: break; - } - return Qt::AlignLeft; -} - -Qt::Alignment VariantPropertyManager::indexVToAlign(int idx) const -{ - switch (idx) { - case 0: return Qt::AlignTop; - case 1: return Qt::AlignVCenter; - case 2: return Qt::AlignBottom; - default: break; - } - return Qt::AlignVCenter; -} - -QString VariantPropertyManager::indexHToString(int idx) const -{ - switch (idx) { - case 0: return tr("Left"); - case 1: return tr("Center"); - case 2: return tr("Right"); - case 3: return tr("Justify"); - default: break; - } - return tr("Left"); -} - -QString VariantPropertyManager::indexVToString(int idx) const -{ - switch (idx) { - case 0: return tr("Top"); - case 1: return tr("Center"); - case 2: return tr("Bottom"); - default: break; - } - return tr("Center"); -} - -} // namespace Tiled - -#include "moc_variantpropertymanager.cpp" diff --git a/src/tiled/variantpropertymanager.h b/src/tiled/variantpropertymanager.h deleted file mode 100644 index 7ae5923f3e..0000000000 --- a/src/tiled/variantpropertymanager.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * variantpropertymanager.h - * Copyright (C) 2006 Trolltech ASA. All rights reserved. (GPLv2) - * Copyright 2013, Thorbjørn Lindeijer - * - * This file is part of Tiled. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#pragma once - -#include "properties.h" - -#include - -#include - -namespace Tiled { - -class MapDocument; -class MapObject; - -class DisplayObjectRef { -public: - explicit DisplayObjectRef(ObjectRef ref = ObjectRef(), - MapDocument *mapDocument = nullptr) - : ref(ref) - , mapDocument(mapDocument) - {} - - bool operator==(const DisplayObjectRef &o) const - { return ref.id == o.ref.id && mapDocument == o.mapDocument; } - - int id() const { return ref.id; } - MapObject *object() const; - - ObjectRef ref; - MapDocument *mapDocument; -}; - -class UnstyledGroup {}; - -/** - * Extension of the QtVariantPropertyManager that adds support for various - * additional types and attributes. - */ -class VariantPropertyManager : public QtVariantPropertyManager -{ - Q_OBJECT - -public: - explicit VariantPropertyManager(QObject *parent = nullptr); - ~VariantPropertyManager() override; - - QVariant value(const QtProperty *property) const override; - int valueType(int propertyType) const override; - bool isPropertyTypeSupported(int propertyType) const override; - - QStringList attributes(int propertyType) const override; - int attributeType(int propertyType, const QString &attribute) const override; - QVariant attributeValue(const QtProperty *property, - const QString &attribute) const override; - - static int tilesetParametersTypeId(); - static int alignmentTypeId(); - static int displayObjectRefTypeId(); - static int unstyledGroupTypeId(); - -public slots: - void setValue(QtProperty *property, const QVariant &val) override; - void setAttribute(QtProperty *property, - const QString &attribute, - const QVariant &value) override; - -protected: - QString valueText(const QtProperty *property) const override; - QIcon valueIcon(const QtProperty *property) const override; - void initializeProperty(QtProperty *property) override; - void uninitializeProperty(QtProperty *property) override; - -private: - void slotValueChanged(QtProperty *property, const QVariant &value); - void slotPropertyDestroyed(QtProperty *property); - - static QString objectRefLabel(const MapObject &object); - - QMap mValues; - - struct FilePathAttributes { - QString filter; - bool directory = false; - }; - QMap mFilePathAttributes; - - struct StringAttributes { - QStringList suggestions; - bool multiline = false; - }; - QMap mStringAttributes; - - int alignToIndexH(Qt::Alignment align) const; - int alignToIndexV(Qt::Alignment align) const; - Qt::Alignment indexHToAlign(int idx) const; - Qt::Alignment indexVToAlign(int idx) const; - QString indexHToString(int idx) const; - QString indexVToString(int idx) const; - QMap m_alignValues; - using PropertyToPropertyMap = QMap; - PropertyToPropertyMap m_propertyToAlignH; - PropertyToPropertyMap m_propertyToAlignV; - PropertyToPropertyMap m_alignHToProperty; - PropertyToPropertyMap m_alignVToProperty; - - const QString mFilterAttribute; - const QString mDirectoryAttribute; - const QString mSuggestionsAttribute; - const QString mMultilineAttribute; - QIcon mImageMissingIcon; - QFileIconProvider mIconProvider; -}; - -} // namespace Tiled - -Q_DECLARE_METATYPE(Tiled::DisplayObjectRef) -Q_DECLARE_METATYPE(Tiled::UnstyledGroup) diff --git a/src/tiled/wangcolormodel.cpp b/src/tiled/wangcolormodel.cpp index 28c177df27..65665cc088 100644 --- a/src/tiled/wangcolormodel.cpp +++ b/src/tiled/wangcolormodel.cpp @@ -20,7 +20,9 @@ #include "wangcolormodel.h" +#include "changeevents.h" #include "changewangcolordata.h" +#include "mapdocument.h" #include "tileset.h" #include "tilesetdocument.h" #include "wangset.h" @@ -130,24 +132,28 @@ void WangColorModel::setName(WangColor *wangColor, const QString &name) { wangColor->setName(name); emitDataChanged(wangColor); + emitToTilesetAndMaps(WangColorChangeEvent(wangColor, WangColorChangeEvent::NameProperty)); } void WangColorModel::setImage(WangColor *wangColor, int imageId) { wangColor->setImageId(imageId); emitDataChanged(wangColor); + emitToTilesetAndMaps(WangColorChangeEvent(wangColor, WangColorChangeEvent::ImageProperty)); } void WangColorModel::setColor(WangColor *wangColor, const QColor &color) { wangColor->setColor(color); emitDataChanged(wangColor); + emitToTilesetAndMaps(WangColorChangeEvent(wangColor, WangColorChangeEvent::ColorProperty)); } void WangColorModel::setProbability(WangColor *wangColor, qreal probability) { wangColor->setProbability(probability); // no data changed signal because probability not exposed by model + emitToTilesetAndMaps(WangColorChangeEvent(wangColor, WangColorChangeEvent::ProbabilityProperty)); } void WangColorModel::emitDataChanged(WangColor *wangColor) @@ -156,4 +162,15 @@ void WangColorModel::emitDataChanged(WangColor *wangColor) emit dataChanged(i, i); } +void WangColorModel::emitToTilesetAndMaps(const ChangeEvent &event) +{ + emit mTilesetDocument->changed(event); + + // todo: this doesn't work reliably because it only reaches maps that use + // the tileset, whereas the Properties view can be showing stuff from any + // tileset. + for (MapDocument *mapDocument : mTilesetDocument->mapDocuments()) + emit mapDocument->changed(event); +} + #include "moc_wangcolormodel.cpp" diff --git a/src/tiled/wangcolormodel.h b/src/tiled/wangcolormodel.h index f07de6a1bb..050f3c5fed 100644 --- a/src/tiled/wangcolormodel.h +++ b/src/tiled/wangcolormodel.h @@ -28,6 +28,7 @@ namespace Tiled { class Tileset; +class ChangeEvent; class TilesetDocument; class WangColorModel : public QAbstractListModel @@ -71,6 +72,7 @@ class WangColorModel : public QAbstractListModel private: void emitDataChanged(WangColor *wangColor); + void emitToTilesetAndMaps(const ChangeEvent &event); TilesetDocument *mTilesetDocument; WangSet *mWangSet; diff --git a/src/tiled/wangdock.cpp b/src/tiled/wangdock.cpp index 5ab91b6533..25db17baf5 100644 --- a/src/tiled/wangdock.cpp +++ b/src/tiled/wangdock.cpp @@ -484,7 +484,7 @@ void WangDock::documentChanged(const ChangeEvent &change) } break; case ChangeEvent::WangSetChanged: - if (static_cast(change).properties & WangSetChangeEvent::TypeProperty) + if (static_cast(change).property == WangSetChangeEvent::TypeProperty) mWangTemplateModel->wangSetChanged(); break; default: diff --git a/tiled.qbs b/tiled.qbs index fb54d9ba13..7787903ee5 100644 --- a/tiled.qbs +++ b/tiled.qbs @@ -29,7 +29,6 @@ Project { "src/libtiled", "src/libtiledquick", "src/plugins", - "src/qtpropertybrowser", "src/qtsingleapplication", "src/terraingenerator", "src/tiled/libtilededitor.qbs",