1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
31 **************************************************************************/
33 #include "formeditorwidget.h"
34 #include "qmldesignerplugin.h"
35 #include "designersettings.h"
37 #include <QWheelEvent>
39 #include <QCoreApplication>
40 #include <QPushButton>
42 #include <QVBoxLayout>
43 #include <QActionGroup>
44 #include <QGraphicsView>
46 #include <zoomaction.h>
47 #include <formeditorgraphicsview.h>
48 #include <formeditorscene.h>
49 #include <formeditorview.h>
50 #include <lineeditaction.h>
52 namespace QmlDesigner {
54 FormEditorWidget::FormEditorWidget(FormEditorView *view)
56 m_formEditorView(view)
58 QFile file(":/qmldesigner/formeditorstylesheet.css");
59 file.open(QFile::ReadOnly);
60 QString styleSheet = QLatin1String(file.readAll());
61 setStyleSheet(styleSheet);
63 QVBoxLayout *fillLayout = new QVBoxLayout(this);
64 fillLayout->setMargin(0);
65 fillLayout->setSpacing(0);
66 setLayout(fillLayout);
68 QList<QAction*> upperActions;
70 m_toolActionGroup = new QActionGroup(this);
72 m_transformToolAction = m_toolActionGroup->addAction("Transform Tool (Press Key Q)");
73 m_transformToolAction->setShortcut(Qt::Key_Q);
74 m_transformToolAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
75 m_transformToolAction->setCheckable(true);
76 m_transformToolAction->setChecked(true);
77 m_transformToolAction->setIcon(QPixmap(":/icon/tool/transform.png"));
78 connect(m_transformToolAction.data(), SIGNAL(triggered(bool)), SLOT(changeTransformTool(bool)));
80 m_anchorToolAction = m_toolActionGroup->addAction("Anchor Tool (Press Key W)");
81 m_anchorToolAction->setShortcut(Qt::Key_W);
82 m_anchorToolAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
83 m_anchorToolAction->setCheckable(true);
84 m_anchorToolAction->setIcon(QPixmap(":/icon/tool/anchor.png"));
85 connect(m_anchorToolAction.data(), SIGNAL(triggered(bool)), SLOT(changeAnchorTool(bool)));
87 // addActions(m_toolActionGroup->actions());
88 // upperActions.append(m_toolActionGroup->actions());
90 QActionGroup *layoutActionGroup = new QActionGroup(this);
91 layoutActionGroup->setExclusive(false);
92 m_snappingAction = layoutActionGroup->addAction(tr("Snap to guides (E)"));
93 m_snappingAction->setShortcut(Qt::Key_E);
94 m_snappingAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
95 m_snappingAction->setCheckable(true);
96 m_snappingAction->setChecked(true);
97 m_snappingAction->setIcon(QPixmap(":/icon/layout/snapping.png"));
99 m_snappingAndAnchoringAction = layoutActionGroup->addAction("Toogle Snapping And Anchoring (Press Key R)");
100 m_snappingAndAnchoringAction->setShortcut(Qt::Key_R);
101 m_snappingAndAnchoringAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
102 m_snappingAndAnchoringAction->setCheckable(true);
103 m_snappingAndAnchoringAction->setChecked(false);
104 m_snappingAndAnchoringAction->setEnabled(false);
105 m_snappingAndAnchoringAction->setVisible(false);
106 m_snappingAndAnchoringAction->setIcon(QPixmap(":/icon/layout/snapping_and_anchoring.png"));
108 addActions(layoutActionGroup->actions());
109 upperActions.append(layoutActionGroup->actions());
111 QAction *separatorAction = new QAction(this);
112 separatorAction->setSeparator(true);
113 addAction(separatorAction);
114 upperActions.append(separatorAction);
116 m_showBoundingRectAction = new QAction(tr("Show bounding rectangles (A)"), this);
117 m_showBoundingRectAction->setShortcut(Qt::Key_A);
118 m_showBoundingRectAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
119 m_showBoundingRectAction->setCheckable(true);
120 m_showBoundingRectAction->setChecked(true);
121 m_showBoundingRectAction->setIcon(QPixmap(":/icon/layout/boundingrect.png"));
123 addAction(m_showBoundingRectAction.data());
124 upperActions.append(m_showBoundingRectAction.data());
126 m_selectOnlyContentItemsAction = new QAction(tr("Only select items with content (S)"), this);
127 m_selectOnlyContentItemsAction->setShortcut(Qt::Key_S);
128 m_selectOnlyContentItemsAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
129 m_selectOnlyContentItemsAction->setCheckable(true);
130 m_selectOnlyContentItemsAction->setChecked(false);
131 m_selectOnlyContentItemsAction->setIcon(QPixmap(":/icon/selection/selectonlycontentitems.png"));
133 addAction(m_selectOnlyContentItemsAction.data());
134 upperActions.append(m_selectOnlyContentItemsAction.data());
136 m_rootWidthAction = new LineEditAction("width", this);
137 connect(m_rootWidthAction.data(), SIGNAL(textChanged(QString)), this, SLOT(changeRootItemWidth(QString)));
138 addAction(m_rootWidthAction.data());
139 upperActions.append(m_rootWidthAction.data());
141 m_rootHeightAction = new LineEditAction("height", this);
142 connect(m_rootHeightAction.data(), SIGNAL(textChanged(QString)), this, SLOT(changeRootItemHeight(QString)));
143 addAction(m_rootHeightAction.data());
144 upperActions.append(m_rootHeightAction.data());
146 m_snappingAndAnchoringAction = layoutActionGroup->addAction("Toogle Snapping And Anchoring (Press Key R)");
148 m_toolBox = new ToolBox(this);
149 fillLayout->addWidget(m_toolBox.data());
150 m_toolBox->setLeftSideActions(upperActions);
152 m_graphicsView = new FormEditorGraphicsView(this);
153 fillLayout->addWidget(m_graphicsView.data());
156 QFile file(":/qmldesigner/scrollbar.css");
157 file.open(QFile::ReadOnly);
158 m_graphicsView.data()->setStyleSheet(file.readAll());
161 QList<QAction*> lowerActions;
163 m_zoomAction = new ZoomAction(m_toolActionGroup.data());
164 connect(m_zoomAction.data(), SIGNAL(zoomLevelChanged(double)), SLOT(setZoomLevel(double)));
165 addAction(m_zoomAction.data());
166 upperActions.append(m_zoomAction.data());
167 m_toolBox->addRightSideAction(m_zoomAction.data());
169 m_resetAction = new QAction(tr("Reset view (R)"), this);
170 m_resetAction->setShortcut(Qt::Key_R);
171 m_resetAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
172 m_resetAction->setIcon(QPixmap(":/icon/reset.png"));
173 connect(m_resetAction.data(), SIGNAL(triggered(bool)), this, SLOT(resetNodeInstanceView()));
174 addAction(m_resetAction.data());
175 upperActions.append(m_resetAction.data());
176 m_toolBox->addRightSideAction(m_resetAction.data());
179 void FormEditorWidget::enterEvent(QEvent *event)
181 m_graphicsView->setFocus();
182 QWidget::enterEvent(event);
185 void FormEditorWidget::changeTransformTool(bool checked)
189 m_formEditorView->changeToTransformTools();
192 void FormEditorWidget::changeRootItemWidth(const QString &widthText)
195 int width = widthText.toInt(&canConvert);
197 m_formEditorView->rootModelNode().setAuxiliaryData("width", width);
199 m_formEditorView->rootModelNode().setAuxiliaryData("width", QVariant());
203 void FormEditorWidget::changeRootItemHeight(const QString &heighText)
206 int height = heighText.toInt(&canConvert);
208 m_formEditorView->rootModelNode().setAuxiliaryData("height", height);
210 m_formEditorView->rootModelNode().setAuxiliaryData("height", QVariant());
214 void FormEditorWidget::resetNodeInstanceView()
216 m_formEditorView->setCurrentState(m_formEditorView->baseState());
217 m_formEditorView->emitCustomNotification(QLatin1String("reset QmlPuppet"));
220 void FormEditorWidget::changeAnchorTool(bool checked)
222 if (checked && m_formEditorView->currentState().isBaseState())
223 m_formEditorView->changeToAnchorTool();
226 void FormEditorWidget::wheelEvent(QWheelEvent *event)
228 if (event->modifiers().testFlag(Qt::ControlModifier)) {
229 if (event->delta() > 0) {
230 zoomAction()->zoomOut();
232 zoomAction()->zoomIn();
237 QWidget::wheelEvent(event);
242 void FormEditorWidget::updateActions()
244 if (m_formEditorView->model() && m_formEditorView->rootModelNode().isValid()) {
245 if (m_formEditorView->rootModelNode().hasAuxiliaryData("width") && m_formEditorView->rootModelNode().auxiliaryData("width").isValid()) {
246 m_rootWidthAction->setLineEditText(m_formEditorView->rootModelNode().auxiliaryData("width").toString());
248 m_rootWidthAction->clearLineEditText();
250 if (m_formEditorView->rootModelNode().hasAuxiliaryData("height") && m_formEditorView->rootModelNode().auxiliaryData("height").isValid()) {
251 m_rootHeightAction->setLineEditText(m_formEditorView->rootModelNode().auxiliaryData("height").toString());
253 m_rootHeightAction->clearLineEditText();
256 m_rootWidthAction->clearLineEditText();
257 m_rootHeightAction->clearLineEditText();
262 void FormEditorWidget::resetView()
264 setRootItemRect(QRectF());
267 void FormEditorWidget::centerScene()
269 m_graphicsView->centerOn(rootItemRect().center());
272 ZoomAction *FormEditorWidget::zoomAction() const
274 return m_zoomAction.data();
277 QAction *FormEditorWidget::anchorToolAction() const
279 return m_anchorToolAction.data();
282 QAction *FormEditorWidget::transformToolAction() const
284 return m_transformToolAction.data();
287 QAction *FormEditorWidget::showBoundingRectAction() const
289 return m_showBoundingRectAction.data();
292 QAction *FormEditorWidget::selectOnlyContentItemsAction() const
294 return m_selectOnlyContentItemsAction.data();
297 QAction *FormEditorWidget::snappingAction() const
299 return m_snappingAction.data();
302 QAction *FormEditorWidget::snappingAndAnchoringAction() const
304 return m_snappingAndAnchoringAction.data();
307 void FormEditorWidget::setZoomLevel(double zoomLevel)
309 m_graphicsView->resetTransform();
311 m_graphicsView->scale(zoomLevel, zoomLevel);
314 void FormEditorWidget::setScene(FormEditorScene *scene)
316 m_graphicsView->setScene(scene);
319 QActionGroup *FormEditorWidget::toolActionGroup() const
321 return m_toolActionGroup.data();
324 ToolBox *FormEditorWidget::toolBox() const
326 return m_toolBox.data();
329 double FormEditorWidget::spacing() const
331 DesignerSettings settings = Internal::BauhausPlugin::pluginInstance()->settings();
332 return settings.itemSpacing;
335 double FormEditorWidget::margins() const
337 DesignerSettings settings = Internal::BauhausPlugin::pluginInstance()->settings();
338 return settings.snapMargin;
341 void FormEditorWidget::setFeedbackNode(const QmlItemNode &node)
343 m_graphicsView->setFeedbackNode(node);
346 QString FormEditorWidget::contextHelpId() const
348 if (!m_formEditorView)
351 QList<ModelNode> nodes = m_formEditorView->selectedModelNodes();
353 if (!nodes.isEmpty()) {
354 helpId = nodes.first().type();
355 helpId.replace("QtQuick", "QML");
361 void FormEditorWidget::setRootItemRect(const QRectF &rect)
363 m_graphicsView->setRootItemRect(rect);
366 QRectF FormEditorWidget::rootItemRect() const
368 return m_graphicsView->rootItemRect();