QmlDesigner: Add support for Component type

Component type is added to Component Library and can be dragged to
the scene. Items under the component are not shown in the scene.

Fixes: QDS-5093
Change-Id: I0c80647e73124866a8b772022a761ca6cbb545a1
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Miikka Heikkinen
2021-09-24 15:49:49 +03:00
parent 9e5744b1f3
commit e0611c0cfa
9 changed files with 70 additions and 40 deletions

View File

@@ -617,7 +617,6 @@ class UnsupportedTypesByQmlUi : public QStringList
{ {
public: public:
UnsupportedTypesByQmlUi() : QStringList({"ShaderEffect", UnsupportedTypesByQmlUi() : QStringList({"ShaderEffect",
"Component",
"Drawer"}) "Drawer"})
{ {
append(UnsupportedTypesByVisualDesigner()); append(UnsupportedTypesByVisualDesigner());

View File

@@ -99,8 +99,7 @@ FormEditorItem::FormEditorItem(const QmlItemNode &qmlItemNode, FormEditorScene*
m_borderWidth(1.0), m_borderWidth(1.0),
m_highlightBoundingRect(false), m_highlightBoundingRect(false),
m_blurContent(false), m_blurContent(false),
m_isContentVisible(true), m_isContentVisible(true)
m_isFormEditorVisible(true)
{ {
setCacheMode(QGraphicsItem::NoCache); setCacheMode(QGraphicsItem::NoCache);
setup(); setup();
@@ -208,17 +207,6 @@ bool FormEditorItem::isContentVisible() const
return m_isContentVisible; return m_isContentVisible;
} }
bool FormEditorItem::isFormEditorVisible() const
{
return m_isFormEditorVisible;
}
void FormEditorItem::setFormEditorVisible(bool isVisible)
{
m_isFormEditorVisible = isVisible;
setVisible(isVisible);
}
QPointF FormEditorItem::center() const QPointF FormEditorItem::center() const
{ {
return mapToScene(qmlItemNode().instanceBoundingRect().center()); return mapToScene(qmlItemNode().instanceBoundingRect().center());

View File

@@ -104,9 +104,6 @@ public:
void setContentVisible(bool visible); void setContentVisible(bool visible);
bool isContentVisible() const; bool isContentVisible() const;
bool isFormEditorVisible() const;
void setFormEditorVisible(bool isVisible);
QPointF center() const; QPointF center() const;
qreal selectionWeigth(const QPointF &point, int iteration); qreal selectionWeigth(const QPointF &point, int iteration);
@@ -152,7 +149,6 @@ private: // variables
bool m_highlightBoundingRect; bool m_highlightBoundingRect;
bool m_blurContent; bool m_blurContent;
bool m_isContentVisible; bool m_isContentVisible;
bool m_isFormEditorVisible;
}; };
class FormEditorFlowItem : public FormEditorItem class FormEditorFlowItem : public FormEditorItem

View File

@@ -199,16 +199,6 @@ void FormEditorView::removeNodeFromScene(const QmlItemNode &qmlItemNode)
m_currentTool->itemsAboutToRemoved(removedItemList); m_currentTool->itemsAboutToRemoved(removedItemList);
} }
void FormEditorView::hideNodeFromScene(const QmlItemNode &qmlItemNode)
{
if (FormEditorItem *item = m_scene->itemForQmlItemNode(qmlItemNode)) {
QList<FormEditorItem*> removedItems = scene()->itemsForQmlItemNodes(qmlItemNode.allSubModelNodes());
removedItems.append(item);
m_currentTool->itemsAboutToRemoved(removedItems);
item->setFormEditorVisible(false);
}
}
void FormEditorView::createFormEditorWidget() void FormEditorView::createFormEditorWidget()
{ {
m_formEditorWidget = QPointer<FormEditorWidget>(new FormEditorWidget(this)); m_formEditorWidget = QPointer<FormEditorWidget>(new FormEditorWidget(this));
@@ -248,10 +238,7 @@ void FormEditorView::temporaryBlockView(int duration)
void FormEditorView::nodeCreated(const ModelNode &node) void FormEditorView::nodeCreated(const ModelNode &node)
{ {
//If the node has source for components/custom parsers we ignore it. if (QmlVisualNode::isFlowTransition(node))
if (QmlItemNode::isValidQmlItemNode(node) && node.nodeSourceType() == ModelNode::NodeWithoutSource) //only setup QmlItems
setupFormEditorItemTree(QmlItemNode(node));
else if (QmlVisualNode::isFlowTransition(node))
setupFormEditorItemTree(QmlItemNode(node)); setupFormEditorItemTree(QmlItemNode(node));
} }
@@ -349,8 +336,26 @@ static inline bool hasNodeSourceParent(const ModelNode &node)
void FormEditorView::nodeReparented(const ModelNode &node, const NodeAbstractProperty &/*newPropertyParent*/, const NodeAbstractProperty &/*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/) void FormEditorView::nodeReparented(const ModelNode &node, const NodeAbstractProperty &/*newPropertyParent*/, const NodeAbstractProperty &/*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/)
{ {
if (hasNodeSourceParent(node)) // If node is not connected to scene root, don't do anything yet to avoid duplicated effort,
hideNodeFromScene(node); // as any removal or addition will remove or add descendants as well.
if (!node.isInHierarchy())
return;
QmlItemNode itemNode(node);
if (hasNodeSourceParent(node)) {
if (FormEditorItem *item = m_scene->itemForQmlItemNode(itemNode)) {
QList<FormEditorItem *> removed = scene()->itemsForQmlItemNodes(itemNode.allSubModelNodes());
removed.append(item);
m_currentTool->itemsAboutToRemoved(removed);
removeNodeFromScene(itemNode);
}
} else if (itemNode.isValid() && node.nodeSourceType() == ModelNode::NodeWithoutSource) {
if (!m_scene->itemForQmlItemNode(itemNode)) {
setupFormEditorItemTree(itemNode);
// Simulate selection change to refresh tools
selectedNodesChanged(selectedModelNodes(), {});
}
}
} }
WidgetInfo FormEditorView::widgetInfo() WidgetInfo FormEditorView::widgetInfo()
@@ -603,8 +608,7 @@ void FormEditorView::auxiliaryDataChanged(const ModelNode &node, const PropertyN
if (name == "invisible") { if (name == "invisible") {
if (FormEditorItem *item = scene()->itemForQmlItemNode(QmlItemNode(node))) { if (FormEditorItem *item = scene()->itemForQmlItemNode(QmlItemNode(node))) {
bool isInvisible = data.toBool(); bool isInvisible = data.toBool();
if (item->isFormEditorVisible()) item->setVisible(!isInvisible);
item->setVisible(!isInvisible);
ModelNode newNode(node); ModelNode newNode(node);
if (isInvisible) if (isInvisible)
newNode.deselectNode(); newNode.deselectNode();

View File

@@ -144,7 +144,6 @@ protected:
private: private:
void setupFormEditorItemTree(const QmlItemNode &qmlItemNode); void setupFormEditorItemTree(const QmlItemNode &qmlItemNode);
void removeNodeFromScene(const QmlItemNode &qmlItemNode); void removeNodeFromScene(const QmlItemNode &qmlItemNode);
void hideNodeFromScene(const QmlItemNode &qmlItemNode);
void createFormEditorWidget(); void createFormEditorWidget();
void temporaryBlockView(int duration = 1000); void temporaryBlockView(int duration = 1000);
void resetNodeInstanceView(); void resetNodeInstanceView();

View File

@@ -34,6 +34,8 @@
#include <nodemetainfo.h> #include <nodemetainfo.h>
#include <utils/algorithm.h>
#include <QGraphicsSceneMouseEvent> #include <QGraphicsSceneMouseEvent>
#include <QDebug> #include <QDebug>
@@ -242,9 +244,23 @@ void SelectionTool::dragMoveEvent(const QList<QGraphicsItem*> &/*itemList*/, QGr
{ {
} }
void SelectionTool::itemsAboutToRemoved(const QList<FormEditorItem*> &/*itemList*/) void SelectionTool::itemsAboutToRemoved(const QList<FormEditorItem*> &itemList)
{ {
const QList<FormEditorItem *> current = items();
QList<FormEditorItem *> remaining = Utils::filtered(current, [&itemList](const FormEditorItem *item) {
return !itemList.contains(item);
});
if (!remaining.isEmpty()) {
m_selectionIndicator.setItems(remaining);
m_resizeIndicator.setItems(remaining);
m_rotationIndicator.setItems(remaining);
m_anchorIndicator.setItems(remaining);
m_bindingIndicator.setItems(remaining);
} else {
clear();
}
} }
void SelectionTool::clear() void SelectionTool::clear()

View File

@@ -1085,10 +1085,18 @@ void NavigatorTreeModel::moveNodesInteractive(NodeAbstractProperty &parentProper
if (modelNode.isValid() if (modelNode.isValid()
&& modelNode != parentProperty.parentModelNode() && modelNode != parentProperty.parentModelNode()
&& !modelNode.isAncestorOf(parentProperty.parentModelNode()) && !modelNode.isAncestorOf(parentProperty.parentModelNode())
&& (modelNode.metaInfo().isSubclassOf(propertyQmlType) || propertyQmlType == "alias")) { && (modelNode.metaInfo().isSubclassOf(propertyQmlType)
|| propertyQmlType == "alias"
|| parentProperty.name() == "data")) {
//### todo: allowing alias is just a heuristic //### todo: allowing alias is just a heuristic
//once the MetaInfo is part of instances we can do this right //once the MetaInfo is part of instances we can do this right
// We assume above that "data" property in parent accepts all types.
// This is a workaround for Component parents to accept children, even though they
// do not have an actual "data" property or apparently any other default property.
// When the actual reparenting happens, model will create the "data" property if
// it is missing.
bool nodeCanBeMovedToParentProperty = removeModelNodeFromNodeProperty(parentProperty, modelNode); bool nodeCanBeMovedToParentProperty = removeModelNodeFromNodeProperty(parentProperty, modelNode);
if (nodeCanBeMovedToParentProperty) { if (nodeCanBeMovedToParentProperty) {
reparentModelNodeToNodeProperty(parentProperty, modelNode); reparentModelNodeToNodeProperty(parentProperty, modelNode);

View File

@@ -309,7 +309,11 @@ QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view,
} }
} }
newQmlObjectNode = QmlObjectNode(view->createModelNode(itemLibraryEntry.typeName(), majorVersion, minorVersion, propertyPairList)); ModelNode::NodeSourceType nodeSourceType = ModelNode::NodeWithoutSource;
if (itemLibraryEntry.typeName() == "QtQml.Component")
nodeSourceType = ModelNode::NodeWithComponentSource;
newQmlObjectNode = QmlObjectNode(view->createModelNode(itemLibraryEntry.typeName(), majorVersion, minorVersion, propertyPairList, {}, {}, nodeSourceType));
} else { } else {
newQmlObjectNode = createQmlObjectNodeFromSource(view, itemLibraryEntry.qmlSource(), position); newQmlObjectNode = createQmlObjectNodeFromSource(view, itemLibraryEntry.qmlSource(), position);
} }

View File

@@ -432,4 +432,20 @@ MetaInfo {
} }
} }
Type {
name: "QtQml.Component"
icon: ":/qtquickplugin/images/item-icon16.png"
Hints {
canBeDroppedInNavigator: true
canBeDroppedInFormEditor: false
}
ItemLibraryEntry {
name: "Component"
category: "e.Qt Quick - Component"
libraryIcon: ":/qtquickplugin/images/item-icon.png"
version: "2.0"
}
}
} }