diff options
author | Thomas Hartmann <Thomas.Hartmann@nokia.com> | 2011-06-27 17:53:36 +0200 |
---|---|---|
committer | Thomas Hartmann <Thomas.Hartmann@nokia.com> | 2011-06-27 17:54:13 +0200 |
commit | dde8ef0c711f6784107a97ae6e8b34f7530c6d24 (patch) | |
tree | 13dd23ac07511fdd5a8e966b6204187ec8af748c /src/plugins/qmldesigner/designercore/model/modelnodecontextmenu.cpp | |
parent | 51d5e232cf5b79782dac6b88c1ce938e2a11e6df (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.cpp | 424 |
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"); + } +} + +} |