QmlDesigner: Add 1-to-n / n-to-1 transitions

* Add one-to-many / many-to-one transitions visualization
* Fix bounding rect of flow items
* Cleanup flow view draw code

Task-number: QDS-2178
Task-number: QDS-2211
Change-Id: I5bf6ec04c6ca730dd1fac6226e5d694963e761b5
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Henning Gruendl
2020-06-03 11:28:24 +02:00
committed by Thomas Hartmann
parent b851b71128
commit d30081ba39
6 changed files with 744 additions and 461 deletions

View File

@@ -186,7 +186,7 @@ FormEditorItem *AbstractFormEditorTool::topMovableFormEditorItem(const QList<QGr
return nullptr;
}
FormEditorItem* AbstractFormEditorTool::nearestFormEditorItem(const QPointF &point, const QList<QGraphicsItem*> & itemList)
FormEditorItem* AbstractFormEditorTool::nearestFormEditorItem(const QPointF &point, const QList<QGraphicsItem*> &itemList)
{
FormEditorItem* nearestItem = nullptr;
foreach (QGraphicsItem *item, itemList) {

View File

@@ -1,5 +1,4 @@
/****************************************************************************
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
@@ -47,37 +46,13 @@ namespace Internal {
class MoveController;
}
enum ConnectionType
{
Default = 0,
Bezier
};
class ConnectionStyle
{
public:
qreal width;
qreal adjustedWidth;
QColor color;
bool dash;
int outOffset;
int inOffset;
int breakOffset;
int radius;
int bezier;
ConnectionType type;
qreal labelOffset;
qreal labelPosition;
bool labelFlipSide;
};
class QMLDESIGNERCORE_EXPORT FormEditorItem : public QGraphicsItem
{
friend class QmlDesigner::FormEditorScene;
public:
~FormEditorItem() override;
void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = nullptr ) override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
bool isContainer() const;
QmlItemNode qmlItemNode() const;
@@ -182,7 +157,7 @@ public:
QPointF instancePosition() const override;
protected:
FormEditorFlowItem(const QmlItemNode &qmlItemNode, FormEditorScene* scene)
FormEditorFlowItem(const QmlItemNode &qmlItemNode, FormEditorScene *scene)
: FormEditorItem(qmlItemNode, scene)
{}
};
@@ -191,12 +166,15 @@ class FormEditorFlowActionItem : public FormEditorItem
{
friend class QmlDesigner::FormEditorScene;
public:
void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = nullptr ) override;
void setDataModelPosition(const QPointF &position) override;
void setDataModelPositionInBaseState(const QPointF &position) override;
void updateGeometry() override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
QTransform instanceSceneTransform() const override;
QTransform instanceSceneContentItemTransform() const override;
protected:
FormEditorFlowActionItem(const QmlItemNode &qmlItemNode, FormEditorScene* scene)
FormEditorFlowActionItem(const QmlItemNode &qmlItemNode, FormEditorScene *scene)
: FormEditorItem(qmlItemNode, scene)
{}
};
@@ -210,11 +188,11 @@ public:
void setDataModelPositionInBaseState(const QPointF &position) override;
void updateGeometry() override;
QPointF instancePosition() const override;
void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = nullptr ) override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
bool flowHitTest(const QPointF &point) const override;
protected:
FormEditorTransitionItem(const QmlItemNode &qmlItemNode, FormEditorScene* scene)
FormEditorTransitionItem(const QmlItemNode &qmlItemNode, FormEditorScene *scene)
: FormEditorItem(qmlItemNode, scene)
{}
private:
@@ -227,7 +205,7 @@ class FormEditorFlowDecisionItem : FormEditorFlowItem
public:
void updateGeometry() override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem * option, QWidget * widget = nullptr ) override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
bool flowHitTest(const QPointF &point) const override;
protected:
@@ -237,7 +215,7 @@ protected:
};
FormEditorFlowDecisionItem(const QmlItemNode &qmlItemNode,
FormEditorScene* scene,
FormEditorScene *scene,
IconType iconType = DecisionIcon)
: FormEditorFlowItem(qmlItemNode, scene), m_iconType(iconType)
{}
@@ -249,10 +227,10 @@ class FormEditorFlowWildcardItem : FormEditorFlowDecisionItem
friend class QmlDesigner::FormEditorScene;
public:
void paint(QPainter *painter, const QStyleOptionGraphicsItem * option, QWidget * widget = nullptr ) override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
protected:
FormEditorFlowWildcardItem(const QmlItemNode &qmlItemNode, FormEditorScene* scene)
FormEditorFlowWildcardItem(const QmlItemNode &qmlItemNode, FormEditorScene *scene)
: FormEditorFlowDecisionItem(qmlItemNode, scene, WildcardIcon)
{
}

View File

@@ -36,6 +36,7 @@
#include "abstractcustomtool.h"
#include <bindingproperty.h>
#include <variantproperty.h>
#include <designersettings.h>
#include <designmodecontext.h>
#include <modelnode.h>
@@ -385,18 +386,38 @@ void FormEditorView::selectedNodesChanged(const QList<ModelNode> &selectedNodeLi
m_scene->update();
}
void FormEditorView::bindingPropertiesChanged(const QList<BindingProperty> &propertyList, AbstractView::PropertyChangeFlags propertyChange)
void FormEditorView::variantPropertiesChanged(const QList<VariantProperty> &propertyList,
AbstractView::PropertyChangeFlags propertyChange)
{
Q_UNUSED(propertyChange)
for (const VariantProperty &property : propertyList) {
QmlVisualNode node(property.parentModelNode());
if (node.isFlowTransition()) {
if (FormEditorItem *item = m_scene->itemForQmlItemNode(node.toQmlItemNode())) {
if (property.name() == "question")
item->updateGeometry();
}
}
}
}
void FormEditorView::bindingPropertiesChanged(const QList<BindingProperty> &propertyList,
AbstractView::PropertyChangeFlags propertyChange)
{
Q_UNUSED(propertyChange)
for (const BindingProperty &property : propertyList) {
QmlVisualNode node(property.parentModelNode());
if (node.isFlowTransition()) {
FormEditorItem *item = m_scene->itemForQmlItemNode(node.toQmlItemNode());
if (item && node.hasNodeParent()) {
if (FormEditorItem *item = m_scene->itemForQmlItemNode(node.toQmlItemNode())) {
if (property.name() == "condition" || property.name() == "question")
item->updateGeometry();
if (node.hasNodeParent()) {
m_scene->reparentItem(node.toQmlItemNode(), node.toQmlItemNode().modelParentItem());
m_scene->synchronizeTransformation(item);
item->update();
}
}
} else if (QmlFlowActionAreaNode::isValidQmlFlowActionAreaNode(property.parentModelNode())) {
const QmlVisualNode target = property.resolveToModelNode();
if (target.modelNode().isValid() && target.isFlowTransition()) {
@@ -502,7 +523,7 @@ void FormEditorView::changeToCustomTool()
const ModelNode selectedModelNode = selectedModelNodes().constFirst();
foreach (AbstractCustomTool *customTool, m_customToolList) {
for (AbstractCustomTool *customTool : m_customToolList) {
if (customTool->wantHandleItem(selectedModelNode) > handlingRank) {
handlingRank = customTool->wantHandleItem(selectedModelNode);
selectedCustomTool = customTool;
@@ -547,9 +568,17 @@ void FormEditorView::auxiliaryDataChanged(const ModelNode &node, const PropertyN
}
} else if (item.isFlowTransition() || item.isFlowActionArea()
|| item.isFlowDecision() || item.isFlowWildcard()) {
FormEditorItem *editorItem = m_scene->itemForQmlItemNode(item);
if (editorItem)
if (FormEditorItem *editorItem = m_scene->itemForQmlItemNode(item)) {
// Update the geomtry if one of the following auxiliary properties has changed
static const QStringList updateGeometryPropertyNames = {
"breakPoint", "bezier", "transitionBezier", "type", "tranitionType", "radius",
"transitionRadius", "labelPosition", "labelFlipSide", "inOffset", "outOffset"
};
if (updateGeometryPropertyNames.contains(QString::fromUtf8(name)))
editorItem->updateGeometry();
editorItem->update();
}
} else if (item.isFlowView() || item.isFlowItem()) {
scene()->update();
} else if (name == "annotation" || name == "customId") {
@@ -562,7 +591,7 @@ void FormEditorView::auxiliaryDataChanged(const ModelNode &node, const PropertyN
void FormEditorView::instancesCompleted(const QVector<ModelNode> &completedNodeList)
{
QList<FormEditorItem*> itemNodeList;
foreach (const ModelNode &node, completedNodeList) {
for (const ModelNode &node : completedNodeList) {
const QmlItemNode qmlItemNode(node);
if (qmlItemNode.isValid()) {
if (FormEditorItem *item = scene()->itemForQmlItemNode(qmlItemNode)) {
@@ -584,7 +613,7 @@ void FormEditorView::instanceInformationsChanged(const QMultiHash<ModelNode, Inf
return QmlItemNode::isValidQmlItemNode(node);
});
foreach (const ModelNode &node, informationChangedNodes) {
for (const ModelNode &node : informationChangedNodes) {
const QmlItemNode qmlItemNode(node);
if (FormEditorItem *item = scene()->itemForQmlItemNode(qmlItemNode)) {
scene()->synchronizeTransformation(item);
@@ -621,7 +650,7 @@ void FormEditorView::instanceInformationsChanged(const QMultiHash<ModelNode, Inf
void FormEditorView::instancesRenderImageChanged(const QVector<ModelNode> &nodeList)
{
foreach (const ModelNode &node, nodeList) {
for (const ModelNode &node : nodeList) {
if (QmlItemNode::isValidQmlItemNode(node))
if (FormEditorItem *item = scene()->itemForQmlItemNode(QmlItemNode(node)))
item->update();
@@ -632,7 +661,7 @@ void FormEditorView::instancesChildrenChanged(const QVector<ModelNode> &nodeList
{
QList<FormEditorItem*> changedItems;
foreach (const ModelNode &node, nodeList) {
for (const ModelNode &node : nodeList) {
const QmlItemNode qmlItemNode(node);
if (qmlItemNode.isValid()) {
if (FormEditorItem *item = scene()->itemForQmlItemNode(qmlItemNode)) {
@@ -702,7 +731,7 @@ QmlItemNode findRecursiveQmlItemNode(const QmlObjectNode &firstQmlObjectNode)
void FormEditorView::instancePropertyChanged(const QList<QPair<ModelNode, PropertyName> > &propertyList)
{
QList<FormEditorItem*> changedItems;
foreach (auto &nodePropertyPair, propertyList) {
for (auto &nodePropertyPair : propertyList) {
const QmlItemNode qmlItemNode(nodePropertyPair.first);
const PropertyName propertyName = nodePropertyPair.second;
if (qmlItemNode.isValid()) {

View File

@@ -76,7 +76,10 @@ public:
void selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
const QList<ModelNode> &lastSelectedNodeList) override;
void bindingPropertiesChanged(const QList<BindingProperty>& propertyList,
void variantPropertiesChanged(const QList<VariantProperty> &propertyList,
PropertyChangeFlags propertyChange) override;
void bindingPropertiesChanged(const QList<BindingProperty> &propertyList,
PropertyChangeFlags propertyChange) override;
void documentMessagesChanged(const QList<DocumentMessage> &errors, const QList<DocumentMessage> &warnings) override;

View File

@@ -600,6 +600,7 @@ void QmlFlowActionAreaNode::assignTargetFlowItem(const QmlFlowTargetNode &flowIt
QmlFlowItemNode QmlFlowActionAreaNode::flowItemParent() const
{
QTC_ASSERT(modelNode().hasParentProperty(), return QmlFlowItemNode({}));
return modelNode().parentProperty().parentModelNode();
}