QmlDesigner: Move the static function from ModeNode to ModelUtils

ModelNode is already quite big and there is no need add more utility
functions.

Change-Id: I5e81c320c4934fc452c05f21b3c878354f857424
Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Marco Bubke
2023-09-20 11:05:22 +02:00
parent 794cb89c2a
commit 53e2115f63
13 changed files with 150 additions and 140 deletions

View File

@@ -23,10 +23,11 @@
#include <formeditortoolbutton.h>
#include <documentmanager.h>
#include <qmldesignerplugin.h>
#include <viewmanager.h>
#include <actioneditor.h>
#include <documentmanager.h>
#include <model/modelutils.h>
#include <viewmanager.h>
#include <qmldesignerplugin.h>
#include <listmodeleditor/listmodeleditordialog.h>
#include <listmodeleditor/listmodeleditormodel.h>
@@ -419,7 +420,7 @@ public:
parentNode = selectionContext().currentSingleSelectedNode().parentProperty().parentModelNode();
if (!ModelNode::isThisOrAncestorLocked(parentNode)) {
if (!ModelUtils::isThisOrAncestorLocked(parentNode)) {
ActionTemplate *selectionAction = new ActionTemplate("SELECTION", {}, &ModelNodeOperations::select);
selectionAction->setParent(menu());
selectionAction->setText(QString(QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Parent")));
@@ -432,11 +433,9 @@ public:
}
}
for (const ModelNode &node : selectionContext().view()->allModelNodes()) {
if (node != selectionContext().currentSingleSelectedNode()
&& node != parentNode
&& contains(node, selectionContext().scenePosition())
&& !node.isRootNode()
&& !ModelNode::isThisOrAncestorLocked(node)) {
if (node != selectionContext().currentSingleSelectedNode() && node != parentNode
&& contains(node, selectionContext().scenePosition()) && !node.isRootNode()
&& !ModelUtils::isThisOrAncestorLocked(node)) {
selectionContext().setTargetNode(node);
QString what = QString(QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Select: %1")).arg(captionForModelNode(node));
ActionTemplate *selectionAction = new ActionTemplate("SELECT", what, &ModelNodeOperations::select);

View File

@@ -8,6 +8,7 @@
#include <bindingproperty.h>
#include <connectioneditorevaluator.h>
#include <exception.h>
#include <model/modelutils.h>
#include <nodeabstractproperty.h>
#include <nodelistproperty.h>
#include <nodemetainfo.h>
@@ -69,7 +70,7 @@ Qt::ItemFlags ConnectionModel::flags(const QModelIndex &modelIndex) const
const int internalId = data(index(modelIndex.row(), TargetModelNodeRow), UserRoles::InternalIdRole).toInt();
ModelNode modelNode = m_connectionView->modelNodeForInternalId(internalId);
if (modelNode.isValid() && ModelNode::isThisOrAncestorLocked(modelNode))
if (modelNode.isValid() && ModelUtils::isThisOrAncestorLocked(modelNode))
return Qt::ItemIsEnabled;
return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled;

View File

@@ -25,6 +25,7 @@
#include <designeractionmanager.h>
#include <designermcumanager.h>
#include <import.h>
#include <model/modelutils.h>
#include <nodeinstanceview.h>
#include <seekerslider.h>
@@ -44,7 +45,8 @@
namespace QmlDesigner {
static inline QIcon contextIcon(const DesignerIcons::IconId &iconId) {
inline static QIcon contextIcon(const DesignerIcons::IconId &iconId)
{
return DesignerActionManager::instance().contextIcon(iconId);
};
@@ -257,17 +259,16 @@ void Edit3DWidget::createContextMenu()
m_contextMenu->addSeparator();
m_selectParentAction = m_contextMenu->addAction(
contextIcon(DesignerIcons::ParentIcon),
tr("Select Parent"), [&] {
ModelNode parentNode = ModelNode::lowestCommonAncestor(view()->selectedModelNodes());
if (!parentNode.isValid())
return;
contextIcon(DesignerIcons::ParentIcon), tr("Select Parent"), [&] {
ModelNode parentNode = ModelUtils::lowestCommonAncestor(view()->selectedModelNodes());
if (!parentNode.isValid())
return;
if (!parentNode.isRootNode() && view()->isSelectedModelNode(parentNode))
parentNode = parentNode.parentProperty().parentModelNode();
if (!parentNode.isRootNode() && view()->isSelectedModelNode(parentNode))
parentNode = parentNode.parentProperty().parentModelNode();
view()->setSelectedModelNode(parentNode);
});
view()->setSelectedModelNode(parentNode);
});
QAction *defaultToggleGroupAction = view()->edit3DAction(View3DActionType::SelectionModeToggle)->action();
m_toggleGroupAction = m_contextMenu->addAction(
@@ -291,7 +292,7 @@ bool Edit3DWidget::isSceneLocked() const
{
if (m_view && m_view->hasModelNodeForInternalId(m_canvas->activeScene())) {
ModelNode node = m_view->modelNodeForInternalId(m_canvas->activeScene());
if (ModelNode::isThisOrAncestorLocked(node))
if (ModelUtils::isThisOrAncestorLocked(node))
return true;
}
return false;
@@ -525,7 +526,7 @@ void Edit3DWidget::dragEnterEvent(QDragEnterEvent *dragEnterEvent)
// Block all drags if scene root node is locked
if (m_view->hasModelNodeForInternalId(m_canvas->activeScene())) {
ModelNode node = m_view->modelNodeForInternalId(m_canvas->activeScene());
if (ModelNode::isThisOrAncestorLocked(node))
if (ModelUtils::isThisOrAncestorLocked(node))
return;
}

View File

@@ -9,6 +9,8 @@
#include "modelnodecontextmenu.h"
#include "qmldesignerconstants.h"
#include <model/modelutils.h>
#include <QDebug>
#include <QGraphicsSceneDragDropEvent>
#include <QMimeData>
@@ -180,7 +182,7 @@ FormEditorItem* AbstractFormEditorTool::nearestFormEditorItem(const QPointF &poi
if (formEditorItem->parentItem() && !formEditorItem->parentItem()->isContentVisible())
continue;
if (formEditorItem && ModelNode::isThisOrAncestorLocked(formEditorItem->qmlItemNode().modelNode()))
if (formEditorItem && ModelUtils::isThisOrAncestorLocked(formEditorItem->qmlItemNode().modelNode()))
continue;
if (!nearestItem)

View File

@@ -12,10 +12,11 @@
#include "qproxystyle.h"
#include <metainfo.h>
#include <model/modelutils.h>
#include <modelnodecontextmenu.h>
#include <theme.h>
#include <qmldesignerconstants.h>
#include <qmlobjectnode.h>
#include <theme.h>
#include <coreplugin/messagebox.h>
#include <utils/qtcassert.h>
@@ -212,7 +213,7 @@ void NameItemDelegate::paint(QPainter *painter,
}
ModelNode node = getModelNode(modelIndex);
if (!ModelNode::isThisOrAncestorLocked(node)) {
if (!ModelUtils::isThisOrAncestorLocked(node)) {
NavigatorWidget *widget = qobject_cast<NavigatorWidget *>(styleOption.widget->parent());
if (widget && !widget->dragType().isEmpty()) {
QByteArray dragType = widget->dragType();

View File

@@ -200,7 +200,7 @@ QVariant NavigatorTreeModel::data(const QModelIndex &index, int role) const
return m_view->isNodeInvisible(modelNode) ? Qt::Unchecked : Qt::Checked;
if (role == ItemOrAncestorLocked)
return ModelNode::isThisOrAncestorLocked(modelNode);
return ModelUtils::isThisOrAncestorLocked(modelNode);
if (role == ModelNodeRole)
return QVariant::fromValue<ModelNode>(modelNode);
@@ -273,13 +273,13 @@ Qt::ItemFlags NavigatorTreeModel::flags(const QModelIndex &index) const
if (index.column() == ColumnType::Alias
|| index.column() == ColumnType::Visibility
|| index.column() == ColumnType::Lock) {
if (ModelNode::isThisOrAncestorLocked(modelNode))
if (ModelUtils::isThisOrAncestorLocked(modelNode))
return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
else
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
}
if (ModelNode::isThisOrAncestorLocked(modelNode))
if (ModelUtils::isThisOrAncestorLocked(modelNode))
return Qt::NoItemFlags;
if (index.column() == ColumnType::Name)

View File

@@ -15,6 +15,7 @@
#include <qmltimeline.h>
#include <qmltimelinekeyframegroup.h>
#include <model/modelutils.h>
#include <rewritingexception.h>
#include <theme.h>
@@ -301,7 +302,7 @@ void TimelineSectionItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
if (event->button() == Qt::LeftButton) {
event->accept();
if (!ModelNode::isThisOrAncestorLocked(m_targetNode))
if (!ModelUtils::isThisOrAncestorLocked(m_targetNode))
toggleCollapsed();
}
}
@@ -334,7 +335,7 @@ void TimelineSectionItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
if (m_targetNode.isValid())
m_targetNode.view()->setSelectedModelNode(m_targetNode);
} else {
if (!ModelNode::isThisOrAncestorLocked(m_targetNode))
if (!ModelUtils::isThisOrAncestorLocked(m_targetNode))
toggleCollapsed();
}
update();

View File

@@ -13,6 +13,7 @@
#include <abstractview.h>
#include <bindingproperty.h>
#include <model/modelutils.h>
#include <variantproperty.h>
#include <qmltimeline.h>
#include <qmltimelinekeyframegroup.h>
@@ -349,7 +350,7 @@ void TransitionEditorSectionItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent
if (event->button() == Qt::LeftButton) {
event->accept();
if (!ModelNode::isThisOrAncestorLocked(m_targetNode))
if (!ModelUtils::isThisOrAncestorLocked(m_targetNode))
toggleCollapsed();
}
}
@@ -382,7 +383,7 @@ void TransitionEditorSectionItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *ev
if (m_targetNode.isValid())
m_targetNode.view()->setSelectedModelNode(m_targetNode);
} else {
if (!ModelNode::isThisOrAncestorLocked(m_targetNode))
if (!ModelUtils::isThisOrAncestorLocked(m_targetNode))
toggleCollapsed();
}
update();

View File

@@ -223,9 +223,6 @@ public:
bool locked() const;
void setLocked(bool value);
static bool isThisOrAncestorLocked(const ModelNode &node);
static ModelNode lowestCommonAncestor(const QList<ModelNode> &nodes);
qint32 internalId() const;
void setNodeSource(const QString&);

View File

@@ -8,12 +8,13 @@
#include "internalnode_p.h"
#include "model.h"
#include "model_p.h"
#include "modelutils.h"
#include "nodeinstanceview.h"
#include "nodelistproperty.h"
#include "nodemetainfo.h"
#include "qmldesignerconstants.h"
#include "qmlstate.h"
#include "qmltimeline.h"
#include "qmldesignerconstants.h"
#include "rewritertransaction.h"
#include "variantproperty.h"
@@ -412,7 +413,7 @@ void AbstractView::setSelectedModelNodes(const QList<ModelNode> &selectedNodeLis
QList<ModelNode> unlockedNodes;
for (const auto &modelNode : selectedNodeList) {
if (!ModelNode::isThisOrAncestorLocked(modelNode))
if (!ModelUtils::isThisOrAncestorLocked(modelNode))
unlockedNodes.push_back(modelNode);
}
@@ -421,7 +422,7 @@ void AbstractView::setSelectedModelNodes(const QList<ModelNode> &selectedNodeLis
void AbstractView::setSelectedModelNode(const ModelNode &modelNode)
{
if (ModelNode::isThisOrAncestorLocked(modelNode)) {
if (ModelUtils::isThisOrAncestorLocked(modelNode)) {
clearSelectedModelNodes();
return;
}

View File

@@ -1230,108 +1230,6 @@ void ModelNode::setLocked(bool value)
}
}
bool ModelNode::isThisOrAncestorLocked(const ModelNode &node)
{
if (!node.isValid())
return false;
if (node.locked())
return true;
if (node.isRootNode() || !node.hasParentProperty())
return false;
return isThisOrAncestorLocked(node.parentProperty().parentModelNode());
}
/*!
* \brief The lowest common ancestor node for node1 and node2. If one of the nodes (Node A) is
* the ancestor of the other node, the return value is Node A and not the parent of Node A.
* \param node1 First node
* \param node2 Second node
* \param depthOfLCA Depth of the return value
* \param depthOfNode1 Depth of node1. Use this parameter for optimization
* \param depthOfNode2 Depth of node2. Use this parameter for optimization
*/
static ModelNode lowestCommonAncestor(const ModelNode &node1,
const ModelNode &node2,
int &depthOfLCA,
const int &depthOfNode1 = -1,
const int &depthOfNode2 = -1)
{
Q_ASSERT(node1.isValid() && node2.isValid());
auto depthOfNode = [](const ModelNode &node) -> int {
int depth = 0;
ModelNode parentNode = node;
while (!parentNode.isRootNode()) {
depth++;
parentNode = parentNode.parentProperty().parentModelNode();
}
return depth;
};
if (node1 == node2) {
depthOfLCA = (depthOfNode1 < 0) ? ((depthOfNode2 < 0) ? depthOfNode(node1) : depthOfNode2)
: depthOfNode1;
return node1;
}
if (node1.isRootNode()) {
depthOfLCA = 0;
return node1;
}
if (node2.isRootNode()) {
depthOfLCA = 0;
return node2;
}
ModelNode nodeLower = node1;
ModelNode nodeHigher = node2;
int depthLower = (depthOfNode1 < 0) ? depthOfNode(nodeLower) : depthOfNode1;
int depthHigher = (depthOfNode2 < 0) ? depthOfNode(nodeHigher) : depthOfNode2;
if (depthLower > depthHigher) {
std::swap(depthLower, depthHigher);
std::swap(nodeLower, nodeHigher);
}
int depthDiff = depthHigher - depthLower;
while (depthDiff--)
nodeHigher = nodeHigher.parentProperty().parentModelNode();
while (nodeLower != nodeHigher) {
nodeLower = nodeLower.parentProperty().parentModelNode();
nodeHigher = nodeHigher.parentProperty().parentModelNode();
--depthLower;
}
depthOfLCA = depthLower;
return nodeLower;
}
/*!
* \brief The lowest common node containing all nodes. If one of the nodes (Node A) is
* the ancestor of the other nodes, the return value is Node A and not the parent of Node A.
*/
ModelNode ModelNode::lowestCommonAncestor(const QList<ModelNode> &nodes)
{
if (nodes.isEmpty())
return {};
ModelNode accumulatedNode = nodes.first();
int accumulatedNodeDepth = -1;
for (const ModelNode &node : Utils::span<const ModelNode>(nodes).subspan(1)) {
accumulatedNode = QmlDesigner::lowestCommonAncestor(accumulatedNode,
node,
accumulatedNodeDepth,
accumulatedNodeDepth);
}
return accumulatedNode;
}
void ModelNode::setScriptFunctions(const QStringList &scriptFunctionList)
{
if (!isValid())

View File

@@ -4,6 +4,7 @@
#include "modelutils.h"
#include <abstractview.h>
#include <nodeabstractproperty.h>
#include <nodemetainfo.h>
#include <projectstorage/projectstorage.h>
#include <projectstorage/sourcepathcache.h>
@@ -162,4 +163,108 @@ QList<ModelNode> allModelNodesWithId(AbstractView *view)
[&](const ModelNode &node) { return node.hasId(); });
}
bool isThisOrAncestorLocked(const ModelNode &node)
{
if (!node.isValid())
return false;
if (node.locked())
return true;
if (node.isRootNode() || !node.hasParentProperty())
return false;
return isThisOrAncestorLocked(node.parentProperty().parentModelNode());
}
/*!
* \brief The lowest common ancestor node for node1 and node2. If one of the nodes (Node A) is
* the ancestor of the other node, the return value is Node A and not the parent of Node A.
* \param node1 First node
* \param node2 Second node
* \param depthOfLCA Depth of the return value
* \param depthOfNode1 Depth of node1. Use this parameter for optimization
* \param depthOfNode2 Depth of node2. Use this parameter for optimization
*/
namespace {
ModelNode lowestCommonAncestor(const ModelNode &node1,
const ModelNode &node2,
int &depthOfLCA,
const int &depthOfNode1 = -1,
const int &depthOfNode2 = -1)
{
Q_ASSERT(node1.isValid() && node2.isValid());
auto depthOfNode = [](const ModelNode &node) -> int {
int depth = 0;
ModelNode parentNode = node;
while (!parentNode.isRootNode()) {
depth++;
parentNode = parentNode.parentProperty().parentModelNode();
}
return depth;
};
if (node1 == node2) {
depthOfLCA = (depthOfNode1 < 0) ? ((depthOfNode2 < 0) ? depthOfNode(node1) : depthOfNode2)
: depthOfNode1;
return node1;
}
if (node1.isRootNode()) {
depthOfLCA = 0;
return node1;
}
if (node2.isRootNode()) {
depthOfLCA = 0;
return node2;
}
ModelNode nodeLower = node1;
ModelNode nodeHigher = node2;
int depthLower = (depthOfNode1 < 0) ? depthOfNode(nodeLower) : depthOfNode1;
int depthHigher = (depthOfNode2 < 0) ? depthOfNode(nodeHigher) : depthOfNode2;
if (depthLower > depthHigher) {
std::swap(depthLower, depthHigher);
std::swap(nodeLower, nodeHigher);
}
int depthDiff = depthHigher - depthLower;
while (depthDiff--)
nodeHigher = nodeHigher.parentProperty().parentModelNode();
while (nodeLower != nodeHigher) {
nodeLower = nodeLower.parentProperty().parentModelNode();
nodeHigher = nodeHigher.parentProperty().parentModelNode();
--depthLower;
}
depthOfLCA = depthLower;
return nodeLower;
}
} // namespace
/*!
* \brief The lowest common node containing all nodes. If one of the nodes (Node A) is
* the ancestor of the other nodes, the return value is Node A and not the parent of Node A.
*/
ModelNode lowestCommonAncestor(const QList<ModelNode> &nodes)
{
if (nodes.isEmpty())
return {};
ModelNode accumulatedNode = nodes.first();
int accumulatedNodeDepth = -1;
for (const ModelNode &node : Utils::span<const ModelNode>(nodes).subspan(1)) {
accumulatedNode = lowestCommonAncestor(accumulatedNode,
node,
accumulatedNodeDepth,
accumulatedNodeDepth);
}
return accumulatedNode;
}
} // namespace QmlDesigner::ModelUtils

View File

@@ -38,4 +38,7 @@ QMLDESIGNERCORE_EXPORT QList<ModelNode> pruneChildren(const QList<ModelNode> &no
QMLDESIGNERCORE_EXPORT QList<ModelNode> allModelNodesWithId(AbstractView *view);
QMLDESIGNERCORE_EXPORT bool isThisOrAncestorLocked(const ModelNode &node);
QMLDESIGNERCORE_EXPORT ModelNode lowestCommonAncestor(const QList<ModelNode> &nodes);
} // namespace QmlDesigner::ModelUtils