diff options
author | Thomas Hartmann <Thomas.Hartmann@nokia.com> | 2011-09-15 13:33:47 +0200 |
---|---|---|
committer | Thomas Hartmann <Thomas.Hartmann@nokia.com> | 2011-09-20 09:45:03 +0200 |
commit | 5754c78b6d245c0c1a105fe5cbbfef9e506e7e6d (patch) | |
tree | e6810f3e0cfe6ef29aa1870bc43a9b6083fa4d5d /src/plugins/qmldesigner/designercore/model/modelnodecontextmenu.cpp | |
parent | bbcaae36adda7233a385dbb9b2e97454b2d2122f (diff) |
QmlDesigner.contextMenu: allowing layout and anchoring
Change-Id: Ifbaff782826b413c508f96929222886da37325c5
Reviewed-on: http://codereview.qt-project.org/4986
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 | 328 |
1 files changed, 301 insertions, 27 deletions
diff --git a/src/plugins/qmldesigner/designercore/model/modelnodecontextmenu.cpp b/src/plugins/qmldesigner/designercore/model/modelnodecontextmenu.cpp index 3ae4815cc2..af7613cf3f 100644 --- a/src/plugins/qmldesigner/designercore/model/modelnodecontextmenu.cpp +++ b/src/plugins/qmldesigner/designercore/model/modelnodecontextmenu.cpp @@ -30,6 +30,7 @@ ** **************************************************************************/ +#include <cmath> #include "modelnodecontextmenu.h" #include <QApplication> #include <QMessageBox> @@ -40,11 +41,15 @@ #include <modelnode.h> #include <qmlitemnode.h> #include <variantproperty.h> +#include <bindingproperty.h> #include <nodeproperty.h> #include <rewritingexception.h> #include <rewritertransaction.h> +#include <designmodewidget.h> +#include <qmlanchors.h> #include <designdocumentcontroller.h> +const QString auxDataString = QLatin1String("anchors_"); namespace QmlDesigner { @@ -74,6 +79,38 @@ static inline bool isItem(const ModelNode &node) return node.isValid() && node.metaInfo().isValid() && node.metaInfo().isSubclassOf("QtQuick.Item", -1, -1); } +static inline bool itemsHaveSameParent(const QList<ModelNode> &siblingList) +{ + if (siblingList.isEmpty()) + return false; + + + QmlItemNode item(siblingList.first()); + if (!item.isValid()) + return false; + + if (item.isRootModelNode()) + return false; + + QmlItemNode parent = item.instanceParent(); + if (!parent.isValid()) + return false; + + foreach (const ModelNode &node, siblingList) { + QmlItemNode currentItem(node); + if (!currentItem.isValid()) + return false; + QmlItemNode currentParent = currentItem.instanceParent(); + if (!currentParent.isValid()) + return false; + if (currentItem.instanceIsInPositioner()) + return false; + if (currentParent != parent) + return false; + } + return true; +} + static inline QList<QmlItemNode> siblingsForNode(const QmlItemNode &itemNode) { QList<QmlItemNode> siblingList; @@ -199,6 +236,7 @@ void ModelNodeContextMenu::execute(const QPoint &pos, bool selectionMenuBool) bool singleSelected = false; bool selectionIsEmpty = m_view->selectedModelNodes().isEmpty(); ModelNode currentSingleNode; + const bool isInBaseState = m_view->currentState().isBaseState(); const QList<ModelNode> &selectedModelNodes = m_view->selectedModelNodes(); if (selectedModelNodes.count()== 1) { singleSelected = true; @@ -243,21 +281,60 @@ void ModelNodeContextMenu::execute(const QPoint &pos, bool selectionMenuBool) //editMenu->addAction(createModelNodeAction(tr("Change Id"), editMenu, QList<ModelNode>() << currentSingleNode, ModelNodeAction::SetId, singleSelected)); ModelNodeAction* action = createModelNodeAction(tr("Reset Position"), editMenu, selectedModelNodes, ModelNodeAction::ResetPosition); if (!modelNodesHaveProperty(selectedModelNodes, QLatin1String("x")) && !modelNodesHaveProperty(selectedModelNodes, QLatin1String("y"))) - action->setDisabled(true); + action->setEnabled(false); editMenu->addAction(action); action = createModelNodeAction(tr("Reset Size"), editMenu, selectedModelNodes, ModelNodeAction::ResetSize); if (!modelNodesHaveProperty(selectedModelNodes, QLatin1String("width")) && !modelNodesHaveProperty(selectedModelNodes, QLatin1String("height"))) - action->setDisabled(true); + action->setEnabled(false); editMenu->addAction(action); action = createModelNodeAction(tr("Visibility"), editMenu, QList<ModelNode>() << currentSingleNode, ModelNodeAction::ModelNodeVisibility, singleSelected); editMenu->addAction(action); if (singleSelected && !isItem(currentSingleNode)) - action->setDisabled(true); + action->setEnabled(false); } else { editMenu->setEnabled(false); } + QMenu *anchorMenu = new QMenu(tr("Anchors"), menu); + menu->addMenu(anchorMenu); + + + if (singleSelected && isInBaseState) { + QmlItemNode itemNode(currentSingleNode); + + bool anchored = itemNode.instanceHasAnchors(); + bool isRootNode = itemNode.isRootNode(); + + ModelNodeAction *action = createModelNodeAction(tr("Fill"), anchorMenu, QList<ModelNode>() << currentSingleNode, ModelNodeAction::AnchorFill, !anchored && !isRootNode); + anchorMenu->addAction(action); + action = createModelNodeAction(tr("Reset"), anchorMenu, QList<ModelNode>() << currentSingleNode, ModelNodeAction::AnchorReset, anchored && !isRootNode); + anchorMenu->addAction(action); + } else { + anchorMenu->setEnabled(false); + } + + QMenu *layoutMenu = new QMenu(tr("Layout"), menu); + menu->addMenu(layoutMenu); + + bool layoutingIsPossible = itemsHaveSameParent(selectedModelNodes) && isInBaseState; + + if (!singleSelected && !selectionIsEmpty && layoutingIsPossible) { + + ModelNodeAction *action = createModelNodeAction(tr("Layout in row"), layoutMenu, selectedModelNodes, ModelNodeAction::LayoutRow, true); + layoutMenu->addAction(action); + action = createModelNodeAction(tr("Layout in Column"), layoutMenu, selectedModelNodes, ModelNodeAction::LayoutColumn, true); + layoutMenu->addAction(action); + action = createModelNodeAction(tr("Layout in Grid"), layoutMenu, selectedModelNodes, ModelNodeAction::LayoutGrid, true); + layoutMenu->addAction(action); + action = createModelNodeAction(tr("Layout in Flow"), layoutMenu, selectedModelNodes, ModelNodeAction::LayoutFlow, true); + layoutMenu->addAction(action); + + } else { + layoutMenu->setEnabled(false); + } + + menu->addSeparator(); bool enterComponent = false; if (singleSelected) { @@ -310,25 +387,35 @@ void ModelNodeAction::goIntoComponent(const ModelNode &modelNode) 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::GoIntoComponent: goIntoComponent(); break; - case ModelNodeAction::SetId: setId(); break; - case ModelNodeAction::ResetZ: resetZ(); break; + try { + 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::GoIntoComponent: goIntoComponent(); break; + case ModelNodeAction::SetId: setId(); break; + case ModelNodeAction::ResetZ: resetZ(); break; + case ModelNodeAction::AnchorFill: anchorsFill(); break; + case ModelNodeAction::AnchorReset: anchorsReset(); break; + case ModelNodeAction::LayoutColumn: layoutColumn(); break; + case ModelNodeAction::LayoutRow: layoutRow(); break; + case ModelNodeAction::LayoutGrid: layoutGrid(); break; + case ModelNodeAction::LayoutFlow: layoutFlow(); break; + } + } catch (RewritingException e) { //better save then sorry + QMessageBox::warning(0, "Error", e.description()); } } @@ -404,7 +491,7 @@ void ModelNodeAction::raise() return; try { - RewriterTransaction(m_view); + RewriterTransaction transaction(m_view); foreach (ModelNode modelNode, m_modelNodeList) { QmlItemNode node = modelNode; if (node.isValid()) { @@ -423,7 +510,7 @@ void ModelNodeAction::lower() if (!m_view) return; try { - RewriterTransaction(m_view); + RewriterTransaction transaction(m_view); foreach (ModelNode modelNode, m_modelNodeList) { QmlItemNode node = modelNode; if (node.isValid()) { @@ -466,7 +553,7 @@ void ModelNodeAction::resetSize() if (!m_view) return; try { - RewriterTransaction(m_view); + RewriterTransaction transaction(m_view); foreach (ModelNode node, m_modelNodeList) { node.removeProperty("width"); node.removeProperty("height"); @@ -481,7 +568,7 @@ void ModelNodeAction::resetPosition() if (!m_view) return; try { - RewriterTransaction(m_view); + RewriterTransaction transaction(m_view); foreach (ModelNode node, m_modelNodeList) { node.removeProperty("x"); node.removeProperty("y"); @@ -505,10 +592,197 @@ void ModelNodeAction::resetZ() if (!m_view) return; - RewriterTransaction(m_view); + RewriterTransaction transaction(m_view); foreach (ModelNode node, m_modelNodeList) { node.removeProperty("z"); } } +static inline void backupPropertyAndRemove(ModelNode node, const QString &propertyName) +{ + if (node.hasVariantProperty(propertyName)) { + node.setAuxiliaryData(auxDataString + propertyName, node.variantProperty(propertyName).value()); + node.removeProperty(propertyName); + + } + if (node.hasBindingProperty(propertyName)) { + node.setAuxiliaryData(auxDataString + propertyName, QmlItemNode(node).instanceValue(propertyName)); + node.removeProperty(propertyName); + } +} + + +static inline void restoreProperty(ModelNode node, const QString &propertyName) +{ + if (node.hasAuxiliaryData(auxDataString + propertyName)) + node.variantProperty(propertyName) = node.auxiliaryData(auxDataString + propertyName); +} + +void ModelNodeAction::anchorsFill() +{ + if (!m_view) + return; + + RewriterTransaction transaction(m_view); + + foreach (ModelNode modelNode, m_modelNodeList) { + QmlItemNode node = modelNode; + if (node.isValid()) { + node.anchors().fill(); + backupPropertyAndRemove(modelNode, QLatin1String("x")); + backupPropertyAndRemove(modelNode, QLatin1String("y")); + backupPropertyAndRemove(modelNode, QLatin1String("width")); + backupPropertyAndRemove(modelNode, QLatin1String("height")); + } + } +} + +void ModelNodeAction::anchorsReset() +{ + if (!m_view) + return; + RewriterTransaction transaction(m_view); + + foreach (ModelNode modelNode, m_modelNodeList) { + QmlItemNode node = modelNode; + if (node.isValid()) { + node.anchors().removeAnchors(); + node.anchors().removeMargins(); + restoreProperty(node, "x"); + restoreProperty(node, "y"); + restoreProperty(node, "width"); + restoreProperty(node, "height"); + } + } +} + +static inline void reparentTo(const ModelNode &node, const QmlItemNode &parent) +{ + + if (parent.isValid() && node.isValid()) { + NodeAbstractProperty parentProperty; + + if (parent.hasDefaultProperty()) { + parentProperty = parent.nodeAbstractProperty(parent.defaultProperty()); + } else { + parentProperty = parent.nodeAbstractProperty(QLatin1String("data")); + } + + parentProperty.reparentHere(node); + } +} + +void ModelNodeAction::layoutRow() +{ + if (!m_view) + return; + + ModelNode row; + { + RewriterTransaction transaction(m_view); + + QmlItemNode parent = QmlItemNode(m_modelNodeList.first()).instanceParent(); + if (!parent.isValid()) + return; + + row = m_view->createModelNode(QLatin1String("QtQuick.Row"), parent.modelNode().majorQtQuickVersion(), 0); + + reparentTo(row, parent); + } + + { + RewriterTransaction transaction(m_view); + foreach (ModelNode modelNode, m_modelNodeList) { + reparentTo(modelNode, row); + modelNode.removeProperty(QLatin1String("x")); + modelNode.removeProperty(QLatin1String("y")); + } + } +} + +void ModelNodeAction::layoutColumn() +{ + if (!m_view) + return; + + ModelNode column; + { + RewriterTransaction transaction(m_view); + + QmlItemNode parent = QmlItemNode(m_modelNodeList.first()).instanceParent(); + if (!parent.isValid()) + return; + + column = m_view->createModelNode(QLatin1String("QtQuick.Column"), parent.modelNode().majorQtQuickVersion(), 0); + + reparentTo(column, parent); + } + + { + RewriterTransaction transaction(m_view); + foreach (ModelNode modelNode, m_modelNodeList) { + reparentTo(modelNode, column); + modelNode.removeProperty(QLatin1String("x")); + modelNode.removeProperty(QLatin1String("y")); + } + } +} + +void ModelNodeAction::layoutGrid() +{ + if (!m_view) + return; + + ModelNode grid; + { + RewriterTransaction transaction(m_view); + + QmlItemNode parent = QmlItemNode(m_modelNodeList.first()).instanceParent(); + if (!parent.isValid()) + return; + + grid = m_view->createModelNode(QLatin1String("QtQuick.Grid"), parent.modelNode().majorQtQuickVersion(), 0); + grid.variantProperty(QLatin1String("columns")) = int(sqrt(double(m_modelNodeList.count()))); + + reparentTo(grid, parent); + } + + { + RewriterTransaction transaction(m_view); + foreach (ModelNode modelNode, m_modelNodeList) { + reparentTo(modelNode, grid); + modelNode.removeProperty(QLatin1String("x")); + modelNode.removeProperty(QLatin1String("y")); + } + } +} + +void ModelNodeAction::layoutFlow() +{ + if (!m_view) + return; + + ModelNode flow; + { + RewriterTransaction transaction(m_view); + + QmlItemNode parent = QmlItemNode(m_modelNodeList.first()).instanceParent(); + if (!parent.isValid()) + return; + + flow = m_view->createModelNode(QLatin1String("QtQuick.Flow"), parent.modelNode().majorQtQuickVersion(), 0); + + reparentTo(flow, parent); + } + + { + RewriterTransaction transaction(m_view); + foreach (ModelNode modelNode, m_modelNodeList) { + reparentTo(modelNode, flow); + modelNode.removeProperty(QLatin1String("x")); + modelNode.removeProperty(QLatin1String("y")); + } + } +} + } |