forked from qt-creator/qt-creator
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:
@@ -23,10 +23,11 @@
|
|||||||
|
|
||||||
#include <formeditortoolbutton.h>
|
#include <formeditortoolbutton.h>
|
||||||
|
|
||||||
#include <documentmanager.h>
|
|
||||||
#include <qmldesignerplugin.h>
|
|
||||||
#include <viewmanager.h>
|
|
||||||
#include <actioneditor.h>
|
#include <actioneditor.h>
|
||||||
|
#include <documentmanager.h>
|
||||||
|
#include <model/modelutils.h>
|
||||||
|
#include <viewmanager.h>
|
||||||
|
#include <qmldesignerplugin.h>
|
||||||
|
|
||||||
#include <listmodeleditor/listmodeleditordialog.h>
|
#include <listmodeleditor/listmodeleditordialog.h>
|
||||||
#include <listmodeleditor/listmodeleditormodel.h>
|
#include <listmodeleditor/listmodeleditormodel.h>
|
||||||
@@ -419,7 +420,7 @@ public:
|
|||||||
|
|
||||||
parentNode = selectionContext().currentSingleSelectedNode().parentProperty().parentModelNode();
|
parentNode = selectionContext().currentSingleSelectedNode().parentProperty().parentModelNode();
|
||||||
|
|
||||||
if (!ModelNode::isThisOrAncestorLocked(parentNode)) {
|
if (!ModelUtils::isThisOrAncestorLocked(parentNode)) {
|
||||||
ActionTemplate *selectionAction = new ActionTemplate("SELECTION", {}, &ModelNodeOperations::select);
|
ActionTemplate *selectionAction = new ActionTemplate("SELECTION", {}, &ModelNodeOperations::select);
|
||||||
selectionAction->setParent(menu());
|
selectionAction->setParent(menu());
|
||||||
selectionAction->setText(QString(QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Parent")));
|
selectionAction->setText(QString(QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Parent")));
|
||||||
@@ -432,11 +433,9 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const ModelNode &node : selectionContext().view()->allModelNodes()) {
|
for (const ModelNode &node : selectionContext().view()->allModelNodes()) {
|
||||||
if (node != selectionContext().currentSingleSelectedNode()
|
if (node != selectionContext().currentSingleSelectedNode() && node != parentNode
|
||||||
&& node != parentNode
|
&& contains(node, selectionContext().scenePosition()) && !node.isRootNode()
|
||||||
&& contains(node, selectionContext().scenePosition())
|
&& !ModelUtils::isThisOrAncestorLocked(node)) {
|
||||||
&& !node.isRootNode()
|
|
||||||
&& !ModelNode::isThisOrAncestorLocked(node)) {
|
|
||||||
selectionContext().setTargetNode(node);
|
selectionContext().setTargetNode(node);
|
||||||
QString what = QString(QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Select: %1")).arg(captionForModelNode(node));
|
QString what = QString(QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Select: %1")).arg(captionForModelNode(node));
|
||||||
ActionTemplate *selectionAction = new ActionTemplate("SELECT", what, &ModelNodeOperations::select);
|
ActionTemplate *selectionAction = new ActionTemplate("SELECT", what, &ModelNodeOperations::select);
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
#include <bindingproperty.h>
|
#include <bindingproperty.h>
|
||||||
#include <connectioneditorevaluator.h>
|
#include <connectioneditorevaluator.h>
|
||||||
#include <exception.h>
|
#include <exception.h>
|
||||||
|
#include <model/modelutils.h>
|
||||||
#include <nodeabstractproperty.h>
|
#include <nodeabstractproperty.h>
|
||||||
#include <nodelistproperty.h>
|
#include <nodelistproperty.h>
|
||||||
#include <nodemetainfo.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();
|
const int internalId = data(index(modelIndex.row(), TargetModelNodeRow), UserRoles::InternalIdRole).toInt();
|
||||||
ModelNode modelNode = m_connectionView->modelNodeForInternalId(internalId);
|
ModelNode modelNode = m_connectionView->modelNodeForInternalId(internalId);
|
||||||
|
|
||||||
if (modelNode.isValid() && ModelNode::isThisOrAncestorLocked(modelNode))
|
if (modelNode.isValid() && ModelUtils::isThisOrAncestorLocked(modelNode))
|
||||||
return Qt::ItemIsEnabled;
|
return Qt::ItemIsEnabled;
|
||||||
|
|
||||||
return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled;
|
return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled;
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
#include <designeractionmanager.h>
|
#include <designeractionmanager.h>
|
||||||
#include <designermcumanager.h>
|
#include <designermcumanager.h>
|
||||||
#include <import.h>
|
#include <import.h>
|
||||||
|
#include <model/modelutils.h>
|
||||||
#include <nodeinstanceview.h>
|
#include <nodeinstanceview.h>
|
||||||
#include <seekerslider.h>
|
#include <seekerslider.h>
|
||||||
|
|
||||||
@@ -44,7 +45,8 @@
|
|||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
static inline QIcon contextIcon(const DesignerIcons::IconId &iconId) {
|
inline static QIcon contextIcon(const DesignerIcons::IconId &iconId)
|
||||||
|
{
|
||||||
return DesignerActionManager::instance().contextIcon(iconId);
|
return DesignerActionManager::instance().contextIcon(iconId);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -257,9 +259,8 @@ void Edit3DWidget::createContextMenu()
|
|||||||
m_contextMenu->addSeparator();
|
m_contextMenu->addSeparator();
|
||||||
|
|
||||||
m_selectParentAction = m_contextMenu->addAction(
|
m_selectParentAction = m_contextMenu->addAction(
|
||||||
contextIcon(DesignerIcons::ParentIcon),
|
contextIcon(DesignerIcons::ParentIcon), tr("Select Parent"), [&] {
|
||||||
tr("Select Parent"), [&] {
|
ModelNode parentNode = ModelUtils::lowestCommonAncestor(view()->selectedModelNodes());
|
||||||
ModelNode parentNode = ModelNode::lowestCommonAncestor(view()->selectedModelNodes());
|
|
||||||
if (!parentNode.isValid())
|
if (!parentNode.isValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -291,7 +292,7 @@ bool Edit3DWidget::isSceneLocked() const
|
|||||||
{
|
{
|
||||||
if (m_view && m_view->hasModelNodeForInternalId(m_canvas->activeScene())) {
|
if (m_view && m_view->hasModelNodeForInternalId(m_canvas->activeScene())) {
|
||||||
ModelNode node = m_view->modelNodeForInternalId(m_canvas->activeScene());
|
ModelNode node = m_view->modelNodeForInternalId(m_canvas->activeScene());
|
||||||
if (ModelNode::isThisOrAncestorLocked(node))
|
if (ModelUtils::isThisOrAncestorLocked(node))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -525,7 +526,7 @@ void Edit3DWidget::dragEnterEvent(QDragEnterEvent *dragEnterEvent)
|
|||||||
// Block all drags if scene root node is locked
|
// Block all drags if scene root node is locked
|
||||||
if (m_view->hasModelNodeForInternalId(m_canvas->activeScene())) {
|
if (m_view->hasModelNodeForInternalId(m_canvas->activeScene())) {
|
||||||
ModelNode node = m_view->modelNodeForInternalId(m_canvas->activeScene());
|
ModelNode node = m_view->modelNodeForInternalId(m_canvas->activeScene());
|
||||||
if (ModelNode::isThisOrAncestorLocked(node))
|
if (ModelUtils::isThisOrAncestorLocked(node))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,6 +9,8 @@
|
|||||||
#include "modelnodecontextmenu.h"
|
#include "modelnodecontextmenu.h"
|
||||||
#include "qmldesignerconstants.h"
|
#include "qmldesignerconstants.h"
|
||||||
|
|
||||||
|
#include <model/modelutils.h>
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QGraphicsSceneDragDropEvent>
|
#include <QGraphicsSceneDragDropEvent>
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
@@ -180,7 +182,7 @@ FormEditorItem* AbstractFormEditorTool::nearestFormEditorItem(const QPointF &poi
|
|||||||
if (formEditorItem->parentItem() && !formEditorItem->parentItem()->isContentVisible())
|
if (formEditorItem->parentItem() && !formEditorItem->parentItem()->isContentVisible())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (formEditorItem && ModelNode::isThisOrAncestorLocked(formEditorItem->qmlItemNode().modelNode()))
|
if (formEditorItem && ModelUtils::isThisOrAncestorLocked(formEditorItem->qmlItemNode().modelNode()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!nearestItem)
|
if (!nearestItem)
|
||||||
|
@@ -12,10 +12,11 @@
|
|||||||
#include "qproxystyle.h"
|
#include "qproxystyle.h"
|
||||||
|
|
||||||
#include <metainfo.h>
|
#include <metainfo.h>
|
||||||
|
#include <model/modelutils.h>
|
||||||
#include <modelnodecontextmenu.h>
|
#include <modelnodecontextmenu.h>
|
||||||
|
#include <theme.h>
|
||||||
#include <qmldesignerconstants.h>
|
#include <qmldesignerconstants.h>
|
||||||
#include <qmlobjectnode.h>
|
#include <qmlobjectnode.h>
|
||||||
#include <theme.h>
|
|
||||||
|
|
||||||
#include <coreplugin/messagebox.h>
|
#include <coreplugin/messagebox.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
@@ -212,7 +213,7 @@ void NameItemDelegate::paint(QPainter *painter,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ModelNode node = getModelNode(modelIndex);
|
ModelNode node = getModelNode(modelIndex);
|
||||||
if (!ModelNode::isThisOrAncestorLocked(node)) {
|
if (!ModelUtils::isThisOrAncestorLocked(node)) {
|
||||||
NavigatorWidget *widget = qobject_cast<NavigatorWidget *>(styleOption.widget->parent());
|
NavigatorWidget *widget = qobject_cast<NavigatorWidget *>(styleOption.widget->parent());
|
||||||
if (widget && !widget->dragType().isEmpty()) {
|
if (widget && !widget->dragType().isEmpty()) {
|
||||||
QByteArray dragType = widget->dragType();
|
QByteArray dragType = widget->dragType();
|
||||||
|
@@ -200,7 +200,7 @@ QVariant NavigatorTreeModel::data(const QModelIndex &index, int role) const
|
|||||||
return m_view->isNodeInvisible(modelNode) ? Qt::Unchecked : Qt::Checked;
|
return m_view->isNodeInvisible(modelNode) ? Qt::Unchecked : Qt::Checked;
|
||||||
|
|
||||||
if (role == ItemOrAncestorLocked)
|
if (role == ItemOrAncestorLocked)
|
||||||
return ModelNode::isThisOrAncestorLocked(modelNode);
|
return ModelUtils::isThisOrAncestorLocked(modelNode);
|
||||||
|
|
||||||
if (role == ModelNodeRole)
|
if (role == ModelNodeRole)
|
||||||
return QVariant::fromValue<ModelNode>(modelNode);
|
return QVariant::fromValue<ModelNode>(modelNode);
|
||||||
@@ -273,13 +273,13 @@ Qt::ItemFlags NavigatorTreeModel::flags(const QModelIndex &index) const
|
|||||||
if (index.column() == ColumnType::Alias
|
if (index.column() == ColumnType::Alias
|
||||||
|| index.column() == ColumnType::Visibility
|
|| index.column() == ColumnType::Visibility
|
||||||
|| index.column() == ColumnType::Lock) {
|
|| index.column() == ColumnType::Lock) {
|
||||||
if (ModelNode::isThisOrAncestorLocked(modelNode))
|
if (ModelUtils::isThisOrAncestorLocked(modelNode))
|
||||||
return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
|
return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
|
||||||
else
|
else
|
||||||
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
|
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ModelNode::isThisOrAncestorLocked(modelNode))
|
if (ModelUtils::isThisOrAncestorLocked(modelNode))
|
||||||
return Qt::NoItemFlags;
|
return Qt::NoItemFlags;
|
||||||
|
|
||||||
if (index.column() == ColumnType::Name)
|
if (index.column() == ColumnType::Name)
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
#include <qmltimeline.h>
|
#include <qmltimeline.h>
|
||||||
#include <qmltimelinekeyframegroup.h>
|
#include <qmltimelinekeyframegroup.h>
|
||||||
|
|
||||||
|
#include <model/modelutils.h>
|
||||||
#include <rewritingexception.h>
|
#include <rewritingexception.h>
|
||||||
|
|
||||||
#include <theme.h>
|
#include <theme.h>
|
||||||
@@ -301,7 +302,7 @@ void TimelineSectionItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
|
|
||||||
if (event->button() == Qt::LeftButton) {
|
if (event->button() == Qt::LeftButton) {
|
||||||
event->accept();
|
event->accept();
|
||||||
if (!ModelNode::isThisOrAncestorLocked(m_targetNode))
|
if (!ModelUtils::isThisOrAncestorLocked(m_targetNode))
|
||||||
toggleCollapsed();
|
toggleCollapsed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -334,7 +335,7 @@ void TimelineSectionItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
if (m_targetNode.isValid())
|
if (m_targetNode.isValid())
|
||||||
m_targetNode.view()->setSelectedModelNode(m_targetNode);
|
m_targetNode.view()->setSelectedModelNode(m_targetNode);
|
||||||
} else {
|
} else {
|
||||||
if (!ModelNode::isThisOrAncestorLocked(m_targetNode))
|
if (!ModelUtils::isThisOrAncestorLocked(m_targetNode))
|
||||||
toggleCollapsed();
|
toggleCollapsed();
|
||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <abstractview.h>
|
#include <abstractview.h>
|
||||||
#include <bindingproperty.h>
|
#include <bindingproperty.h>
|
||||||
|
#include <model/modelutils.h>
|
||||||
#include <variantproperty.h>
|
#include <variantproperty.h>
|
||||||
#include <qmltimeline.h>
|
#include <qmltimeline.h>
|
||||||
#include <qmltimelinekeyframegroup.h>
|
#include <qmltimelinekeyframegroup.h>
|
||||||
@@ -349,7 +350,7 @@ void TransitionEditorSectionItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent
|
|||||||
|
|
||||||
if (event->button() == Qt::LeftButton) {
|
if (event->button() == Qt::LeftButton) {
|
||||||
event->accept();
|
event->accept();
|
||||||
if (!ModelNode::isThisOrAncestorLocked(m_targetNode))
|
if (!ModelUtils::isThisOrAncestorLocked(m_targetNode))
|
||||||
toggleCollapsed();
|
toggleCollapsed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -382,7 +383,7 @@ void TransitionEditorSectionItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *ev
|
|||||||
if (m_targetNode.isValid())
|
if (m_targetNode.isValid())
|
||||||
m_targetNode.view()->setSelectedModelNode(m_targetNode);
|
m_targetNode.view()->setSelectedModelNode(m_targetNode);
|
||||||
} else {
|
} else {
|
||||||
if (!ModelNode::isThisOrAncestorLocked(m_targetNode))
|
if (!ModelUtils::isThisOrAncestorLocked(m_targetNode))
|
||||||
toggleCollapsed();
|
toggleCollapsed();
|
||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
|
@@ -223,9 +223,6 @@ public:
|
|||||||
bool locked() const;
|
bool locked() const;
|
||||||
void setLocked(bool value);
|
void setLocked(bool value);
|
||||||
|
|
||||||
static bool isThisOrAncestorLocked(const ModelNode &node);
|
|
||||||
static ModelNode lowestCommonAncestor(const QList<ModelNode> &nodes);
|
|
||||||
|
|
||||||
qint32 internalId() const;
|
qint32 internalId() const;
|
||||||
|
|
||||||
void setNodeSource(const QString&);
|
void setNodeSource(const QString&);
|
||||||
|
@@ -8,12 +8,13 @@
|
|||||||
#include "internalnode_p.h"
|
#include "internalnode_p.h"
|
||||||
#include "model.h"
|
#include "model.h"
|
||||||
#include "model_p.h"
|
#include "model_p.h"
|
||||||
|
#include "modelutils.h"
|
||||||
#include "nodeinstanceview.h"
|
#include "nodeinstanceview.h"
|
||||||
#include "nodelistproperty.h"
|
#include "nodelistproperty.h"
|
||||||
#include "nodemetainfo.h"
|
#include "nodemetainfo.h"
|
||||||
|
#include "qmldesignerconstants.h"
|
||||||
#include "qmlstate.h"
|
#include "qmlstate.h"
|
||||||
#include "qmltimeline.h"
|
#include "qmltimeline.h"
|
||||||
#include "qmldesignerconstants.h"
|
|
||||||
#include "rewritertransaction.h"
|
#include "rewritertransaction.h"
|
||||||
#include "variantproperty.h"
|
#include "variantproperty.h"
|
||||||
|
|
||||||
@@ -412,7 +413,7 @@ void AbstractView::setSelectedModelNodes(const QList<ModelNode> &selectedNodeLis
|
|||||||
QList<ModelNode> unlockedNodes;
|
QList<ModelNode> unlockedNodes;
|
||||||
|
|
||||||
for (const auto &modelNode : selectedNodeList) {
|
for (const auto &modelNode : selectedNodeList) {
|
||||||
if (!ModelNode::isThisOrAncestorLocked(modelNode))
|
if (!ModelUtils::isThisOrAncestorLocked(modelNode))
|
||||||
unlockedNodes.push_back(modelNode);
|
unlockedNodes.push_back(modelNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,7 +422,7 @@ void AbstractView::setSelectedModelNodes(const QList<ModelNode> &selectedNodeLis
|
|||||||
|
|
||||||
void AbstractView::setSelectedModelNode(const ModelNode &modelNode)
|
void AbstractView::setSelectedModelNode(const ModelNode &modelNode)
|
||||||
{
|
{
|
||||||
if (ModelNode::isThisOrAncestorLocked(modelNode)) {
|
if (ModelUtils::isThisOrAncestorLocked(modelNode)) {
|
||||||
clearSelectedModelNodes();
|
clearSelectedModelNodes();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
void ModelNode::setScriptFunctions(const QStringList &scriptFunctionList)
|
||||||
{
|
{
|
||||||
if (!isValid())
|
if (!isValid())
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include "modelutils.h"
|
#include "modelutils.h"
|
||||||
|
|
||||||
#include <abstractview.h>
|
#include <abstractview.h>
|
||||||
|
#include <nodeabstractproperty.h>
|
||||||
#include <nodemetainfo.h>
|
#include <nodemetainfo.h>
|
||||||
#include <projectstorage/projectstorage.h>
|
#include <projectstorage/projectstorage.h>
|
||||||
#include <projectstorage/sourcepathcache.h>
|
#include <projectstorage/sourcepathcache.h>
|
||||||
@@ -162,4 +163,108 @@ QList<ModelNode> allModelNodesWithId(AbstractView *view)
|
|||||||
[&](const ModelNode &node) { return node.hasId(); });
|
[&](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
|
} // namespace QmlDesigner::ModelUtils
|
||||||
|
@@ -38,4 +38,7 @@ QMLDESIGNERCORE_EXPORT QList<ModelNode> pruneChildren(const QList<ModelNode> &no
|
|||||||
|
|
||||||
QMLDESIGNERCORE_EXPORT QList<ModelNode> allModelNodesWithId(AbstractView *view);
|
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
|
} // namespace QmlDesigner::ModelUtils
|
||||||
|
Reference in New Issue
Block a user