diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp index 43be341e8ab..04c231a9ba4 100644 --- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp +++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -1161,6 +1162,38 @@ bool isStackedContainer(const SelectionContext &context) return NodeHints::fromModelNode(currentSelectedNode).isStackedContainer(); } +bool isStackedContainerAndIndexIsVariantOrResolvableBinding(const SelectionContext &context) +{ + if (!isStackedContainer(context)) + return false; + + ModelNode currentSelectedNode = context.currentSingleSelectedNode(); + + const PropertyName propertyName = ModelNodeOperations::getIndexPropertyName(currentSelectedNode); + + QTC_ASSERT(currentSelectedNode.metaInfo().hasProperty(propertyName), return false); + + QmlItemNode containerItemNode(currentSelectedNode); + + QTC_ASSERT(containerItemNode.isValid(), return false); + + if (containerItemNode.hasBindingProperty(propertyName)) { + const AbstractProperty resolvedProperty = containerItemNode.bindingProperty(propertyName) + .resolveToProperty(); + if (resolvedProperty.isValid() && resolvedProperty.isVariantProperty()) { + auto variantProperty = resolvedProperty.toVariantProperty(); + if (!variantProperty.isValid()) + return false; + + return true; + } + + return false; + } + + return containerItemNode.modelNode().hasVariantProperty(propertyName); +} + bool isStackedContainerWithoutTabBar(const SelectionContext &context) { if (!isStackedContainer(context)) @@ -1196,11 +1229,38 @@ bool isStackedContainerAndIndexCanBeDecreased(const SelectionContext &context) QTC_ASSERT(currentSelectedNode.metaInfo().hasProperty(propertyName), return false); QmlItemNode containerItemNode(currentSelectedNode); + QTC_ASSERT(containerItemNode.isValid(), return false); - const int value = containerItemNode.instanceValue(propertyName).toInt(); + auto isMoreThan = [](const QVariant &variant, int min) -> bool { + if (!variant.isValid()) + return false; - return value > 0; + bool ok = false; + int value = variant.toInt(&ok); + return ok && value > min; + }; + + if (currentSelectedNode.hasBindingProperty(propertyName)) { + const AbstractProperty resolvedProperty = currentSelectedNode.bindingProperty(propertyName) + .resolveToProperty(); + if (resolvedProperty.isValid() && resolvedProperty.isVariantProperty()) { + const auto variantProperty = resolvedProperty.toVariantProperty(); + if (!variantProperty.isValid()) + return false; + + if (isMoreThan(variantProperty.value(), 0)) + return true; + } + + return false; + } + + QVariant modelValue = containerItemNode.modelValue(propertyName); + if (isMoreThan(modelValue, 0)) + return true; + + return false; } bool isStackedContainerAndIndexCanBeIncreased(const SelectionContext &context) @@ -1215,13 +1275,40 @@ bool isStackedContainerAndIndexCanBeIncreased(const SelectionContext &context) QTC_ASSERT(currentSelectedNode.metaInfo().hasProperty(propertyName), return false); QmlItemNode containerItemNode(currentSelectedNode); + QTC_ASSERT(containerItemNode.isValid(), return false); - const int value = containerItemNode.instanceValue(propertyName).toInt(); + auto isLessThan = [](const QVariant &variant, int max) -> bool { + if (!variant.isValid()) + return false; + + bool ok = false; + int value = variant.toInt(&ok); + return ok && value < max; + }; const int maxValue = currentSelectedNode.directSubModelNodes().size() - 1; - return value < maxValue; + if (currentSelectedNode.hasBindingProperty(propertyName)) { + const AbstractProperty resolvedProperty = currentSelectedNode.bindingProperty(propertyName) + .resolveToProperty(); + if (resolvedProperty.isValid() && resolvedProperty.isVariantProperty()) { + const auto variantProperty = resolvedProperty.toVariantProperty(); + if (!variantProperty.isValid()) + return false; + + if (isLessThan(variantProperty.value(), maxValue)) + return true; + } + + return false; + } + + QVariant modelValue = containerItemNode.modelValue(propertyName); + if (isLessThan(modelValue, maxValue)) + return true; + + return false; } bool isGroup(const SelectionContext &context) @@ -1851,40 +1938,38 @@ void DesignerActionManager::createDefaultDesignerActions() &isStackedContainer, &isStackedContainer)); - addDesignerAction(new ModelNodeContextMenuAction( - addTabBarToStackedContainerCommandId, - addTabBarToStackedContainerDisplayName, - {}, - stackedContainerCategory, - QKeySequence("Ctrl+Shift+t"), - 2, - &addTabBarToStackedContainer, - &isStackedContainerWithoutTabBar, - &isStackedContainer)); + addDesignerAction(new ModelNodeContextMenuAction(addTabBarToStackedContainerCommandId, + addTabBarToStackedContainerDisplayName, + {}, + stackedContainerCategory, + QKeySequence("Ctrl+Shift+t"), + 2, + &addTabBarToStackedContainer, + &isStackedContainerWithoutTabBar, + &isStackedContainer)); - addDesignerAction(new ModelNodeFormEditorAction( - decreaseIndexOfStackedContainerCommandId, - decreaseIndexToStackedContainerDisplayName, - prevIcon.icon(), - decreaseIndexOfStackedContainerToolTip, - stackedContainerCategory, - QKeySequence("Ctrl+Shift+Left"), - 3, - &decreaseIndexOfStackedContainer, - &isStackedContainerAndIndexCanBeDecreased, - &isStackedContainer)); - - addDesignerAction(new ModelNodeFormEditorAction( - increaseIndexOfStackedContainerCommandId, - increaseIndexToStackedContainerDisplayName, - nextIcon.icon(), - increaseIndexOfStackedContainerToolTip, - stackedContainerCategory, - QKeySequence("Ctrl+Shift+Right"), - 4, - &increaseIndexOfStackedContainer, - &isStackedContainerAndIndexCanBeIncreased, - &isStackedContainer)); + addDesignerAction( + new ModelNodeFormEditorAction(decreaseIndexOfStackedContainerCommandId, + decreaseIndexToStackedContainerDisplayName, + prevIcon.icon(), + decreaseIndexOfStackedContainerToolTip, + stackedContainerCategory, + QKeySequence("Ctrl+Shift+Left"), + 3, + &decreaseIndexOfStackedContainer, + &isStackedContainerAndIndexCanBeDecreased, + &isStackedContainerAndIndexIsVariantOrResolvableBinding)); + addDesignerAction( + new ModelNodeFormEditorAction(increaseIndexOfStackedContainerCommandId, + increaseIndexToStackedContainerDisplayName, + nextIcon.icon(), + increaseIndexOfStackedContainerToolTip, + stackedContainerCategory, + QKeySequence("Ctrl+Shift+Right"), + 4, + &increaseIndexOfStackedContainer, + &isStackedContainerAndIndexCanBeIncreased, + &isStackedContainerAndIndexIsVariantOrResolvableBinding)); addDesignerAction( new ModelNodeAction(layoutRowLayoutCommandId, diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp index 2fad0ef8da6..3d5626a585e 100644 --- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp +++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp @@ -1132,6 +1132,46 @@ static void setIndexProperty(const AbstractProperty &property, const QVariant &v Core::AsynchronousMessageBox::warning(title, description); } +static std::optional getIndexProperty(const AbstractProperty &property) +{ + if (property.isBindingProperty()) { + const AbstractProperty resolvedProperty = property.toBindingProperty().resolveToProperty(); + if (resolvedProperty.isValid() && resolvedProperty.isVariantProperty()) { + const auto variantProperty = resolvedProperty.toVariantProperty(); + if (!variantProperty.isValid()) + return std::nullopt; + + auto variant = variantProperty.value(); + if (!variant.isValid()) + return std::nullopt; + + bool ok = false; + int value = variant.toInt(&ok); + if (!ok) + return std::nullopt; + + return value; + } + } else { + QmlItemNode itemNode(property.parentModelNode()); + if (!itemNode.isValid()) + return std::nullopt; + + QVariant modelValue(itemNode.modelValue(property.name())); + if (!modelValue.isValid()) + return std::nullopt; + + bool ok = false; + int value = modelValue.toInt(&ok); + if (!ok) + return std::nullopt; + + return value; + } + + return std::nullopt; +} + void increaseIndexOfStackedContainer(const SelectionContext &selectionContext) { AbstractView *view = selectionContext.view(); @@ -1144,17 +1184,16 @@ void increaseIndexOfStackedContainer(const SelectionContext &selectionContext) const PropertyName propertyName = getIndexPropertyName(container); QTC_ASSERT(container.metaInfo().hasProperty(propertyName), return); - QmlItemNode containerItemNode(container); - QTC_ASSERT(containerItemNode.isValid(), return); + std::optional value = getIndexProperty(container.property(propertyName)); + QTC_ASSERT(value, return); - int value = containerItemNode.instanceValue(propertyName).toInt(); - ++value; + ++*value; const int maxValue = container.directSubModelNodes().size(); QTC_ASSERT(value < maxValue, return); - setIndexProperty(container.property(propertyName), value); + setIndexProperty(container.property(propertyName), *value); } void decreaseIndexOfStackedContainer(const SelectionContext &selectionContext) @@ -1169,15 +1208,14 @@ void decreaseIndexOfStackedContainer(const SelectionContext &selectionContext) const PropertyName propertyName = getIndexPropertyName(container); QTC_ASSERT(container.metaInfo().hasProperty(propertyName), return); - QmlItemNode containerItemNode(container); - QTC_ASSERT(containerItemNode.isValid(), return); + std::optional value = getIndexProperty(container.property(propertyName)); + QTC_ASSERT(value, return); - int value = containerItemNode.instanceValue(propertyName).toInt(); - --value; + --*value; QTC_ASSERT(value > -1, return); - setIndexProperty(container.property(propertyName), value); + setIndexProperty(container.property(propertyName), *value); } void addTabBarToStackedContainer(const SelectionContext &selectionContext) diff --git a/src/plugins/qmldesigner/components/formeditor/formeditortoolbutton.cpp b/src/plugins/qmldesigner/components/formeditor/formeditortoolbutton.cpp index d6cb6428da5..ce9a7b1ffcd 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditortoolbutton.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditortoolbutton.cpp @@ -7,8 +7,8 @@ #include #include -#include #include +#include #include #include @@ -19,16 +19,21 @@ static const auto category = FormEditorTracing::category; const int toolButtonSize = 14; -FormEditorToolButton::FormEditorToolButton(QAction *action, QGraphicsItem *parent) : QGraphicsWidget(parent), m_action(action) +FormEditorToolButton::FormEditorToolButton(QAction *action, QGraphicsItem *parent) + : QGraphicsWidget(parent) + , m_action(action) { NanotraceHR::Tracer tracer{"form editor tool button constructor", category()}; resize(toolButtonSize, toolButtonSize + 2); setPreferredSize(toolButtonSize, toolButtonSize + 2); setAcceptHoverEvents(true); - connect(action, &QAction::changed, this, [this](){ + connect(action, &QAction::changed, this, [this]() { setEnabled(m_action->isEnabled()); setVisible(m_action->isVisible()); + // Reset to Normal. When action isn't enabled anymore and therefor the button too, it + // doesn't receives events anymore, which leaves the state in Hover. + m_state = Normal; update(); }); @@ -46,10 +51,14 @@ void FormEditorToolButton::paint(QPainter *painter, const QStyleOptionGraphicsIt painter->save(); painter->setRenderHint(QPainter::Antialiasing); - QRectF adjustedRect(size().width() - toolButtonSize, size().height() - toolButtonSize, toolButtonSize, toolButtonSize); + QRectF adjustedRect(size().width() - toolButtonSize, + size().height() - toolButtonSize, + toolButtonSize, + toolButtonSize); painter->setPen(Qt::NoPen); - static QColor selectionColor = Utils::creatorColor(Utils::Theme::QmlDesigner_FormEditorSelectionColor); + static QColor selectionColor = Utils::creatorColor( + Utils::Theme::QmlDesigner_FormEditorSelectionColor); if (m_state == Hovered) painter->setBrush(selectionColor.lighter(110)); @@ -60,9 +69,11 @@ void FormEditorToolButton::paint(QPainter *painter, const QStyleOptionGraphicsIt painter->drawRoundedRect(adjustedRect, 1, 1, Qt::AbsoluteSize); if (!isEnabled()) - setOpacity(0.5); + painter->setOpacity(0.5); - painter->drawPixmap(size().width() - toolButtonSize, size().height() - toolButtonSize, m_action->icon().pixmap(toolButtonSize, toolButtonSize)); + painter->drawPixmap(size().width() - toolButtonSize, + size().height() - toolButtonSize, + m_action->icon().pixmap(toolButtonSize, toolButtonSize)); painter->restore(); } @@ -74,7 +85,7 @@ QRectF FormEditorToolButton::boundingRect() const return QRectF(0, 0, toolButtonSize, toolButtonSize + 2); } -void FormEditorToolButton::hoverEnterEvent(QGraphicsSceneHoverEvent * event) +void FormEditorToolButton::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { NanotraceHR::Tracer tracer{"form editor tool button hover enter event", category()}; @@ -85,7 +96,7 @@ void FormEditorToolButton::hoverEnterEvent(QGraphicsSceneHoverEvent * event) update(); } -void FormEditorToolButton::hoverLeaveEvent(QGraphicsSceneHoverEvent * event) +void FormEditorToolButton::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { NanotraceHR::Tracer tracer{"form editor tool button hover leave event", category()}; @@ -96,14 +107,14 @@ void FormEditorToolButton::hoverLeaveEvent(QGraphicsSceneHoverEvent * event) update(); } -void FormEditorToolButton::hoverMoveEvent(QGraphicsSceneHoverEvent * event) +void FormEditorToolButton::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { NanotraceHR::Tracer tracer{"form editor tool button hover move event", category()}; QGraphicsWidget::hoverMoveEvent(event); } -void FormEditorToolButton::mousePressEvent(QGraphicsSceneMouseEvent * event) +void FormEditorToolButton::mousePressEvent(QGraphicsSceneMouseEvent *event) { NanotraceHR::Tracer tracer{"form editor tool button mouse press event", category()}; @@ -112,7 +123,7 @@ void FormEditorToolButton::mousePressEvent(QGraphicsSceneMouseEvent * event) update(); } -void FormEditorToolButton::mouseReleaseEvent(QGraphicsSceneMouseEvent * event) +void FormEditorToolButton::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { NanotraceHR::Tracer tracer{"form editor tool button mouse release event", category()}; @@ -122,4 +133,4 @@ void FormEditorToolButton::mouseReleaseEvent(QGraphicsSceneMouseEvent * event) emit clicked(); } -} //QmlDesigner +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/formeditor/selectionindicator.cpp b/src/plugins/qmldesigner/components/formeditor/selectionindicator.cpp index fccbbf0d83d..988507111b5 100644 --- a/src/plugins/qmldesigner/components/formeditor/selectionindicator.cpp +++ b/src/plugins/qmldesigner/components/formeditor/selectionindicator.cpp @@ -74,8 +74,8 @@ void SelectionIndicator::clear() static QPolygonF boundingRectInLayerItemSpaceForItem(FormEditorItem *item, QGraphicsItem *layerItem) { - QPolygonF boundingRectInSceneSpace(item->mapToScene(item->qmlItemNode().instanceBoundingRect())); - return layerItem->mapFromScene(boundingRectInSceneSpace); + QPolygonF boundingRectInSceneSpace(item->mapToScene(item->qmlItemNode().instanceBoundingRect())); + return layerItem->mapFromScene(boundingRectInSceneSpace); } static bool checkSingleSelection(const QList &itemList) @@ -204,7 +204,7 @@ void SelectionIndicator::setCursor(const QCursor &cursor) m_cursor = cursor; - for (QGraphicsItem *item : std::as_const(m_indicatorShapeHash)) + for (QGraphicsItem *item : std::as_const(m_indicatorShapeHash)) item->setCursor(cursor); } @@ -212,23 +212,23 @@ void SelectionIndicator::adjustAnnotationPosition(const QRectF &itemRect, const { NanotraceHR::Tracer tracer{"selection indicator adjust annotation position", category()}; - if (!m_annotationItem) return; + if (!m_annotationItem) + return; const qreal iconWShift = m_annotationItem->iconWidth() * 0.5; - const qreal iconHShift = (m_annotationItem->iconHeight() * 0.45)/scaleFactor; + const qreal iconHShift = (m_annotationItem->iconHeight() * 0.45) / scaleFactor; qreal iconX = 0.0; qreal iconY = -(iconHShift); - if (((labelRect.width() + iconWShift)/scaleFactor) > itemRect.width()) - iconY -= labelRect.height()/scaleFactor; + if (((labelRect.width() + iconWShift) / scaleFactor) > itemRect.width()) + iconY -= labelRect.height() / scaleFactor; - if ((iconWShift/scaleFactor) > itemRect.width()) + if ((iconWShift / scaleFactor) > itemRect.width()) iconX = 0.0; else - iconX = (itemRect.width()) - (iconWShift/scaleFactor); - - m_annotationItem->setPos(iconX*scaleFactor, iconY*scaleFactor); -} + iconX = (itemRect.width()) - (iconWShift / scaleFactor); + m_annotationItem->setPos(iconX * scaleFactor, iconY * scaleFactor); +} }