Commit 5754c78b authored by Thomas Hartmann's avatar Thomas Hartmann
Browse files

QmlDesigner.contextMenu: allowing layout and anchoring

Change-Id: Ifbaff782826b413c508f96929222886da37325c5
Reviewed-on: http://codereview.qt-project.org/4986


Reviewed-by: default avatarQt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: default avatarThomas Hartmann <Thomas.Hartmann@nokia.com>
parent bbcaae36
......@@ -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"));
}
}
}
}
......@@ -64,7 +64,13 @@ public:
ResetPosition,
GoIntoComponent,
SetId,
ResetZ
ResetZ,
AnchorReset,
AnchorFill,
LayoutRow,
LayoutColumn,
LayoutGrid,
LayoutFlow
};
......@@ -94,6 +100,12 @@ private:
void goIntoComponent();
void setId();
void resetZ();
void anchorsFill();
void anchorsReset();
void layoutRow();
void layoutColumn();
void layoutGrid();
void layoutFlow();
QmlModelView *m_view;
QList<ModelNode> m_modelNodeList;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment