aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/qmldesigner/designercore/model/modelnodecontextmenu.cpp
diff options
context:
space:
mode:
authorThomas Hartmann <Thomas.Hartmann@nokia.com>2011-09-15 13:33:47 +0200
committerThomas Hartmann <Thomas.Hartmann@nokia.com>2011-09-20 09:45:03 +0200
commit5754c78b6d245c0c1a105fe5cbbfef9e506e7e6d (patch)
treee6810f3e0cfe6ef29aa1870bc43a9b6083fa4d5d /src/plugins/qmldesigner/designercore/model/modelnodecontextmenu.cpp
parentbbcaae36adda7233a385dbb9b2e97454b2d2122f (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.cpp328
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"));
+ }
+ }
+}
+
}