summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hartmann <Thomas.Hartmann@digia.com>2013-07-16 12:23:07 +0200
committerThomas Hartmann <Thomas.Hartmann@digia.com>2013-07-16 12:29:44 +0200
commit066b3ab8890475a8a91f7eb2021e631618345ff0 (patch)
tree4eacfe7af83837e32b81785ab1632036d112e469
parentbcf9b3a171ad5a9dc478ad392b4e21bfbf0c6403 (diff)
downloadqt-creator-066b3ab8890475a8a91f7eb2021e631618345ff0.tar.gz
QmlDesigner.ContextMenu: fix support for Layouts
We have positioner in QtQuick and "real" layouts in QtQuick.Layouts. Change-Id: Ie1c5235820ac698048a229af7ede9d8f57926b19 Reviewed-by: Marco Bubke <marco.bubke@digia.com>
-rw-r--r--src/plugins/qmldesigner/components/componentcore/componentcore_constants.h16
-rw-r--r--src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp198
-rw-r--r--src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp178
-rw-r--r--src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h14
4 files changed, 388 insertions, 18 deletions
diff --git a/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h b/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h
index 9c67060fb4..289c1e8c87 100644
--- a/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h
+++ b/src/plugins/qmldesigner/components/componentcore/componentcore_constants.h
@@ -82,10 +82,18 @@ const char resetZDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Re
const char anchorsFillDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Fill");
const char anchorsResetDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Reset");
-const char layoutColumnDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Layout in Column");
-const char layoutRowDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Layout in Row");
-const char layoutGridDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Layout in Grid");
-const char layoutFlowDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Layout in Flow");
+const char layoutColumnPositionerDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Layout in Column (Positioner)");
+const char layoutRowPositionerDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Layout in Row (Positioner)");
+const char layoutGridPositionerDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Layout in Grid (Positioner)");
+const char layoutFlowPositionerDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Layout in Flow (Positioner)");
+
+const char layoutColumnLayoutDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Layout in ColumnLayout");
+const char layoutRowLayoutDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Layout in RowLayout");
+const char layoutGridLayoutDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Layout in GridLayout");
+
+const char layoutFillWidthDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Fill Width");
+const char layoutFillHeightDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Fill Height");
+
const int priorityFirst = 220;
const int prioritySelectionCategory = 200;
diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
index 0facd04494..041bdf5b32 100644
--- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp
@@ -30,6 +30,7 @@
#include "designeractionmanager.h"
#include "modelnodecontextmenu_helper.h"
#include <nodeproperty.h>
+#include <nodemetainfo.h>
namespace QmlDesigner {
@@ -246,6 +247,65 @@ public:
}
};
+class FillLayoutModelNodeAction : public ModelNodeAction
+{
+public:
+ FillLayoutModelNodeAction(const QString &description, const QByteArray &category, int priority,
+ ModelNodeOperations::SelectionAction action,
+ SelectionContextFunction enabled = &SelectionContextFunctors::always,
+ SelectionContextFunction visibility = &SelectionContextFunctors::always) :
+ ModelNodeAction(description, category, priority, action, enabled, visibility)
+ {}
+ virtual void updateContext()
+ {
+ defaultAction()->setSelectionContext(selectionContext());
+ if (selectionContext().isValid()) {
+ defaultAction()->setEnabled(isEnabled(selectionContext()));
+ defaultAction()->setVisible(isVisible(selectionContext()));
+
+ defaultAction()->setCheckable(true);
+ QmlItemNode itemNode = QmlItemNode(selectionContext().currentSingleSelectedNode());
+ if (itemNode.isValid()) {
+ bool flag = false;
+ if (itemNode.modelNode().hasProperty(m_propertyName)
+ || itemNode.propertyAffectedByCurrentState(m_propertyName))
+ flag = itemNode.modelValue(m_propertyName).toBool();
+ defaultAction()->setChecked(flag);
+ } else {
+ defaultAction()->setEnabled(false);
+ }
+ }
+ }
+protected:
+ PropertyName m_propertyName;
+};
+
+class FillWidthModelNodeAction : public FillLayoutModelNodeAction
+{
+public:
+ FillWidthModelNodeAction(const QString &description, const QByteArray &category, int priority,
+ ModelNodeOperations::SelectionAction action,
+ SelectionContextFunction enabled = &SelectionContextFunctors::always,
+ SelectionContextFunction visibility = &SelectionContextFunctors::always) :
+ FillLayoutModelNodeAction(description, category, priority, action, enabled, visibility)
+ {
+ m_propertyName = "Layout.fillWidth";
+ }
+};
+
+class FillHeightModelNodeAction : public FillLayoutModelNodeAction
+{
+public:
+ FillHeightModelNodeAction(const QString &description, const QByteArray &category, int priority,
+ ModelNodeOperations::SelectionAction action,
+ SelectionContextFunction enabled = &SelectionContextFunctors::always,
+ SelectionContextFunction visibility = &SelectionContextFunctors::always) :
+ FillLayoutModelNodeAction(description, category, priority, action, enabled, visibility)
+ {
+ m_propertyName = "Layout.fillHeight";
+ }
+};
+
class SelectionModelNodeAction : public MenuDesignerAction
{
public:
@@ -328,9 +388,42 @@ bool selectionHasSameParentAndInBaseState(const SelectionContext &context)
return selectionHasSameParent(context) && inBaseState(context);
}
+bool isNotInLayout(const SelectionContext &context)
+{
+ if (selectionNotEmpty(context)) {
+ ModelNode selectedModelNode = context.selectedModelNodes().first();
+ ModelNode parentModelNode;
+
+ if (selectedModelNode.hasParentProperty())
+ parentModelNode = selectedModelNode.parentProperty().parentModelNode();
+
+ if (parentModelNode.isValid() && parentModelNode.metaInfo().isValid())
+ return !parentModelNode.metaInfo().isLayoutable();
+ }
+
+ return true;
+}
+
bool selectionCanBeLayouted(const SelectionContext &context)
{
- return selectionHasSameParentAndInBaseState(context) && inBaseState(context);
+ return selectionHasSameParentAndInBaseState(context)
+ && inBaseState(context)
+ && isNotInLayout(context);
+}
+
+bool hasQtQuickLayoutImport(const SelectionContext &context)
+{
+ if (context.qmlModelView() && context.qmlModelView()->model()) {
+ Import import = Import::createLibraryImport(QLatin1String("QtQuick.Layouts"), QLatin1String("1.0"));
+ return context.qmlModelView()->model()->hasImport(import, true, true);
+ }
+
+ return false;
+}
+
+bool selectionCanBeLayoutedAndasQtQuickLayoutImport(const SelectionContext &context)
+{
+ return selectionCanBeLayouted(context) && hasQtQuickLayoutImport(context);
}
bool selectionNotEmptyAndHasZProperty(const SelectionContext &context)
@@ -350,6 +443,34 @@ bool selectionNotEmptyAndHasXorYProperty(const SelectionContext &context)
&& selectionHasProperty1or2(context, xProperty, yProperty);
}
+bool singleSelectionAndInQtQuickLayout(const SelectionContext &context)
+{
+ if (!singleSelection(context))
+ return false;
+
+ ModelNode currentSelectedNode = context.currentSingleSelectedNode();
+ if (!currentSelectedNode.isValid())
+ return false;
+
+ if (!currentSelectedNode.hasParentProperty())
+ return false;
+
+ ModelNode parentModelNode = currentSelectedNode.parentProperty().parentModelNode();
+
+ NodeMetaInfo metaInfo = parentModelNode.metaInfo();
+
+ if (!metaInfo.isValid())
+ return false;
+
+ return metaInfo.isSubclassOf("QtQuick.Layouts.Layout", -1, -1);
+}
+
+bool layoutOptionVisible(const SelectionContext &context)
+{
+ return multiSelectionAndInBaseState(context)
+ || singleSelectionAndInQtQuickLayout(context);
+}
+
void DesignerActionManager::createDefaultDesignerActions()
{
using namespace SelectionContextFunctors;
@@ -387,15 +508,80 @@ void DesignerActionManager::createDefaultDesignerActions()
(anchorsResetDisplayName, anchorsCategory, 180, &anchorsReset, &singleSelectionItemIsAnchored));
addDesignerAction(new MenuDesignerAction(layoutCategoryDisplayName, layoutCategory,
- priorityLayoutCategory, &multiSelectionAndInBaseState));
+ priorityLayoutCategory, &layoutOptionVisible));
addDesignerAction(new ModelNodeAction
- (layoutRowDisplayName, layoutCategory, 200, &layoutRow, &selectionCanBeLayouted));
+ (layoutRowPositionerDisplayName,
+ layoutCategory,
+ 200,
+ &layoutRowPositioner,
+ &selectionCanBeLayouted,
+ selectionCanBeLayouted));
+
addDesignerAction(new ModelNodeAction
- (layoutColumnDisplayName, layoutCategory, 180, &layoutColumn, &selectionCanBeLayouted));
+ (layoutColumnPositionerDisplayName,
+ layoutCategory,
+ 180,
+ &layoutColumnPositioner,
+ &selectionCanBeLayouted,
+ selectionCanBeLayouted));
+
+ addDesignerAction(new ModelNodeAction
+ (layoutGridPositionerDisplayName,
+ layoutCategory,
+ 160,
+ &layoutGridPositioner,
+ &selectionCanBeLayouted,
+ selectionCanBeLayouted));
+
addDesignerAction(new ModelNodeAction
- (layoutGridDisplayName, layoutCategory, 160, &layoutGrid, &selectionCanBeLayouted));
+ (layoutFlowPositionerDisplayName,
+ layoutCategory,
+ 140,
+ &layoutFlowPositioner,
+ &selectionCanBeLayouted,
+ selectionCanBeLayouted));
+
+ addDesignerAction(new SeperatorDesignerAction(layoutCategory, 120));
+
+ addDesignerAction(new ModelNodeAction
+ (layoutRowLayoutDisplayName,
+ layoutCategory,
+ 100,
+ &layoutRowLayout,
+ &selectionCanBeLayoutedAndasQtQuickLayoutImport,
+ &selectionCanBeLayoutedAndasQtQuickLayoutImport));
+
+ addDesignerAction(new ModelNodeAction
+ (layoutColumnLayoutDisplayName,
+ layoutCategory,
+ 80,
+ &layoutColumnLayout,
+ &selectionCanBeLayoutedAndasQtQuickLayoutImport,
+ &selectionCanBeLayoutedAndasQtQuickLayoutImport));
+
addDesignerAction(new ModelNodeAction
- (layoutFlowDisplayName, layoutCategory, 140, &layoutFlow, &selectionCanBeLayouted));
+ (layoutGridLayoutDisplayName,
+ layoutCategory,
+ 60,
+ &layoutGridLayout,
+ &selectionCanBeLayoutedAndasQtQuickLayoutImport,
+ &selectionCanBeLayoutedAndasQtQuickLayoutImport));
+
+ addDesignerAction(new FillWidthModelNodeAction
+ (layoutFillWidthDisplayName,
+ layoutCategory,
+ 40,
+ &setFillWidth,
+ singleSelectionAndInQtQuickLayout,
+ singleSelectionAndInQtQuickLayout));
+
+ addDesignerAction(new FillHeightModelNodeAction
+ (layoutFillHeightDisplayName,
+ layoutCategory,
+ 20,
+ &setFillHeight,
+ singleSelectionAndInQtQuickLayout,
+ singleSelectionAndInQtQuickLayout));
addDesignerAction(new SeperatorDesignerAction(rootCategory, priorityTopLevelSeperator));
addDesignerAction(new ModelNodeAction
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
index 182fca25c8..931501b4fd 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp
@@ -245,6 +245,31 @@ void setVisible(const SelectionContext &selectionState)
}
}
+void setFillWidth(const SelectionContext &selectionState)
+{
+ if (!selectionState.qmlModelView()
+ || selectionState.selectedModelNodes().isEmpty())
+ return;
+
+ try {
+ selectionState.selectedModelNodes().first().variantProperty("Layout.fillWidth") = selectionState.toggled();
+ } catch (RewritingException &e) { //better save then sorry
+ QMessageBox::warning(0, "Error", e.description());
+ }
+}
+
+void setFillHeight(const SelectionContext &selectionState)
+{
+ if (!selectionState.qmlModelView()
+ || selectionState.selectedModelNodes().isEmpty())
+ return;
+
+ try {
+ selectionState.selectedModelNodes().first().variantProperty("Layout.fillHeight") = selectionState.toggled();
+ } catch (RewritingException &e) { //better save then sorry
+ QMessageBox::warning(0, "Error", e.description());
+ }
+}
void resetSize(const SelectionContext &selectionState)
{
@@ -420,7 +445,7 @@ static inline QPoint getUpperLeftPosition(const QList<ModelNode> &modelNodeList)
return p;
}
-void layoutRow(const SelectionContext &selectionState)
+void layoutRowPositioner(const SelectionContext &selectionState)
{
if (!selectionState.qmlModelView())
return;
@@ -465,7 +490,7 @@ void layoutRow(const SelectionContext &selectionState)
}
}
-void layoutColumn(const SelectionContext &selectionState)
+void layoutColumnPositioner(const SelectionContext &selectionState)
{
if (!selectionState.qmlModelView())
return;
@@ -508,7 +533,7 @@ void layoutColumn(const SelectionContext &selectionState)
}
}
-void layoutGrid(const SelectionContext &selectionState)
+void layoutGridPositioner(const SelectionContext &selectionState)
{
if (!selectionState.qmlModelView())
return;
@@ -552,7 +577,7 @@ void layoutGrid(const SelectionContext &selectionState)
}
}
-void layoutFlow(const SelectionContext &selectionState)
+void layoutFlowPositioner(const SelectionContext &selectionState)
{
if (!selectionState.qmlModelView())
return;
@@ -595,6 +620,151 @@ void layoutFlow(const SelectionContext &selectionState)
}
}
+void layoutRowLayout(const SelectionContext &selectionState)
+{
+ if (!selectionState.qmlModelView()
+ || selectionState.selectedModelNodes().isEmpty())
+ return;
+
+ static TypeName rowLayoutType = "QtQuick.Layouts.RowLayout";
+
+ if (!selectionState.qmlModelView()->model()->hasNodeMetaInfo(rowLayoutType))
+ return;
+
+ NodeMetaInfo rowMetaInfo = selectionState.qmlModelView()->model()->metaInfo(rowLayoutType);
+
+ QList<ModelNode> selectedNodeList = selectionState.selectedModelNodes();
+ QmlItemNode qmlItemNode = QmlItemNode(selectedNodeList.first());
+
+ if (qmlItemNode.isValid() && qmlItemNode.hasInstanceParentItem()) {
+
+ ModelNode rowNode;
+ {
+ RewriterTransaction transaction(selectionState.qmlModelView());
+
+ QmlItemNode parentNode = qmlItemNode.instanceParentItem();
+
+ rowNode = selectionState.qmlModelView()->createModelNode(rowLayoutType, rowMetaInfo.majorVersion(), rowMetaInfo.minorVersion());
+
+ reparentTo(rowNode, parentNode);
+ }
+
+ {
+ RewriterTransaction transaction(selectionState.qmlModelView());
+
+ QPoint upperLeftPosition = getUpperLeftPosition(selectedNodeList);
+ rowNode.variantProperty("x") = upperLeftPosition.x();
+ rowNode.variantProperty("y") = upperLeftPosition.y();
+
+ QList<ModelNode> sortedSelectedNodes = selectedNodeList;
+ qSort(sortedSelectedNodes.begin(), sortedSelectedNodes.end(), compareByX);
+
+ foreach (ModelNode selectedNode, sortedSelectedNodes) {
+ reparentTo(selectedNode, rowNode);
+ selectedNode.removeProperty("x");
+ selectedNode.removeProperty("y");
+ }
+ }
+ }
+}
+
+void layoutColumnLayout(const SelectionContext &selectionState)
+{
+ if (!selectionState.qmlModelView()
+ || selectionState.selectedModelNodes().isEmpty())
+ return;
+
+ static TypeName columnLayoutType = "QtQuick.Layouts.ColumnLayout";
+
+ if (!selectionState.qmlModelView()->model()->hasNodeMetaInfo(columnLayoutType))
+ return;
+
+ NodeMetaInfo columnMetaInfo = selectionState.qmlModelView()->model()->metaInfo(columnLayoutType);
+
+ QList<ModelNode> selectedNodeList = selectionState.selectedModelNodes();
+ QmlItemNode qmlItemNode = QmlItemNode(selectedNodeList.first());
+
+ if (qmlItemNode.isValid() && qmlItemNode.hasInstanceParentItem()) {
+
+ ModelNode columnNode;
+ {
+ RewriterTransaction transaction(selectionState.qmlModelView());
+
+ QmlItemNode parentNode = qmlItemNode.instanceParentItem();
+
+ columnNode = selectionState.qmlModelView()->createModelNode(columnLayoutType, columnMetaInfo.majorVersion(), columnMetaInfo.minorVersion());
+
+ reparentTo(columnNode, parentNode);
+ }
+
+ {
+ RewriterTransaction transaction(selectionState.qmlModelView());
+
+ QPoint upperLeftPosition = getUpperLeftPosition(selectedNodeList);
+ columnNode.variantProperty("x") = upperLeftPosition.x();
+ columnNode.variantProperty("y") = upperLeftPosition.y();
+
+ QList<ModelNode> sortedSelectedNodes = selectedNodeList;
+ qSort(sortedSelectedNodes.begin(), sortedSelectedNodes.end(), compareByY);
+
+ foreach (ModelNode selectedNode, sortedSelectedNodes) {
+ reparentTo(selectedNode, columnNode);
+ selectedNode.removeProperty("x");
+ selectedNode.removeProperty("y");
+ }
+ }
+ }
+}
+
+void layoutGridLayout(const SelectionContext &selectionState)
+{
+ if (!selectionState.qmlModelView()
+ || selectionState.selectedModelNodes().isEmpty())
+ return;
+
+ static TypeName gridLayoutType = "QtQuick.Layouts.GridLayout";
+
+ if (!selectionState.qmlModelView()->model()->hasNodeMetaInfo(gridLayoutType))
+ return;
+
+ NodeMetaInfo gridMetaInfo = selectionState.qmlModelView()->model()->metaInfo(gridLayoutType);
+
+ QList<ModelNode> selectedNodeList = selectionState.selectedModelNodes();
+ QmlItemNode qmlItemNode = QmlItemNode(selectedNodeList.first());
+
+ if (qmlItemNode.isValid() && qmlItemNode.hasInstanceParentItem()) {
+
+ ModelNode gridNode;
+ {
+ RewriterTransaction transaction(selectionState.qmlModelView());
+
+ QmlItemNode parentNode = qmlItemNode.instanceParentItem();
+
+ gridNode = selectionState.qmlModelView()->createModelNode(gridLayoutType, gridMetaInfo.majorVersion(), gridMetaInfo.minorVersion());
+ gridNode.variantProperty("columns") = int(sqrt(double(selectedNodeList.count())));
+
+ reparentTo(gridNode, parentNode);
+ }
+
+ {
+ RewriterTransaction transaction(selectionState.qmlModelView());
+
+ QPoint upperLeftPosition = getUpperLeftPosition(selectedNodeList);
+ gridNode.variantProperty("x") = upperLeftPosition.x();
+ gridNode.variantProperty("y") = upperLeftPosition.y();
+
+ QList<ModelNode> sortedSelectedNodes = selectedNodeList;
+ qSort(sortedSelectedNodes.begin(), sortedSelectedNodes.end(), compareByGrid);
+
+ foreach (ModelNode selectedNode, sortedSelectedNodes) {
+ reparentTo(selectedNode, gridNode);
+ selectedNode.removeProperty("x");
+ selectedNode.removeProperty("y");
+ }
+ }
+ }
+}
+
} // namespace Mode
} //QmlDesigner
diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h
index 7905961230..a94421a8a8 100644
--- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h
+++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.h
@@ -52,6 +52,8 @@ void paste(const SelectionContext &selectionState);
void undo(const SelectionContext &selectionState);
void redo(const SelectionContext &selectionState);
void setVisible(const SelectionContext &selectionState);
+void setFillWidth(const SelectionContext &selectionState);
+void setFillHeight(const SelectionContext &selectionState);
void resetSize(const SelectionContext &selectionState);
void resetPosition(const SelectionContext &selectionState);
void goIntoComponent(const SelectionContext &selectionState);
@@ -59,10 +61,14 @@ void setId(const SelectionContext &selectionState);
void resetZ(const SelectionContext &selectionState);
void anchorsFill(const SelectionContext &selectionState);
void anchorsReset(const SelectionContext &selectionState);
-void layoutRow(const SelectionContext &selectionState);
-void layoutColumn(const SelectionContext &selectionState);
-void layoutGrid(const SelectionContext &selectionState);
-void layoutFlow(const SelectionContext &selectionState);
+void layoutRowPositioner(const SelectionContext &selectionState);
+void layoutColumnPositioner(const SelectionContext &selectionState);
+void layoutGridPositioner(const SelectionContext &selectionState);
+void layoutFlowPositioner(const SelectionContext &selectionState);
+void layoutRowLayout(const SelectionContext &selectionState);
+void layoutColumnLayout(const SelectionContext &selectionState);
+void layoutGridLayout(const SelectionContext &selectionState);
+
} // namespace ModelNodeOperationso
} //QmlDesigner