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/tiled/changeproperties.cpp b/src/tiled/changeproperties.cpp index 9b36a3a479..8814936668 100644 --- a/src/tiled/changeproperties.cpp +++ b/src/tiled/changeproperties.cpp @@ -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 25c1d3751e..32358d4a23 100644 --- a/src/tiled/colorbutton.cpp +++ b/src/tiled/colorbutton.cpp @@ -22,7 +22,6 @@ #include "utils.h" -#include #include #include @@ -68,7 +67,8 @@ 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); } @@ -77,7 +77,7 @@ 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("Unset")); + 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/propertieswidget.cpp b/src/tiled/propertieswidget.cpp index ba11667291..c1f9deb34b 100644 --- a/src/tiled/propertieswidget.cpp +++ b/src/tiled/propertieswidget.cpp @@ -418,10 +418,9 @@ class VariantMapProperty : public GroupProperty public: VariantMapProperty(const QString &name, QObject *parent = nullptr) : GroupProperty(name, parent) - { - } + {} - void setValue(const QVariantMap &value); + void setValue(const QVariantMap &value, const QVariantMap &suggestions = {}); const QVariantMap &value() const { return mValue; } signals: @@ -444,6 +443,7 @@ class VariantMapProperty : public GroupProperty void emitValueChangedRecursively(Property *property); QVariantMap mValue; + QVariantMap mSuggestions; QHash mPropertyMap; }; @@ -464,7 +464,31 @@ class CustomProperties : public VariantMapProperty private: // todo: optimize further + 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(); @@ -1196,6 +1220,7 @@ class ImageLayerProperties : public LayerProperties [this](const QColor &value) { push(new ChangeImageLayerTransparentColor(mapDocument(), { imageLayer() }, value)); }); + mTransparentColorProperty->setAlpha(false); mRepeatProperty = new ImageLayerRepeatProperty( tr("Repeat"), @@ -1250,7 +1275,7 @@ class ImageLayerProperties : public LayerProperties GroupProperty *mImageLayerProperties; UrlProperty *mImageProperty; - Property *mTransparentColorProperty; + ColorProperty *mTransparentColorProperty; Property *mRepeatProperty; }; @@ -2227,19 +2252,24 @@ void PropertiesWidget::currentObjectChanged(Object *object) } -void VariantMapProperty::setValue(const QVariantMap &value) +void VariantMapProperty::setValue(const QVariantMap &value, + const QVariantMap &suggestions) { mValue = value; + mSuggestions = suggestions; + + QVariantMap allProperties = mSuggestions; + mergeProperties(allProperties, mValue); clear(); - QMapIterator it(mValue); + QMapIterator it(allProperties); while (it.hasNext()) { it.next(); const QString &name = it.key(); auto get = [=] { - return mValue.value(name); + return mValue.value(name, mSuggestions.value(name)); }; auto set = [=] (const QVariant &value) { mValue.insert(name, value); @@ -2248,7 +2278,12 @@ void VariantMapProperty::setValue(const QVariantMap &value) }; if (auto property = createProperty({ name }, std::move(get), std::move(set))) { - property->setActions(Property::Remove); + if (mValue.contains(name)) { + property->setActions(Property::Action::Remove); + } else { + property->setEnabled(false); + property->setActions(Property::Action::Add); + } updateModifiedRecursively(property, it.value()); @@ -2258,12 +2293,34 @@ void VariantMapProperty::setValue(const QVariantMap &value) connect(property, &Property::removeRequested, this, [=] { mValue.remove(name); - if (auto property = mPropertyMap.take(name)) - deleteProperty(property); + if (!mSuggestions.contains(name)) { + if (auto property = mPropertyMap.take(name)) + deleteProperty(property); + } else { + if (auto property = mPropertyMap.value(name)) { + property->setEnabled(false); + property->setActions(Property::Action::Add); + emitValueChangedRecursively(property); + updateModifiedRecursively(property, mSuggestions.value(name)); + } + } emit memberValueChanged({ name }, QVariant()); emit valueChanged(); }); + + connect(property, &Property::addRequested, this, [=] { + const auto memberValue = mSuggestions.value(name); + mValue.insert(name, memberValue); + + if (auto property = mPropertyMap.value(name)) { + property->setEnabled(true); + property->setActions(Property::Action::Remove); + } + + emit memberValueChanged({ name }, memberValue); + emit valueChanged(); + }); } } @@ -2364,7 +2421,7 @@ void VariantMapProperty::createClassMembers(const QStringList &path, }; if (auto childProperty = createProperty(childPath, std::move(getMember), setMember)) { - childProperty->setActions(Property::Reset); + childProperty->setActions(Property::Action::Reset); groupProperty->addProperty(childProperty); connect(childProperty, &Property::resetRequested, this, [=] { @@ -2416,6 +2473,8 @@ void CustomProperties::setDocument(Document *document) 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); @@ -2429,10 +2488,14 @@ void CustomProperties::setDocument(Document *document) void CustomProperties::refresh() { - if (mDocument && mDocument->currentObject()) - setValue(mDocument->currentObject()->properties()); - else + if (!mDocument || !mDocument->currentObject()) { setValue({}); + return; + } + + // todo: gather the values from all selected objects + setValue(mDocument->currentObject()->properties(), + mDocument->currentObject()->inheritedProperties()); } void CustomProperties::setPropertyValue(const QStringList &path, const QVariant &value) diff --git a/src/tiled/propertyeditorwidgets.cpp b/src/tiled/propertyeditorwidgets.cpp index 284248c9a2..1a50ca321b 100644 --- a/src/tiled/propertyeditorwidgets.cpp +++ b/src/tiled/propertyeditorwidgets.cpp @@ -545,14 +545,19 @@ void PropertyLabel::setModified(bool modified) setFont(f); } -void PropertyLabel::mousePressEvent(QMouseEvent *event) -{ - if (m_expandable && event->button() == Qt::LeftButton) { - setExpanded(!m_expanded); - return; +bool PropertyLabel::event(QEvent *event) +{ + // Handled here instead of in mousePressEvent because we want it to be + // expandable also when the label is disabled. + if (event->type() == QEvent::MouseButtonPress && m_expandable) { + auto mouseEvent = static_cast(event); + if (mouseEvent->button() == Qt::LeftButton) { + setExpanded(!m_expanded); + return true; + } } - ElidingLabel::mousePressEvent(event); + return ElidingLabel::event(event); } void PropertyLabel::paintEvent(QPaintEvent *event) diff --git a/src/tiled/propertyeditorwidgets.h b/src/tiled/propertyeditorwidgets.h index cf3330ccd1..b29c1cf848 100644 --- a/src/tiled/propertyeditorwidgets.h +++ b/src/tiled/propertyeditorwidgets.h @@ -302,7 +302,7 @@ class PropertyLabel : public ElidingLabel void toggled(bool expanded); protected: - void mousePressEvent(QMouseEvent *event) override; + bool event(QEvent *event) override; void paintEvent(QPaintEvent *) override; private: 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/varianteditor.cpp b/src/tiled/varianteditor.cpp index a73a3831e1..6469775f20 100644 --- a/src/tiled/varianteditor.cpp +++ b/src/tiled/varianteditor.cpp @@ -65,6 +65,14 @@ void Property::setModified(bool modified) } } +void Property::setActions(Actions actions) +{ + if (m_actions != actions) { + m_actions = actions; + emit actionsChanged(actions); + } +} + void StringProperty::setPlaceholderText(const QString &placeholderText) { if (m_placeholderText != placeholderText) { @@ -328,10 +336,12 @@ QWidget *RectFProperty::createEditor(QWidget *parent) return editor; } -// todo: needs to handle invalid color (unset value) +// todo: needs to allow setting color back to invalid (unset) QWidget *ColorProperty::createEditor(QWidget *parent) { auto editor = new ColorButton(parent); + editor->setShowAlphaChannel(m_alpha); + auto syncEditor = [=] { const QSignalBlocker blocker(editor); editor->setColor(value()); @@ -507,8 +517,8 @@ void VariantEditor::clear() while (it.hasNext()) { it.next(); auto &widgets = it.value(); - Utils::deleteAllFromLayout(widgets.layout); - delete widgets.layout; + Utils::deleteAllFromLayout(widgets.rowLayout); + delete widgets.rowLayout; delete widgets.children; it.key()->disconnect(this); @@ -531,97 +541,102 @@ void VariantEditor::addProperty(Property *property) const auto halfSpacing = Utils::dpiScaled(2); - widgets.layout = new QHBoxLayout; - widgets.layout->setSpacing(halfSpacing * 2); + widgets.rowLayout = new QHBoxLayout; + widgets.rowLayout->setSpacing(halfSpacing * 2); if (displayMode == Property::DisplayMode::Separator) { auto separator = new QFrame(this); - widgets.layout->setContentsMargins(0, halfSpacing, 0, halfSpacing); + widgets.rowLayout->setContentsMargins(0, halfSpacing, 0, halfSpacing); separator->setFrameShape(QFrame::HLine); separator->setFrameShadow(QFrame::Plain); separator->setForegroundRole(QPalette::Mid); - widgets.layout->addWidget(separator); - m_layout->addLayout(widgets.layout); + widgets.rowLayout->addWidget(separator); + m_layout->addLayout(widgets.rowLayout); return; } - auto label = new PropertyLabel(m_level, this); + widgets.label = new PropertyLabel(m_level, this); if (displayMode != Property::DisplayMode::NoLabel) { - label->setText(property->name()); - label->setToolTip(property->toolTip()); - label->setEnabled(property->isEnabled()); - label->setModified(property->isModified()); - connect(property, &Property::toolTipChanged, label, &QWidget::setToolTip); - connect(property, &Property::enabledChanged, label, &QWidget::setEnabled); - connect(property, &Property::modifiedChanged, label, &PropertyLabel::setModified); + widgets.label->setText(property->name()); + widgets.label->setModified(property->isModified()); + connect(property, &Property::modifiedChanged, widgets.label, &PropertyLabel::setModified); } if (displayMode == Property::DisplayMode::Header) - label->setHeader(true); + widgets.label->setHeader(true); else - widgets.layout->setContentsMargins(0, halfSpacing, halfSpacing * 2, halfSpacing); - - widgets.layout->addWidget(label, LabelStretch, Qt::AlignTop); + widgets.rowLayout->setContentsMargins(0, halfSpacing, halfSpacing * 2, halfSpacing); - QHBoxLayout *editorLayout = widgets.layout; - const auto editor = property->createEditor(this); + widgets.rowLayout->addWidget(widgets.label, LabelStretch, Qt::AlignTop); - if (editor && property->actions()) { - editorLayout = new QHBoxLayout; - widgets.layout->addLayout(editorLayout, WidgetStretch); - } - - if (editor) { - editor->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); - editor->setToolTip(property->toolTip()); - editor->setEnabled(property->isEnabled()); - connect(property, &Property::toolTipChanged, editor, &QWidget::setToolTip); - connect(property, &Property::enabledChanged, editor, &QWidget::setEnabled); + widgets.editorLayout = new QHBoxLayout; + widgets.editor = property->createEditor(this); - editorLayout->addWidget(editor, WidgetStretch, Qt::AlignTop); + if (widgets.editor) { + widgets.editor->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); + widgets.editorLayout->addWidget(widgets.editor, EditorStretch, Qt::AlignTop); + widgets.rowLayout->addLayout(widgets.editorLayout, EditorStretch); + } else { + widgets.rowLayout->addLayout(widgets.editorLayout, 0); } - if (property->actions()) { - if (property->actions() & Property::Reset) { - auto resetButton = new QToolButton; - resetButton->setToolTip(tr("Reset")); - resetButton->setAutoRaise(true); - resetButton->setEnabled(property->isModified()); - Utils::setThemeIcon(resetButton, "edit-clear"); - editorLayout->addWidget(resetButton, 0, Qt::AlignTop); - connect(resetButton, &QAbstractButton::clicked, property, &Property::resetRequested); - connect(property, &Property::modifiedChanged, resetButton, &QWidget::setEnabled); - } - - if (property->actions() & Property::Remove) { - auto removeButton = new QToolButton; - removeButton->setToolTip(tr("Remove")); - removeButton->setAutoRaise(true); - Utils::setThemeIcon(removeButton, "remove"); - editorLayout->addWidget(removeButton, 0, Qt::AlignTop); - connect(removeButton, &QAbstractButton::clicked, property, &Property::removeRequested); - } - } + widgets.resetButton = new QToolButton(this); + widgets.resetButton->setToolTip(tr("Reset")); + widgets.resetButton->setAutoRaise(true); + widgets.resetButton->setEnabled(property->isModified()); + Utils::setThemeIcon(widgets.resetButton, "edit-clear"); + widgets.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(this); + widgets.removeButton->setToolTip(tr("Remove")); + widgets.removeButton->setAutoRaise(true); + Utils::setThemeIcon(widgets.removeButton, "remove"); + widgets.editorLayout->addWidget(widgets.removeButton, 0, Qt::AlignTop); + connect(widgets.removeButton, &QAbstractButton::clicked, property, &Property::removeRequested); + + widgets.addButton = new QToolButton(this); + widgets.addButton->setToolTip(tr("Add")); + widgets.addButton->setAutoRaise(true); + Utils::setThemeIcon(widgets.addButton, "add"); + widgets.editorLayout->addWidget(widgets.addButton, 0, Qt::AlignTop); + connect(widgets.addButton, &QAbstractButton::clicked, property, &Property::addRequested); + + updatePropertyEnabled(widgets, property->isEnabled()); + updatePropertyToolTip(widgets, property->toolTip()); + updatePropertyActions(widgets, property->actions()); + + connect(property, &Property::enabledChanged, this, [=] (bool enabled) { + updatePropertyEnabled(m_propertyWidgets[property], enabled); + }); + connect(property, &Property::toolTipChanged, this, [=] (const QString &toolTip) { + updatePropertyToolTip(m_propertyWidgets[property], toolTip); + }); + connect(property, &Property::actionsChanged, this, [=] (Property::Actions actions) { + updatePropertyActions(m_propertyWidgets[property], actions); + }); - m_layout->addLayout(widgets.layout); + m_layout->addLayout(widgets.rowLayout); if (auto groupProperty = dynamic_cast(property)) { - label->setExpandable(true); - label->setExpanded(label->isHeader()); + widgets.label->setExpandable(true); + widgets.label->setExpanded(widgets.label->isHeader()); auto children = new VariantEditor(this); - if (label->isHeader()) + if (widgets.label->isHeader()) children->setContentsMargins(0, halfSpacing, 0, halfSpacing); children->setLevel(m_level + 1); - children->setVisible(label->isExpanded()); + children->setEnabled(property->isEnabled()); + children->setVisible(widgets.label->isExpanded()); for (auto property : groupProperty->subProperties()) children->addProperty(property); connect(groupProperty, &GroupProperty::propertyAdded, children, &VariantEditor::addProperty); - connect(label, &PropertyLabel::toggled, children, [=](bool expanded) { + connect(widgets.label, &PropertyLabel::toggled, children, [=](bool expanded) { children->setVisible(expanded); // needed to avoid flickering when hiding the editor @@ -645,10 +660,10 @@ void VariantEditor::removeProperty(Property *property) auto it = m_propertyWidgets.constFind(property); Q_ASSERT(it != m_propertyWidgets.constEnd()); - if (it != m_propertyWidgets.end()) { + if (it != m_propertyWidgets.constEnd()) { auto &widgets = it.value(); - Utils::deleteAllFromLayout(widgets.layout); - delete widgets.layout; + Utils::deleteAllFromLayout(widgets.rowLayout); + delete widgets.rowLayout; delete widgets.children; m_propertyWidgets.erase(it); @@ -666,6 +681,31 @@ void VariantEditor::setLevel(int level) setAutoFillBackground(m_level > 1); } +void VariantEditor::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 VariantEditor::updatePropertyToolTip(const PropertyWidgets &widgets, const QString &toolTip) +{ + if (widgets.label) + widgets.label->setToolTip(toolTip); + if (widgets.editor) + widgets.editor->setToolTip(toolTip); +} + +void VariantEditor::updatePropertyActions(const PropertyWidgets &widgets, Property::Actions actions) +{ + widgets.resetButton->setVisible(actions & Property::Action::Reset); + widgets.removeButton->setVisible(actions & Property::Action::Remove); + widgets.addButton->setVisible(actions & Property::Action::Add); +} + QWidget *BaseEnumProperty::createEnumEditor(QWidget *parent) { diff --git a/src/tiled/varianteditor.h b/src/tiled/varianteditor.h index c4dc66a928..9ef8f11ba8 100644 --- a/src/tiled/varianteditor.h +++ b/src/tiled/varianteditor.h @@ -30,6 +30,7 @@ #include class QHBoxLayout; +class QToolButton; class QVBoxLayout; namespace Tiled { @@ -46,6 +47,7 @@ class Property : public QObject 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(Actions actions READ actions WRITE setActions NOTIFY actionsChanged) public: enum class DisplayMode { @@ -55,9 +57,10 @@ class Property : public QObject Separator }; - enum Action { + enum class Action { Reset = 0x01, Remove = 0x02, + Add = 0x04, }; Q_DECLARE_FLAGS(Actions, Action) @@ -78,7 +81,7 @@ class Property : public QObject void setModified(bool modified); Actions actions() const { return m_actions; } - void setActions(Actions actions) { m_actions = actions; } + void setActions(Actions actions); virtual DisplayMode displayMode() const { return DisplayMode::Default; } @@ -89,9 +92,11 @@ class Property : public QObject void valueChanged(); void enabledChanged(bool enabled); void modifiedChanged(bool modified); + void actionsChanged(Actions actions); void resetRequested(); void removeRequested(); + void addRequested(); private: friend class GroupProperty; @@ -349,6 +354,11 @@ 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 @@ -461,14 +471,24 @@ class VariantEditor : public QWidget private: static constexpr int LabelStretch = 4; - static constexpr int WidgetStretch = 6; + static constexpr int EditorStretch = 6; struct PropertyWidgets { - QHBoxLayout *layout = nullptr; + QHBoxLayout *rowLayout = nullptr; + QHBoxLayout *editorLayout = nullptr; + PropertyLabel *label = nullptr; + QWidget *editor = nullptr; + QToolButton *resetButton = nullptr; + QToolButton *removeButton = nullptr; + QToolButton *addButton = nullptr; QWidget *children = nullptr; }; + void updatePropertyEnabled(const PropertyWidgets &widgets, bool enabled); + void updatePropertyToolTip(const PropertyWidgets &widgets, const QString &toolTip); + void updatePropertyActions(const PropertyWidgets &widgets, Property::Actions actions); + QVBoxLayout *m_layout; QHash m_propertyWidgets; int m_level = 0;