aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/qmldesigner/designercore/model/modelnodecontextmenu.cpp
diff options
context:
space:
mode:
authorThomas Hartmann <Thomas.Hartmann@nokia.com>2011-06-27 17:53:36 +0200
committerThomas Hartmann <Thomas.Hartmann@nokia.com>2011-06-27 17:54:13 +0200
commitdde8ef0c711f6784107a97ae6e8b34f7530c6d24 (patch)
tree13dd23ac07511fdd5a8e966b6204187ec8af748c /src/plugins/qmldesigner/designercore/model/modelnodecontextmenu.cpp
parent51d5e232cf5b79782dac6b88c1ce938e2a11e6df (diff)
QmlDesigner.model: adding generic context menu in QmlModelView
Change-Id: I210199ecb26db65416ff147da2f12aa5e775d3fd Reviewed-on: http://codereview.qt.nokia.com/789 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Thomas Hartmann <Thomas.Hartmann@nokia.com>
Diffstat (limited to 'src/plugins/qmldesigner/designercore/model/modelnodecontextmenu.cpp')
-rw-r--r--src/plugins/qmldesigner/designercore/model/modelnodecontextmenu.cpp424
1 files changed, 424 insertions, 0 deletions
diff --git a/src/plugins/qmldesigner/designercore/model/modelnodecontextmenu.cpp b/src/plugins/qmldesigner/designercore/model/modelnodecontextmenu.cpp
new file mode 100644
index 0000000000..6704b80ef6
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/model/modelnodecontextmenu.cpp
@@ -0,0 +1,424 @@
+#include "modelnodecontextmenu.h"
+#include <QApplication>
+#include <coreplugin/editormanager/editormanager.h>
+#include <nodeabstractproperty.h>
+#include <nodelistproperty.h>
+#include <nodemetainfo.h>
+#include <modelnode.h>
+#include <qmlitemnode.h>
+#include <variantproperty.h>
+#include <nodeproperty.h>
+#include <rewritertransaction.h>
+#include <designdocumentcontroller.h>
+
+
+namespace QmlDesigner {
+
+static inline QString captionForModelNode(const ModelNode &modelNode)
+{
+ if (modelNode.id().isEmpty())
+ return modelNode.simplifiedTypeName();
+
+ return modelNode.id();
+}
+
+static inline bool contains(const QmlItemNode &node, const QPoint &p)
+{
+ return node.instanceSceneTransform().mapRect(node.instanceBoundingRect()).contains(p);
+}
+
+static inline bool checkIfNodeIsAView(const ModelNode &node)
+{
+ return node.metaInfo().isValid() &&
+ (node.metaInfo().isSubclassOf("QtQuick.ListView", -1, -1) ||
+ node.metaInfo().isSubclassOf("QtQuick.GridView", -1, -1) ||
+ node.metaInfo().isSubclassOf("QtQuick.PathView", -1, -1));
+}
+
+static inline QList<QmlItemNode> siblingsForNode(const QmlItemNode &itemNode)
+{
+ QList<QmlItemNode> siblingList;
+
+ if (itemNode.isValid() && itemNode.modelNode().parentProperty().isValid()) {
+ QList<ModelNode> modelNodes = itemNode.modelNode().parentProperty().parentModelNode().allDirectSubModelNodes();
+ foreach (const ModelNode &node, modelNodes) {
+ QmlItemNode childItemNode = node;
+ if (childItemNode.isValid())
+ siblingList.append(childItemNode);
+ }
+ }
+
+ return siblingList;
+}
+
+static signed int getMaxZValue(const QList<QmlItemNode> &siblingList)
+{
+ signed int maximum = INT_MIN;
+ foreach (const QmlItemNode &node, siblingList) {
+ signed int z = node.instanceValue("z").toInt();
+ if (z > maximum)
+ maximum = z;
+ }
+ return maximum;
+}
+
+static signed int getMinZValue(const QList<QmlItemNode> &siblingList)
+{
+ signed int minimum = INT_MAX;
+ foreach (const QmlItemNode &node, siblingList) {
+ signed int z = node.instanceValue("z").toInt();
+ if (z < minimum)
+ minimum = z;
+ }
+ return minimum;
+}
+
+
+static inline bool modelNodeIsComponent(const ModelNode &node)
+{
+ if (!node.isValid() || !node.metaInfo().isValid())
+ return false;
+
+ if (node.metaInfo().isComponent())
+ return true;
+
+ if (node.nodeSourceType() == ModelNode::ComponentSource)
+ return true;
+ if (checkIfNodeIsAView(node) &&
+ node.hasNodeProperty("delegate")) {
+ if (node.nodeProperty("delegate").modelNode().metaInfo().isComponent())
+ return true;
+ if (node.nodeProperty("delegate").modelNode().nodeSourceType() == ModelNode::ComponentSource)
+ return true;
+ }
+
+ return false;
+}
+
+static inline bool isFileComponent(const ModelNode &node)
+{
+ if (!node.isValid() || !node.metaInfo().isValid())
+ return false;
+
+ if (node.metaInfo().isComponent())
+ return true;
+
+ if (checkIfNodeIsAView(node) &&
+ node.hasNodeProperty("delegate")) {
+ if (node.nodeProperty("delegate").modelNode().metaInfo().isComponent())
+ return true;
+ }
+
+ return false;
+}
+
+static inline void openFileForComponent(const ModelNode &node)
+{
+ if (node.metaInfo().isComponent()) {
+ Core::EditorManager::instance()->openEditor(node.metaInfo().componentFileName());
+ } else if (checkIfNodeIsAView(node) &&
+ node.hasNodeProperty("delegate") &&
+ node.nodeProperty("delegate").modelNode().metaInfo().isComponent()) {
+ Core::EditorManager::instance()->openEditor(node.nodeProperty("delegate").modelNode().metaInfo().componentFileName());
+ }
+}
+
+static inline void openInlineComponent(const ModelNode &node)
+{
+ if (!node.isValid() || !node.metaInfo().isValid())
+ return;
+
+ if (!DesignDocumentController::instance())
+ return;
+
+ if (node.nodeSourceType() == ModelNode::ComponentSource)
+ DesignDocumentController::instance()->changeCurrentModelTo(node);
+ if (checkIfNodeIsAView(node) &&
+ node.hasNodeProperty("delegate")) {
+ if (node.nodeProperty("delegate").modelNode().nodeSourceType() == ModelNode::ComponentSource)
+ DesignDocumentController::instance()->changeCurrentModelTo(node.nodeProperty("delegate").modelNode());
+ }
+}
+
+ModelNodeContextMenu::ModelNodeContextMenu(QmlModelView *view) : m_view(view)
+{
+}
+
+void ModelNodeContextMenu::execute(const QPoint &pos, bool selectionMenuBool)
+{
+ QMenu* menu = new QMenu();
+
+ bool singleSelected = false;
+ bool selectionIsEmpty = m_view->selectedModelNodes().isEmpty();
+ ModelNode currentSingleNode;
+ if (m_view->selectedModelNodes().count()== 1) {
+ singleSelected = true;
+ currentSingleNode = m_view->selectedModelNodes().first();
+ }
+
+ if (selectionMenuBool) {
+ QMenu *selectionMenu = new QMenu(QApplication::translate("ModelNodeContextMenu", "Selecion"), menu);
+ menu->addMenu(selectionMenu);
+ ModelNode parentNode;
+ if (singleSelected) {
+ //ModelNodeAction *selectionAction;
+ //selectionAction = createModelNodeAction(QApplication::translate("ModelNodeContextMenu", "DeSelect: ") + captionForModelNode(currentSingleNode), selectionMenu, QList<ModelNode>() << currentSingleNode, ModelNodeAction::DeSelectModelNode);
+ //selectionMenu->addAction(selectionAction);
+ if (!currentSingleNode.isRootNode()) {
+ parentNode = currentSingleNode.parentProperty().parentModelNode();
+ selectionMenu->addAction(createModelNodeAction(QApplication::translate("ModelNodeContextMenu", "Select parent: ") + captionForModelNode(parentNode),
+ selectionMenu, QList<ModelNode>() << parentNode, ModelNodeAction::SelectModelNode));
+ }
+
+ selectionMenu->addSeparator();
+ }
+ foreach (const ModelNode &node, m_view->allModelNodes()) {
+ if (node != currentSingleNode && node != parentNode && contains(node, m_scenePos) && !node.isRootNode())
+ selectionMenu->addAction(createModelNodeAction(QApplication::translate("ModelNodeContextMenu", "Select: ") + captionForModelNode(node), selectionMenu, QList<ModelNode>() << node, ModelNodeAction::SelectModelNode));
+ }
+ }
+
+ QMenu *stackMenu = new QMenu(QApplication::translate("ModelNodeContextMenu", "Stack (z)"), menu);
+ menu->addMenu(stackMenu);
+
+ stackMenu->addAction(createModelNodeAction(QApplication::translate("ModelNodeContextMenu", "To Front"), stackMenu, QList<ModelNode>() << currentSingleNode, ModelNodeAction::ToFront, singleSelected));
+ stackMenu->addAction(createModelNodeAction(QApplication::translate("ModelNodeContextMenu", "To Back"), stackMenu, QList<ModelNode>() << currentSingleNode, ModelNodeAction::ToBack, singleSelected));
+ stackMenu->addAction(createModelNodeAction(QApplication::translate("ModelNodeContextMenu", "Raise"), stackMenu, QList<ModelNode>() << m_view->selectedModelNodes(), ModelNodeAction::Raise));
+ stackMenu->addAction(createModelNodeAction(QApplication::translate("ModelNodeContextMenu", "Lower"), stackMenu, QList<ModelNode>() << m_view->selectedModelNodes(), ModelNodeAction::Lower));
+ stackMenu->addSeparator();
+ stackMenu->addAction(createModelNodeAction(QApplication::translate("ModelNodeContextMenu", "Reset z property"), stackMenu, QList<ModelNode>() << m_view->selectedModelNodes(), ModelNodeAction::ResetZ));
+
+ QMenu *editMenu = new QMenu(QApplication::translate("ModelNodeContextMenu", "Edit"), menu);
+ menu->addMenu(editMenu);
+ if (!selectionIsEmpty) {
+ //editMenu->addAction(createModelNodeAction(QApplication::translate("ModelNodeContextMenu", "Change Id"), editMenu, QList<ModelNode>() << currentSingleNode, ModelNodeAction::SetId, singleSelected));
+ editMenu->addAction(createModelNodeAction(QApplication::translate("ModelNodeContextMenu", "Reset Position"), editMenu, m_view->selectedModelNodes(), ModelNodeAction::ResetPosition));
+ editMenu->addAction(createModelNodeAction(QApplication::translate("ModelNodeContextMenu", "Reset Size"), editMenu, m_view->selectedModelNodes(), ModelNodeAction::ResetSize));
+ editMenu->addAction(createModelNodeAction(QApplication::translate("ModelNodeContextMenu", "Visibility"), editMenu, QList<ModelNode>() << currentSingleNode, ModelNodeAction::ModelNodeVisibility, singleSelected));
+
+ } else {
+ editMenu->setEnabled(false);
+ }
+
+ menu->addSeparator();
+ bool enterComponent = false;
+ if (singleSelected) {
+ enterComponent = modelNodeIsComponent(currentSingleNode);
+ }
+ menu->addAction(createModelNodeAction(QApplication::translate("ModelNodeContextMenu", "Go into Component"), editMenu, QList<ModelNode>() << currentSingleNode, ModelNodeAction::EnterComponent, enterComponent));
+
+ menu->exec(pos);
+ menu->deleteLater();
+}
+
+void ModelNodeContextMenu::setScenePos(const QPoint &pos)
+{
+ m_scenePos = pos;
+}
+
+
+ModelNodeAction* ModelNodeContextMenu::createModelNodeAction(const QString &description, QMenu *menu, const QList<ModelNode> &modelNodeList, ModelNodeAction::ModelNodeActionType type, bool enabled)
+{
+ ModelNodeAction* action = new ModelNodeAction(description, menu, m_view, modelNodeList, type);
+ action->setEnabled(enabled);
+ return action;
+}
+
+
+ModelNodeAction::ModelNodeAction( const QString & text, QObject *parent, QmlModelView *view, const QList<ModelNode> &modelNodeList, ModelNodeActionType type) :
+ QAction(text, parent), m_view(view), m_modelNodeList(modelNodeList), m_type(type)
+{
+ if (type == ModelNodeVisibility) {
+ setCheckable(true);
+ QmlItemNode itemNode = QmlItemNode(m_modelNodeList.first());
+ if (itemNode.isValid())
+ setChecked(itemNode.instanceValue("visible").toBool());
+ else
+ setEnabled(false);
+ }
+ connect(this, SIGNAL(triggered(bool)), this, SLOT(actionTriggered(bool)));
+}
+
+void ModelNodeAction::actionTriggered(bool b)
+{
+ switch (m_type) {
+ case ModelNodeAction::SelectModelNode: select(); break;
+ case ModelNodeAction::DeSelectModelNode: deSelect(); break;
+ case ModelNodeAction::CutSelection: cut(); break;
+ case ModelNodeAction::CopySelection: copy(); break;
+ case ModelNodeAction::DeleteSelection: deleteSelection(); break;
+ case ModelNodeAction::ToFront: toFront(); break;
+ case ModelNodeAction::ToBack: toBack(); break;
+ case ModelNodeAction::Raise: raise(); break;
+ case ModelNodeAction::Lower: lower(); break;
+ case ModelNodeAction::Paste: paste(); break;
+ case ModelNodeAction::Undo: undo(); break;
+ case ModelNodeAction::Redo: redo(); break;
+ case ModelNodeAction::ModelNodeVisibility: setVisible(b); break;
+ case ModelNodeAction::ResetSize: resetSize(); break;
+ case ModelNodeAction::ResetPosition: resetPosition(); break;
+ case ModelNodeAction::EnterComponent: enterComponent(); break;
+ case ModelNodeAction::SetId: setId(); break;
+ case ModelNodeAction::ResetZ: resetZ(); break;
+ }
+}
+
+void ModelNodeAction::select()
+{
+ if (m_view)
+ m_view->setSelectedModelNodes(m_modelNodeList);
+}
+
+void ModelNodeAction::deSelect()
+{
+ if (m_view) {
+ QList<ModelNode> selectedNodes = m_view->selectedModelNodes();
+ foreach (const ModelNode &node, m_modelNodeList) {
+ if (selectedNodes.contains(node))
+ selectedNodes.removeAll(node);
+ }
+ m_view->setSelectedModelNodes(selectedNodes);
+ }
+}
+
+void ModelNodeAction::cut()
+{
+}
+
+
+void ModelNodeAction::copy()
+{
+}
+
+void ModelNodeAction::deleteSelection()
+{
+}
+
+void ModelNodeAction::toFront()
+{
+ if (!m_view)
+ return;
+
+ QmlItemNode node = m_modelNodeList.first();
+ if (node.isValid()) {
+ signed int maximumZ = getMaxZValue(siblingsForNode(node));
+ maximumZ++;
+ node.setVariantProperty("z", maximumZ);
+ }
+}
+
+
+void ModelNodeAction::toBack()
+{
+ if (!m_view)
+ return;
+
+ QmlItemNode node = m_modelNodeList.first();
+ if (node.isValid()) {
+ signed int minimumZ = getMinZValue(siblingsForNode(node));
+ minimumZ--;
+ node.setVariantProperty("z", minimumZ);
+ }
+}
+
+void ModelNodeAction::raise()
+{
+ if (!m_view)
+ return;
+
+ RewriterTransaction(m_view);
+ foreach (ModelNode modelNode, m_modelNodeList) {
+ QmlItemNode node = modelNode;
+ if (node.isValid()) {
+ signed int z = node.instanceValue("z").toInt();
+ z++;
+ node.setVariantProperty("z", z);
+ }
+ }
+}
+
+void ModelNodeAction::lower()
+{
+ if (!m_view)
+ return;
+
+ RewriterTransaction(m_view);
+ foreach (ModelNode modelNode, m_modelNodeList) {
+ QmlItemNode node = modelNode;
+ if (node.isValid()) {
+ signed int z = node.instanceValue("z").toInt();
+ z--;
+ node.setVariantProperty("z", z);
+ }
+ }
+}
+
+void ModelNodeAction::paste()
+{
+}
+
+void ModelNodeAction::undo()
+{
+}
+
+void ModelNodeAction::redo()
+{
+}
+
+void ModelNodeAction::setVisible(bool b)
+{
+ m_modelNodeList.first().variantProperty("visible") = b;
+}
+
+
+void ModelNodeAction::resetSize()
+{
+ if (!m_view)
+ return;
+
+ RewriterTransaction(m_view);
+ foreach (ModelNode node, m_modelNodeList) {
+ node.removeProperty("width");
+ node.removeProperty("height");
+ }
+}
+
+void ModelNodeAction::resetPosition()
+{
+ if (!m_view)
+ return;
+
+ RewriterTransaction(m_view);
+ foreach (ModelNode node, m_modelNodeList) {
+ node.removeProperty("x");
+ node.removeProperty("y");
+ }
+}
+
+void ModelNodeAction::enterComponent()
+{
+ const ModelNode node = m_modelNodeList.first();
+ if (node.isValid()) {
+ if (isFileComponent(node))
+ openFileForComponent(node);
+ else
+ openInlineComponent(node);
+ }
+}
+
+void ModelNodeAction::setId()
+{
+}
+
+void ModelNodeAction::resetZ()
+{
+ if (!m_view)
+ return;
+
+ RewriterTransaction(m_view);
+ foreach (ModelNode node, m_modelNodeList) {
+ node.removeProperty("z");
+ }
+}
+
+}