Skip to content
Snippets Groups Projects
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
No related branches found
No related tags found
No related merge requests found
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
** **
**************************************************************************/ **************************************************************************/
#include <cmath>
#include "modelnodecontextmenu.h" #include "modelnodecontextmenu.h"
#include <QApplication> #include <QApplication>
#include <QMessageBox> #include <QMessageBox>
...@@ -40,11 +41,15 @@ ...@@ -40,11 +41,15 @@
#include <modelnode.h> #include <modelnode.h>
#include <qmlitemnode.h> #include <qmlitemnode.h>
#include <variantproperty.h> #include <variantproperty.h>
#include <bindingproperty.h>
#include <nodeproperty.h> #include <nodeproperty.h>
#include <rewritingexception.h> #include <rewritingexception.h>
#include <rewritertransaction.h> #include <rewritertransaction.h>
#include <designmodewidget.h>
#include <qmlanchors.h>
#include <designdocumentcontroller.h> #include <designdocumentcontroller.h>
const QString auxDataString = QLatin1String("anchors_");
namespace QmlDesigner { namespace QmlDesigner {
...@@ -74,6 +79,38 @@ static inline bool isItem(const ModelNode &node) ...@@ -74,6 +79,38 @@ static inline bool isItem(const ModelNode &node)
return node.isValid() && node.metaInfo().isValid() && node.metaInfo().isSubclassOf("QtQuick.Item", -1, -1); 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) static inline QList<QmlItemNode> siblingsForNode(const QmlItemNode &itemNode)
{ {
QList<QmlItemNode> siblingList; QList<QmlItemNode> siblingList;
...@@ -199,6 +236,7 @@ void ModelNodeContextMenu::execute(const QPoint &pos, bool selectionMenuBool) ...@@ -199,6 +236,7 @@ void ModelNodeContextMenu::execute(const QPoint &pos, bool selectionMenuBool)
bool singleSelected = false; bool singleSelected = false;
bool selectionIsEmpty = m_view->selectedModelNodes().isEmpty(); bool selectionIsEmpty = m_view->selectedModelNodes().isEmpty();
ModelNode currentSingleNode; ModelNode currentSingleNode;
const bool isInBaseState = m_view->currentState().isBaseState();
const QList<ModelNode> &selectedModelNodes = m_view->selectedModelNodes(); const QList<ModelNode> &selectedModelNodes = m_view->selectedModelNodes();
if (selectedModelNodes.count()== 1) { if (selectedModelNodes.count()== 1) {
singleSelected = true; singleSelected = true;
...@@ -243,21 +281,60 @@ void ModelNodeContextMenu::execute(const QPoint &pos, bool selectionMenuBool) ...@@ -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)); //editMenu->addAction(createModelNodeAction(tr("Change Id"), editMenu, QList<ModelNode>() << currentSingleNode, ModelNodeAction::SetId, singleSelected));
ModelNodeAction* action = createModelNodeAction(tr("Reset Position"), editMenu, selectedModelNodes, ModelNodeAction::ResetPosition); ModelNodeAction* action = createModelNodeAction(tr("Reset Position"), editMenu, selectedModelNodes, ModelNodeAction::ResetPosition);
if (!modelNodesHaveProperty(selectedModelNodes, QLatin1String("x")) && !modelNodesHaveProperty(selectedModelNodes, QLatin1String("y"))) if (!modelNodesHaveProperty(selectedModelNodes, QLatin1String("x")) && !modelNodesHaveProperty(selectedModelNodes, QLatin1String("y")))
action->setDisabled(true); action->setEnabled(false);
editMenu->addAction(action); editMenu->addAction(action);
action = createModelNodeAction(tr("Reset Size"), editMenu, selectedModelNodes, ModelNodeAction::ResetSize); action = createModelNodeAction(tr("Reset Size"), editMenu, selectedModelNodes, ModelNodeAction::ResetSize);
if (!modelNodesHaveProperty(selectedModelNodes, QLatin1String("width")) && !modelNodesHaveProperty(selectedModelNodes, QLatin1String("height"))) if (!modelNodesHaveProperty(selectedModelNodes, QLatin1String("width")) && !modelNodesHaveProperty(selectedModelNodes, QLatin1String("height")))
action->setDisabled(true); action->setEnabled(false);
editMenu->addAction(action); editMenu->addAction(action);
action = createModelNodeAction(tr("Visibility"), editMenu, QList<ModelNode>() << currentSingleNode, ModelNodeAction::ModelNodeVisibility, singleSelected); action = createModelNodeAction(tr("Visibility"), editMenu, QList<ModelNode>() << currentSingleNode, ModelNodeAction::ModelNodeVisibility, singleSelected);
editMenu->addAction(action); editMenu->addAction(action);
if (singleSelected && !isItem(currentSingleNode)) if (singleSelected && !isItem(currentSingleNode))
action->setDisabled(true); action->setEnabled(false);
} else { } else {
editMenu->setEnabled(false); 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(); menu->addSeparator();
bool enterComponent = false; bool enterComponent = false;
if (singleSelected) { if (singleSelected) {
...@@ -310,25 +387,35 @@ void ModelNodeAction::goIntoComponent(const ModelNode &modelNode) ...@@ -310,25 +387,35 @@ void ModelNodeAction::goIntoComponent(const ModelNode &modelNode)
void ModelNodeAction::actionTriggered(bool b) void ModelNodeAction::actionTriggered(bool b)
{ {
switch (m_type) { try {
case ModelNodeAction::SelectModelNode: select(); break; switch (m_type) {
case ModelNodeAction::DeSelectModelNode: deSelect(); break; case ModelNodeAction::SelectModelNode: select(); break;
case ModelNodeAction::CutSelection: cut(); break; case ModelNodeAction::DeSelectModelNode: deSelect(); break;
case ModelNodeAction::CopySelection: copy(); break; case ModelNodeAction::CutSelection: cut(); break;
case ModelNodeAction::DeleteSelection: deleteSelection(); break; case ModelNodeAction::CopySelection: copy(); break;
case ModelNodeAction::ToFront: toFront(); break; case ModelNodeAction::DeleteSelection: deleteSelection(); break;
case ModelNodeAction::ToBack: toBack(); break; case ModelNodeAction::ToFront: toFront(); break;
case ModelNodeAction::Raise: raise(); break; case ModelNodeAction::ToBack: toBack(); break;
case ModelNodeAction::Lower: lower(); break; case ModelNodeAction::Raise: raise(); break;
case ModelNodeAction::Paste: paste(); break; case ModelNodeAction::Lower: lower(); break;
case ModelNodeAction::Undo: undo(); break; case ModelNodeAction::Paste: paste(); break;
case ModelNodeAction::Redo: redo(); break; case ModelNodeAction::Undo: undo(); break;
case ModelNodeAction::ModelNodeVisibility: setVisible(b); break; case ModelNodeAction::Redo: redo(); break;
case ModelNodeAction::ResetSize: resetSize(); break; case ModelNodeAction::ModelNodeVisibility: setVisible(b); break;
case ModelNodeAction::ResetPosition: resetPosition(); break; case ModelNodeAction::ResetSize: resetSize(); break;
case ModelNodeAction::GoIntoComponent: goIntoComponent(); break; case ModelNodeAction::ResetPosition: resetPosition(); break;
case ModelNodeAction::SetId: setId(); break; case ModelNodeAction::GoIntoComponent: goIntoComponent(); break;
case ModelNodeAction::ResetZ: resetZ(); 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() ...@@ -404,7 +491,7 @@ void ModelNodeAction::raise()
return; return;
try { try {
RewriterTransaction(m_view); RewriterTransaction transaction(m_view);
foreach (ModelNode modelNode, m_modelNodeList) { foreach (ModelNode modelNode, m_modelNodeList) {
QmlItemNode node = modelNode; QmlItemNode node = modelNode;
if (node.isValid()) { if (node.isValid()) {
...@@ -423,7 +510,7 @@ void ModelNodeAction::lower() ...@@ -423,7 +510,7 @@ void ModelNodeAction::lower()
if (!m_view) if (!m_view)
return; return;
try { try {
RewriterTransaction(m_view); RewriterTransaction transaction(m_view);
foreach (ModelNode modelNode, m_modelNodeList) { foreach (ModelNode modelNode, m_modelNodeList) {
QmlItemNode node = modelNode; QmlItemNode node = modelNode;
if (node.isValid()) { if (node.isValid()) {
...@@ -466,7 +553,7 @@ void ModelNodeAction::resetSize() ...@@ -466,7 +553,7 @@ void ModelNodeAction::resetSize()
if (!m_view) if (!m_view)
return; return;
try { try {
RewriterTransaction(m_view); RewriterTransaction transaction(m_view);
foreach (ModelNode node, m_modelNodeList) { foreach (ModelNode node, m_modelNodeList) {
node.removeProperty("width"); node.removeProperty("width");
node.removeProperty("height"); node.removeProperty("height");
...@@ -481,7 +568,7 @@ void ModelNodeAction::resetPosition() ...@@ -481,7 +568,7 @@ void ModelNodeAction::resetPosition()
if (!m_view) if (!m_view)
return; return;
try { try {
RewriterTransaction(m_view); RewriterTransaction transaction(m_view);
foreach (ModelNode node, m_modelNodeList) { foreach (ModelNode node, m_modelNodeList) {
node.removeProperty("x"); node.removeProperty("x");
node.removeProperty("y"); node.removeProperty("y");
...@@ -505,10 +592,197 @@ void ModelNodeAction::resetZ() ...@@ -505,10 +592,197 @@ void ModelNodeAction::resetZ()
if (!m_view) if (!m_view)
return; return;
RewriterTransaction(m_view); RewriterTransaction transaction(m_view);
foreach (ModelNode node, m_modelNodeList) { foreach (ModelNode node, m_modelNodeList) {
node.removeProperty("z"); 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: ...@@ -64,7 +64,13 @@ public:
ResetPosition, ResetPosition,
GoIntoComponent, GoIntoComponent,
SetId, SetId,
ResetZ ResetZ,
AnchorReset,
AnchorFill,
LayoutRow,
LayoutColumn,
LayoutGrid,
LayoutFlow
}; };
...@@ -94,6 +100,12 @@ private: ...@@ -94,6 +100,12 @@ private:
void goIntoComponent(); void goIntoComponent();
void setId(); void setId();
void resetZ(); void resetZ();
void anchorsFill();
void anchorsReset();
void layoutRow();
void layoutColumn();
void layoutGrid();
void layoutFlow();
QmlModelView *m_view; QmlModelView *m_view;
QList<ModelNode> m_modelNodeList; QList<ModelNode> m_modelNodeList;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment