forked from qt-creator/qt-creator
QmlDesigner: Fix stacked container UI
* Add a new check for stacked container and index property being either a variant or a resolvable binding. * Decrease/increase checks read resolvable bindings if applicable and use model value if not. * Increase/decrease functions use resolvable bindings if applicable and use model value if not. * Fix FormEditorToolButton opacity being set on the widget instead of the painter. Task-number: QDS-15274 Change-Id: Ia8c95b900204d3d4041cda7f60534eb3a52c3f65 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
committed by
Henning Gründl
parent
1a3998e51c
commit
a80281c6ed
@@ -25,6 +25,7 @@
|
||||
#include <nodeproperty.h>
|
||||
#include <qmldesignertr.h>
|
||||
#include <theme.h>
|
||||
#include <variantproperty.h>
|
||||
|
||||
#include <formeditortoolbutton.h>
|
||||
|
||||
@@ -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,8 +1938,7 @@ void DesignerActionManager::createDefaultDesignerActions()
|
||||
&isStackedContainer,
|
||||
&isStackedContainer));
|
||||
|
||||
addDesignerAction(new ModelNodeContextMenuAction(
|
||||
addTabBarToStackedContainerCommandId,
|
||||
addDesignerAction(new ModelNodeContextMenuAction(addTabBarToStackedContainerCommandId,
|
||||
addTabBarToStackedContainerDisplayName,
|
||||
{},
|
||||
stackedContainerCategory,
|
||||
@@ -1862,8 +1948,8 @@ void DesignerActionManager::createDefaultDesignerActions()
|
||||
&isStackedContainerWithoutTabBar,
|
||||
&isStackedContainer));
|
||||
|
||||
addDesignerAction(new ModelNodeFormEditorAction(
|
||||
decreaseIndexOfStackedContainerCommandId,
|
||||
addDesignerAction(
|
||||
new ModelNodeFormEditorAction(decreaseIndexOfStackedContainerCommandId,
|
||||
decreaseIndexToStackedContainerDisplayName,
|
||||
prevIcon.icon(),
|
||||
decreaseIndexOfStackedContainerToolTip,
|
||||
@@ -1872,10 +1958,9 @@ void DesignerActionManager::createDefaultDesignerActions()
|
||||
3,
|
||||
&decreaseIndexOfStackedContainer,
|
||||
&isStackedContainerAndIndexCanBeDecreased,
|
||||
&isStackedContainer));
|
||||
|
||||
addDesignerAction(new ModelNodeFormEditorAction(
|
||||
increaseIndexOfStackedContainerCommandId,
|
||||
&isStackedContainerAndIndexIsVariantOrResolvableBinding));
|
||||
addDesignerAction(
|
||||
new ModelNodeFormEditorAction(increaseIndexOfStackedContainerCommandId,
|
||||
increaseIndexToStackedContainerDisplayName,
|
||||
nextIcon.icon(),
|
||||
increaseIndexOfStackedContainerToolTip,
|
||||
@@ -1884,7 +1969,7 @@ void DesignerActionManager::createDefaultDesignerActions()
|
||||
4,
|
||||
&increaseIndexOfStackedContainer,
|
||||
&isStackedContainerAndIndexCanBeIncreased,
|
||||
&isStackedContainer));
|
||||
&isStackedContainerAndIndexIsVariantOrResolvableBinding));
|
||||
|
||||
addDesignerAction(
|
||||
new ModelNodeAction(layoutRowLayoutCommandId,
|
||||
|
@@ -1132,6 +1132,46 @@ static void setIndexProperty(const AbstractProperty &property, const QVariant &v
|
||||
Core::AsynchronousMessageBox::warning(title, description);
|
||||
}
|
||||
|
||||
static std::optional<int> 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<int> 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<int> 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)
|
||||
|
@@ -7,8 +7,8 @@
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QPainter>
|
||||
|
||||
#include <utils/theme/theme.h>
|
||||
#include <utils/stylehelper.h>
|
||||
#include <utils/theme/theme.h>
|
||||
|
||||
#include <QAction>
|
||||
#include <QCursor>
|
||||
@@ -19,7 +19,9 @@ 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()};
|
||||
|
||||
@@ -29,6 +31,9 @@ FormEditorToolButton::FormEditorToolButton(QAction *action, QGraphicsItem *paren
|
||||
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();
|
||||
}
|
||||
@@ -122,4 +133,4 @@ void FormEditorToolButton::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
|
||||
emit clicked();
|
||||
}
|
||||
|
||||
} //QmlDesigner
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -212,7 +212,8 @@ 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;
|
||||
@@ -229,6 +230,5 @@ void SelectionIndicator::adjustAnnotationPosition(const QRectF &itemRect, const
|
||||
|
||||
m_annotationItem->setPos(iconX * scaleFactor, iconY * scaleFactor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user