diff options
Diffstat (limited to 'src/plugins')
62 files changed, 2662 insertions, 1938 deletions
diff --git a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp index 0ead22317d..cdce831037 100644 --- a/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp +++ b/src/plugins/qmldesigner/components/componentcore/designeractionmanager.cpp @@ -186,6 +186,11 @@ public: m_designerActionList = designerActionList; } + QWidget *widget() + { + return 0; + } + protected: void setupContext() { diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.cpp index 3db5ff0e62..4cddd48293 100644 --- a/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.cpp +++ b/src/plugins/qmldesigner/components/componentcore/modelnodecontextmenu_helper.cpp @@ -35,12 +35,13 @@ #include <bindingproperty.h> #include <nodeproperty.h> #include <designmodewidget.h> +#include <qmldesignerplugin.h> namespace QmlDesigner { -static inline DesignDocumentController* designDocumentController() +static inline DesignDocument* currentDesignDocument() { - return Internal::DesignModeWidget::instance()->currentDesignDocumentController(); + return QmlDesignerPlugin::instance()->documentManager().currentDesignDocument(); } static inline bool checkIfNodeIsAView(const ModelNode &node) @@ -103,14 +104,14 @@ static inline bool modelNodeIsComponent(const ModelNode &node) if (!node.isValid() || !node.metaInfo().isValid()) return false; - if (node.metaInfo().isComponent()) + if (node.metaInfo().isFileComponent()) return true; if (node.nodeSourceType() == ModelNode::NodeWithComponentSource) return true; if (checkIfNodeIsAView(node) && node.hasNodeProperty("delegate")) { - if (node.nodeProperty("delegate").modelNode().metaInfo().isComponent()) + if (node.nodeProperty("delegate").modelNode().metaInfo().isFileComponent()) return true; if (node.nodeProperty("delegate").modelNode().nodeSourceType() == ModelNode::NodeWithComponentSource) return true; @@ -156,12 +157,12 @@ static inline bool isFileComponent(const ModelNode &node) if (!node.isValid() || !node.metaInfo().isValid()) return false; - if (node.metaInfo().isComponent()) + if (node.metaInfo().isFileComponent()) return true; if (checkIfNodeIsAView(node) && node.hasNodeProperty("delegate")) { - if (node.nodeProperty("delegate").modelNode().metaInfo().isComponent()) + if (node.nodeProperty("delegate").modelNode().metaInfo().isFileComponent()) return true; } @@ -170,21 +171,23 @@ static inline bool isFileComponent(const ModelNode &node) static inline void openFileForComponent(const ModelNode &node) { + QmlDesignerPlugin::instance()->viewManager().nextFileIsCalledInternally(); + //int width = 0; //int height = 0; QHash<QString, QVariant> propertyHash; - if (node.metaInfo().isComponent()) { + if (node.metaInfo().isFileComponent()) { //getWidthHeight(node, width, height); getProperties(node, propertyHash); - designDocumentController()->changeToExternalSubComponent(node.metaInfo().componentFileName()); + currentDesignDocument()->changeToExternalSubComponent(node.metaInfo().componentFileName()); } else if (checkIfNodeIsAView(node) && node.hasNodeProperty("delegate") && - node.nodeProperty("delegate").modelNode().metaInfo().isComponent()) { + node.nodeProperty("delegate").modelNode().metaInfo().isFileComponent()) { //getWidthHeight(node, width, height); getProperties(node, propertyHash); - designDocumentController()->changeToExternalSubComponent(node.nodeProperty("delegate").modelNode().metaInfo().componentFileName()); + currentDesignDocument()->changeToExternalSubComponent(node.nodeProperty("delegate").modelNode().metaInfo().componentFileName()); } - ModelNode rootModelNode = designDocumentController()->model()->rewriterView()->rootModelNode(); + ModelNode rootModelNode = currentDesignDocument()->rewriterView()->rootModelNode(); applyProperties(rootModelNode, propertyHash); //rootModelNode.setAuxiliaryData("width", width); //rootModelNode.setAuxiliaryData("height", height); @@ -192,10 +195,11 @@ static inline void openFileForComponent(const ModelNode &node) static inline void openInlineComponent(const ModelNode &node) { + if (!node.isValid() || !node.metaInfo().isValid()) return; - if (!designDocumentController()) + if (!currentDesignDocument()) return; QHash<QString, QVariant> propertyHash; @@ -203,27 +207,27 @@ static inline void openInlineComponent(const ModelNode &node) if (node.nodeSourceType() == ModelNode::NodeWithComponentSource) { //getWidthHeight(node, width, height); getProperties(node, propertyHash); - designDocumentController()->changeToSubComponent(node); + currentDesignDocument()->changeToSubComponent(node); } else if (checkIfNodeIsAView(node) && node.hasNodeProperty("delegate")) { if (node.nodeProperty("delegate").modelNode().nodeSourceType() == ModelNode::NodeWithComponentSource) { //getWidthHeight(node, width, height); getProperties(node, propertyHash); - designDocumentController()->changeToSubComponent(node.nodeProperty("delegate").modelNode()); + currentDesignDocument()->changeToSubComponent(node.nodeProperty("delegate").modelNode()); } } - ModelNode rootModelNode = designDocumentController()->model()->rewriterView()->rootModelNode(); + ModelNode rootModelNode = currentDesignDocument()->rewriterView()->rootModelNode(); applyProperties(rootModelNode, propertyHash); //rootModelNode.setAuxiliaryData("width", width); //rootModelNode.setAuxiliaryData("height", height); } namespace ComponentUtils { - void goIntoComponent(const ModelNode &modelNode) { if (modelNode.isValid() && modelNodeIsComponent(modelNode)) { + QmlDesignerPlugin::instance()->viewManager().setComponentNode(modelNode); if (isFileComponent(modelNode)) openFileForComponent(modelNode); else diff --git a/src/plugins/qmldesigner/components/formeditor/formeditor.pri b/src/plugins/qmldesigner/components/formeditor/formeditor.pri index f353e868ee..f2ca8013c9 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditor.pri +++ b/src/plugins/qmldesigner/components/formeditor/formeditor.pri @@ -32,7 +32,8 @@ SOURCES += formeditoritem.cpp \ zoomaction.cpp \ formeditorgraphicsview.cpp \ numberseriesaction.cpp \ - lineeditaction.cpp + lineeditaction.cpp \ + formeditorcrumblebar.cpp HEADERS += formeditorscene.h \ formeditorwidget.h \ formeditoritem.h \ @@ -63,5 +64,6 @@ HEADERS += formeditorscene.h \ zoomaction.h \ formeditorgraphicsview.h \ numberseriesaction.h \ - lineeditaction.h + lineeditaction.h \ + formeditorcrumblebar.h RESOURCES += formeditor.qrc diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorcrumblebar.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorcrumblebar.cpp new file mode 100644 index 0000000000..8e009b6aae --- /dev/null +++ b/src/plugins/qmldesigner/components/formeditor/formeditorcrumblebar.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "formeditorcrumblebar.h" + +#include "qmldesignerplugin.h" + +#include <QVariant> +#include <QtDebug> + +namespace QmlDesigner { + +FormEditorCrumbleBar::FormEditorCrumbleBar(QObject *parent) : + QObject(parent), + m_isInternalCalled(false), + m_crumblePath(new Utils::CrumblePath) +{ + connect(m_crumblePath, + SIGNAL(elementClicked(QVariant)), + this, + SLOT(onCrumblePathElementClicked(QVariant))); +} + +void FormEditorCrumbleBar::pushFile(const QString &fileName) +{ + if (m_isInternalCalled == false) + crumblePath()->clear(); + + CrumbleBarInfo crumbleBarInfo; + crumbleBarInfo.fileName = fileName; + + crumblePath()->pushElement(fileName.split("/").last(), QVariant::fromValue(crumbleBarInfo)); + + m_isInternalCalled = false; +} + +static DesignDocument *currentDesignDocument() +{ + return QmlDesignerPlugin::instance()->documentManager().currentDesignDocument(); +} + +void FormEditorCrumbleBar::pushInFileComponent(const QString &componentId) +{ + CrumbleBarInfo crumbleBarInfo; + crumbleBarInfo.componentId = componentId; + crumbleBarInfo.fileName = currentDesignDocument()->textEditor()->document()->fileName(); + + CrumbleBarInfo lastElementCrumbleBarInfo = crumblePath()->dataForLastIndex().value<CrumbleBarInfo>(); + + if (!lastElementCrumbleBarInfo.componentId.isEmpty()) + crumblePath()->popElement(); + + crumblePath()->pushElement(componentId, QVariant::fromValue(crumbleBarInfo)); +} + +void FormEditorCrumbleBar::nextFileIsCalledInternally() +{ + m_isInternalCalled = true; +} + +Utils::CrumblePath *FormEditorCrumbleBar::crumblePath() +{ + return m_crumblePath; +} + +void FormEditorCrumbleBar::onCrumblePathElementClicked(const QVariant &data) +{ + CrumbleBarInfo crumbleBarInfo = data.value<CrumbleBarInfo>(); + + if (crumbleBarInfo == crumblePath()->dataForLastIndex().value<CrumbleBarInfo>()) + return; + + while (crumbleBarInfo != crumblePath()->dataForLastIndex().value<CrumbleBarInfo>()) + crumblePath()->popElement(); + + if (!crumbleBarInfo.componentId.isEmpty()) + crumblePath()->popElement(); + + crumblePath()->popElement(); + + m_isInternalCalled = true; + Core::EditorManager::openEditor(crumbleBarInfo.fileName); + if (!crumbleBarInfo.componentId.isEmpty()) + currentDesignDocument()->changeToSubComponent(currentDesignDocument()->rewriterView()->modelNodeForId(crumbleBarInfo.componentId)); +} + +bool operator ==(const CrumbleBarInfo &first, const CrumbleBarInfo &second) +{ + return first.fileName == second.fileName && first.componentId == second.componentId; +} + +bool operator !=(const CrumbleBarInfo &first, const CrumbleBarInfo &second) +{ + return first.fileName != second.fileName || first.componentId != second.componentId; +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorcrumblebar.h b/src/plugins/qmldesigner/components/formeditor/formeditorcrumblebar.h new file mode 100644 index 0000000000..18069a0ca2 --- /dev/null +++ b/src/plugins/qmldesigner/components/formeditor/formeditorcrumblebar.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLDESIGNER_FORMEDITORCRUMBLEBAR_H +#define QMLDESIGNER_FORMEDITORCRUMBLEBAR_H + +#include <QObject> +#include <utils/crumblepath.h> + +namespace QmlDesigner { + + + +class FormEditorCrumbleBar : public QObject +{ + Q_OBJECT +public: + explicit FormEditorCrumbleBar(QObject *parent = 0); + + void pushFile(const QString &fileName); + void pushInFileComponent(const QString &componentId); + + void nextFileIsCalledInternally(); + + Utils::CrumblePath *crumblePath(); + +private slots: + void onCrumblePathElementClicked(const QVariant &data); + +private: + bool m_isInternalCalled; + Utils::CrumblePath *m_crumblePath; +}; + +class CrumbleBarInfo { +public: + QString fileName; + QString componentId; +}; + +bool operator ==(const CrumbleBarInfo &first, const CrumbleBarInfo &second); +bool operator !=(const CrumbleBarInfo &first, const CrumbleBarInfo &second); +} // namespace QmlDesigner + +Q_DECLARE_METATYPE(QmlDesigner::CrumbleBarInfo) + +#endif // QMLDESIGNER_FORMEDITORCRUMBLEBAR_H diff --git a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp index 3178bebe72..27a973c45d 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp @@ -317,6 +317,9 @@ void FormEditorItem::paintPlaceHolderForInvisbleItem(QPainter *painter) const void FormEditorItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { + if (!painter->isActive()) + return; + if (!qmlItemNode().isValid()) return; diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp index 1cda0c1c09..7af29f8ce4 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp @@ -65,7 +65,6 @@ FormEditorScene::FormEditorScene(FormEditorWidget *view, FormEditorView *editorV setupScene(); view->setScene(this); setItemIndexMethod(QGraphicsScene::NoIndex); - setSceneRect(-canvasWidth()/2., -canvasHeight()/2., canvasWidth(), canvasHeight()); } FormEditorScene::~FormEditorScene() @@ -100,13 +99,13 @@ FormEditorItem* FormEditorScene::itemForQmlItemNode(const QmlItemNode &qmlItemNo double FormEditorScene::canvasWidth() const { - DesignerSettings settings = Internal::BauhausPlugin::pluginInstance()->settings(); + DesignerSettings settings = QmlDesignerPlugin::instance()->settings(); return settings.canvasWidth; } double FormEditorScene::canvasHeight() const { - DesignerSettings settings = Internal::BauhausPlugin::pluginInstance()->settings(); + DesignerSettings settings = QmlDesignerPlugin::instance()->settings(); return settings.canvasHeight; } @@ -217,6 +216,7 @@ FormEditorItem *FormEditorScene::addFormEditorItem(const QmlItemNode &qmlItemNod m_qmlItemNodeItemHash.insert(qmlItemNode, formEditorItem); if (qmlItemNode.isRootNode()) { + setSceneRect(-canvasWidth()/2., -canvasHeight()/2., canvasWidth(), canvasHeight()); formLayerItem()->update(); manipulatorLayerItem()->update(); } diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp index c15437fe5f..ac4b3bc078 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp @@ -68,9 +68,9 @@ FormEditorView::FormEditorView(QObject *parent) m_currentTool(m_selectionTool), m_transactionCounter(0) { - connect(widget()->zoomAction(), SIGNAL(zoomLevelChanged(double)), SLOT(updateGraphicsIndicators())); - connect(widget()->showBoundingRectAction(), SIGNAL(toggled(bool)), scene(), SLOT(setShowBoundingRects(bool))); - connect(widget()->selectOnlyContentItemsAction(), SIGNAL(toggled(bool)), this, SLOT(setSelectOnlyContentItemsAction(bool))); + connect(formEditorWidget()->zoomAction(), SIGNAL(zoomLevelChanged(double)), SLOT(updateGraphicsIndicators())); + connect(formEditorWidget()->showBoundingRectAction(), SIGNAL(toggled(bool)), scene(), SLOT(setShowBoundingRects(bool))); + connect(formEditorWidget()->selectOnlyContentItemsAction(), SIGNAL(toggled(bool)), this, SLOT(setSelectOnlyContentItemsAction(bool))); } @@ -267,9 +267,13 @@ void FormEditorView::bindingPropertiesChanged(const QList<BindingProperty>& prop QmlModelView::bindingPropertiesChanged(propertyList, propertyChange); } -FormEditorWidget *FormEditorView::widget() const +QWidget *FormEditorView::widget() +{ + return m_formEditorWidget.data(); +} + +FormEditorWidget *FormEditorView::formEditorWidget() { - Q_ASSERT(!m_formEditorWidget.isNull()); return m_formEditorWidget.data(); } @@ -453,8 +457,8 @@ void FormEditorView::instanceInformationsChange(const QMultiHash<ModelNode, Info if (qmlItemNode.isValid() && scene()->hasItemForQmlItemNode(qmlItemNode)) { scene()->synchronizeTransformation(qmlItemNode); if (qmlItemNode.isRootModelNode() && informationChangeHash.values(node).contains(Size)) { - widget()->setRootItemRect(qmlItemNode.instanceBoundingRect()); - widget()->centerScene(); + formEditorWidget()->setRootItemRect(qmlItemNode.instanceBoundingRect()); + formEditorWidget()->centerScene(); } itemNodeList.append(scene()->itemForQmlItemNode(qmlItemNode)); @@ -588,13 +592,6 @@ void FormEditorView::actualStateChanged(const ModelNode &node) QmlModelState newQmlModelState(node); } -Utils::CrumblePath *FormEditorView::crumblePath() const -{ - if (widget() && widget()->toolBox()) - return widget()->toolBox()->crumblePath(); - return 0; -} - void FormEditorView::reset() { QTimer::singleShot(200, this, SLOT(delayedReset())); diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.h b/src/plugins/qmldesigner/components/formeditor/formeditorview.h index 240f42249c..f93f8ff186 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorview.h +++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.h @@ -61,7 +61,7 @@ class FormEditorView : public QmlModelView Q_OBJECT public: - FormEditorView(QObject *parent); + FormEditorView(QObject *parent = 0); ~FormEditorView(); // AbstractView @@ -85,7 +85,8 @@ public: void propertiesRemoved(const QList<AbstractProperty> &propertyList); // FormEditorView - FormEditorWidget *widget() const; + QWidget *widget(); + FormEditorWidget *formEditorWidget(); AbstractFormEditorTool *currentTool() const; FormEditorScene *scene() const; @@ -117,8 +118,6 @@ public: void actualStateChanged(const ModelNode &node); - Utils::CrumblePath *crumblePath() const; - protected: void reset(); diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp index 498c2bcbe6..6957f7af23 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp @@ -241,6 +241,11 @@ void FormEditorWidget::setFocus() m_graphicsView->setFocus(Qt::OtherFocusReason); } +FormEditorCrumbleBar *FormEditorWidget::formEditorCrumbleBar() const +{ + return toolBox()->formEditorCrumbleBar(); +} + ZoomAction *FormEditorWidget::zoomAction() const { return m_zoomAction.data(); @@ -295,13 +300,13 @@ ToolBox *FormEditorWidget::toolBox() const double FormEditorWidget::spacing() const { - DesignerSettings settings = Internal::BauhausPlugin::pluginInstance()->settings(); + DesignerSettings settings = QmlDesignerPlugin::instance()->settings(); return settings.itemSpacing; } double FormEditorWidget::margins() const { - DesignerSettings settings = Internal::BauhausPlugin::pluginInstance()->settings(); + DesignerSettings settings = QmlDesignerPlugin::instance()->settings(); return settings.snapMargin; } diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h index 90e5fd4c3b..a6bbb33cbe 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h +++ b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h @@ -32,6 +32,8 @@ #include <QWidget> +#include "formeditorcrumblebar.h" + QT_BEGIN_NAMESPACE class QActionGroup; QT_END_NAMESPACE @@ -78,6 +80,8 @@ public: void setFocus(); + FormEditorCrumbleBar *formEditorCrumbleBar() const; + protected: void wheelEvent(QWheelEvent *event); QActionGroup *toolActionGroup() const; diff --git a/src/plugins/qmldesigner/components/formeditor/movetool.cpp b/src/plugins/qmldesigner/components/formeditor/movetool.cpp index b34c0240c8..219a6aac84 100644 --- a/src/plugins/qmldesigner/components/formeditor/movetool.cpp +++ b/src/plugins/qmldesigner/components/formeditor/movetool.cpp @@ -106,8 +106,8 @@ void MoveTool::mouseMoveEvent(const QList<QGraphicsItem*> &itemList, } } - bool shouldSnapping = view()->widget()->snappingAction()->isChecked(); - bool shouldSnappingAndAnchoring = view()->widget()->snappingAndAnchoringAction()->isChecked(); + bool shouldSnapping = view()->formEditorWidget()->snappingAction()->isChecked(); + bool shouldSnappingAndAnchoring = view()->formEditorWidget()->snappingAndAnchoringAction()->isChecked(); MoveManipulator::Snapping useSnapping = MoveManipulator::NoSnapping; if (event->modifiers().testFlag(Qt::ControlModifier) != (shouldSnapping || shouldSnappingAndAnchoring)) { diff --git a/src/plugins/qmldesigner/components/formeditor/resizetool.cpp b/src/plugins/qmldesigner/components/formeditor/resizetool.cpp index a301556af9..666af43d6b 100644 --- a/src/plugins/qmldesigner/components/formeditor/resizetool.cpp +++ b/src/plugins/qmldesigner/components/formeditor/resizetool.cpp @@ -77,8 +77,8 @@ void ResizeTool::mouseMoveEvent(const QList<QGraphicsItem*> &, QGraphicsSceneMouseEvent *event) { if (m_resizeManipulator.isActive()) { - bool shouldSnapping = view()->widget()->snappingAction()->isChecked(); - bool shouldSnappingAndAnchoring = view()->widget()->snappingAndAnchoringAction()->isChecked(); + bool shouldSnapping = view()->formEditorWidget()->snappingAction()->isChecked(); + bool shouldSnappingAndAnchoring = view()->formEditorWidget()->snappingAndAnchoringAction()->isChecked(); ResizeManipulator::Snapping useSnapping = ResizeManipulator::NoSnapping; if (event->modifiers().testFlag(Qt::ControlModifier) != (shouldSnapping || shouldSnappingAndAnchoring)) { diff --git a/src/plugins/qmldesigner/components/formeditor/toolbox.cpp b/src/plugins/qmldesigner/components/formeditor/toolbox.cpp index 1641feb642..7e1b9f2ebf 100644 --- a/src/plugins/qmldesigner/components/formeditor/toolbox.cpp +++ b/src/plugins/qmldesigner/components/formeditor/toolbox.cpp @@ -44,19 +44,20 @@ namespace QmlDesigner { ToolBox::ToolBox(QWidget *parentWidget) : Utils::StyledBar(parentWidget), m_leftToolBar(new QToolBar("LeftSidebar", this)), - m_rightToolBar(new QToolBar("RightSidebar", this)) + m_rightToolBar(new QToolBar("RightSidebar", this)), + m_formEditorCrumbleBar(new FormEditorCrumbleBar(this)) { setMaximumHeight(44); setSingleRow(false); QFrame *frame = new QFrame(this); - m_crumblePath = new Utils::CrumblePath(frame); frame->setStyleSheet("background-color: #4e4e4e;"); frame->setFrameShape(QFrame::NoFrame); QHBoxLayout *layout = new QHBoxLayout(frame); layout->setMargin(0); layout->setSpacing(0); frame->setLayout(layout); - layout->addWidget(m_crumblePath); + qDebug() << __FUNCTION__; + layout->addWidget(m_formEditorCrumbleBar->crumblePath()); frame->setProperty("panelwidget", true); frame->setProperty("panelwidget_singlerow", false); QVBoxLayout *verticalLayout = new QVBoxLayout(this); @@ -126,9 +127,9 @@ QList<QAction*> ToolBox::actions() const return QList<QAction*>() << m_leftToolBar->actions() << m_rightToolBar->actions(); } -Utils::CrumblePath *ToolBox::crumblePath() const +FormEditorCrumbleBar *ToolBox::formEditorCrumbleBar() const { - return m_crumblePath; + return m_formEditorCrumbleBar; } } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/formeditor/toolbox.h b/src/plugins/qmldesigner/components/formeditor/toolbox.h index 40a40345b8..b44ff37959 100644 --- a/src/plugins/qmldesigner/components/formeditor/toolbox.h +++ b/src/plugins/qmldesigner/components/formeditor/toolbox.h @@ -32,6 +32,8 @@ #include "utils/styledbar.h" +#include "formeditorcrumblebar.h" + QT_BEGIN_NAMESPACE class QToolBar; QT_END_NAMESPACE @@ -51,13 +53,12 @@ public: void addLeftSideAction(QAction *action); void addRightSideAction(QAction *action); QList<QAction*> actions() const; - Utils::CrumblePath *crumblePath() const; - + FormEditorCrumbleBar *formEditorCrumbleBar() const; private: QToolBar *m_leftToolBar; QToolBar *m_rightToolBar; - Utils::CrumblePath *m_crumblePath; + FormEditorCrumbleBar *m_formEditorCrumbleBar; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/integration/componentaction.cpp b/src/plugins/qmldesigner/components/integration/componentaction.cpp index 8a1704ca00..e4cf92821f 100644 --- a/src/plugins/qmldesigner/components/integration/componentaction.cpp +++ b/src/plugins/qmldesigner/components/integration/componentaction.cpp @@ -32,7 +32,8 @@ #include <QComboBox> #include "componentview.h" #include <QStandardItemModel> -#include <QDebug> +#include <qmldesignerplugin.h> +#include <modelnode.h> namespace QmlDesigner { @@ -42,9 +43,9 @@ ComponentAction::ComponentAction(ComponentView *componentView) { } -void ComponentAction::setCurrentIndex(int i) +void ComponentAction::setCurrentIndex(int index) { - emit currentIndexChanged(i); + emit currentIndexChanged(index); } QWidget *ComponentAction::createWidget(QWidget *parent) @@ -59,9 +60,21 @@ QWidget *ComponentAction::createWidget(QWidget *parent) return comboBox; } +static const QString fileNameOfCurrentDocument() +{ + return QmlDesignerPlugin::instance()->documentManager().currentDesignDocument()->textEditor()->document()->fileName(); +} + void ComponentAction::emitCurrentComponentChanged(int index) { - emit currentComponentChanged(m_componentView->modelNode(index)); + ModelNode componentNode = m_componentView->modelNode(index); + + if ( index > 0) + QmlDesignerPlugin::instance()->viewManager().pushInFileComponentOnCrambleBar(componentNode.id()); + else + QmlDesignerPlugin::instance()->viewManager().pushFileOnCrambleBar(fileNameOfCurrentDocument()); + + emit currentComponentChanged(componentNode); } } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/integration/componentaction.h b/src/plugins/qmldesigner/components/integration/componentaction.h index 1a9e6974ac..6e77523a9c 100644 --- a/src/plugins/qmldesigner/components/integration/componentaction.h +++ b/src/plugins/qmldesigner/components/integration/componentaction.h @@ -48,16 +48,17 @@ class ComponentAction : public QWidgetAction Q_OBJECT public: ComponentAction(ComponentView *componentView); - void setCurrentIndex(int); + void setCurrentIndex(int index); + protected: QWidget *createWidget(QWidget *parent); signals: void currentComponentChanged(const ModelNode &node); - void currentIndexChanged(int); + void currentIndexChanged(int index); -private slots: +public slots: void emitCurrentComponentChanged(int index); private: diff --git a/src/plugins/qmldesigner/components/integration/componentview.cpp b/src/plugins/qmldesigner/components/integration/componentview.cpp index 3c5ed3f8e0..cad1ca39ed 100644 --- a/src/plugins/qmldesigner/components/integration/componentview.cpp +++ b/src/plugins/qmldesigner/components/integration/componentview.cpp @@ -34,6 +34,7 @@ #include <nodemetainfo.h> #include <nodeabstractproperty.h> #include <QStandardItemModel> +#include <QAbstractItemView> // silence gcc warnings about unused parameters @@ -46,8 +47,6 @@ ComponentView::ComponentView(QObject *parent) { } - - void ComponentView::nodeAboutToBeRemoved(const ModelNode &removedNode) { removeSingleNodeFromList(removedNode); @@ -74,6 +73,11 @@ void ComponentView::setComponentNode(const ModelNode &node) m_componentAction->setCurrentIndex(indexForNode(node)); } +QWidget *ComponentView::widget() +{ + return 0; +} + void ComponentView::appendWholeDocumentAsComponent() { QStandardItem *item = new QStandardItem(tr("whole document")); @@ -110,7 +114,6 @@ void ComponentView::modelAttached(Model *model) AbstractView::modelAttached(model); - Q_ASSERT(model->masterModel()); appendWholeDocumentAsComponent(); searchForComponentAndAddToList(rootModelNode()); diff --git a/src/plugins/qmldesigner/components/integration/componentview.h b/src/plugins/qmldesigner/components/integration/componentview.h index 4d1edd11a9..cd88f6b17d 100644 --- a/src/plugins/qmldesigner/components/integration/componentview.h +++ b/src/plugins/qmldesigner/components/integration/componentview.h @@ -37,6 +37,7 @@ QT_BEGIN_NAMESPACE class QStandardItemModel; +class QComboBox; QT_END_NAMESPACE namespace QmlDesigner { @@ -53,7 +54,7 @@ public: ModelNodeRole = Qt::UserRole }; - ComponentView(QObject *parent); + ComponentView(QObject *parent = 0); void modelAttached(Model *model); void modelAboutToBeDetached(Model *model); @@ -106,6 +107,8 @@ public: void setComponentNode(const ModelNode &node); + QWidget *widget(); + signals: void componentListChanged(const QStringList &componentList); @@ -118,6 +121,7 @@ private: //functions int indexForNode(const ModelNode &node); private: + QList<QComboBox*> m_comboBoxList; QStandardItemModel *m_standardItemModel; ComponentAction *m_componentAction; }; diff --git a/src/plugins/qmldesigner/components/integration/designdocument.cpp b/src/plugins/qmldesigner/components/integration/designdocument.cpp new file mode 100644 index 0000000000..a6abe0cacb --- /dev/null +++ b/src/plugins/qmldesigner/components/integration/designdocument.cpp @@ -0,0 +1,793 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "designdocument.h" +#include "designdocumentview.h" +#include "xuifiledialog.h" +#include "componentview.h" + +#include <itemlibrarywidget.h> +#include <formeditorwidget.h> +#include <toolbox.h> +#include <metainfo.h> +#include <invalidargumentexception.h> +#include <componentaction.h> +#include <designeractionmanager.h> +#include <qmlobjectnode.h> +#include <rewritingexception.h> +#include <nodelistproperty.h> +#include <variantproperty.h> +#include <rewritingexception.h> +#include <modelnodeoperations.h> +#include <qmldesignerplugin.h> + +#include <projectexplorer/projectexplorer.h> +#include <projectexplorer/project.h> +#include <projectexplorer/target.h> +#include <qmlprojectmanager/qmlprojectrunconfiguration.h> +#include <qtsupport/qtkitinformation.h> +#include <qtsupport/qtsupportconstants.h> +#include <qtsupport/qtversionmanager.h> +#include <utils/crumblepath.h> +#include <utils/fileutils.h> + +#include <QCoreApplication> +#include <QDir> +#include <QFile> +#include <QFileInfo> +#include <QUrl> +#include <QProcess> +#include <QTemporaryFile> +#include <QDebug> +#include <QEvent> + +#include <QBoxLayout> +#include <QComboBox> +#include <QErrorMessage> +#include <QFileDialog> +#include <QLabel> +#include <QMdiArea> +#include <QMdiSubWindow> +#include <QMessageBox> +#include <QUndoStack> +#include <QPlainTextEdit> +#include <QApplication> + +enum { + debug = false +}; + +namespace QmlDesigner { + + +bool DesignDocument::s_clearCrumblePath = true; +bool DesignDocument::s_pushCrumblePath = true; + + +/** + \class QmlDesigner::DesignDocument + + DesignDocument acts as a facade to a model representing a qml document, + and the different views/widgets accessing it. + */ +DesignDocument::DesignDocument(QObject *parent) : + QObject(parent), + m_documentModel(Model::create("QtQuick.Item", 1, 0)), + m_inFileComponentModel(Model::create("QtQuick.Item", 1, 0)), + m_currentModel(m_documentModel), + m_subComponentManager(new SubComponentManager(m_documentModel.data(), this)), + m_rewriterView (new RewriterView(RewriterView::Amend, m_documentModel.data())), + m_documentLoaded(false), + m_qtVersionId(-1) +{ + updateActiveQtVersion(); +} + +DesignDocument::~DesignDocument() +{ + delete m_documentModel.data(); + delete m_inFileComponentModel.data(); + + delete rewriterView(); + + delete m_inFileComponentTextModifier.data(); + delete m_documentTextModifier.data(); +} + +Model *DesignDocument::currentModel() const +{ + return m_currentModel.data(); +} + +Model *DesignDocument::documentModel() const +{ + return m_documentModel.data(); +} + +void DesignDocument::changeToDocumentModel() +{ + viewManager().detachRewriterView(); + viewManager().detachViewsExceptRewriterAndComponetView(); + + m_currentModel = m_documentModel; + + viewManager().attachRewriterView(m_documentTextModifier.data()); + viewManager().attachViewsExceptRewriterAndComponetView(); +} + +void DesignDocument::changeToInFileComponentModel() +{ + viewManager().detachRewriterView(); + viewManager().detachViewsExceptRewriterAndComponetView(); + + m_currentModel = m_inFileComponentModel; + + viewManager().attachRewriterView(m_inFileComponentTextModifier.data()); + viewManager().attachViewsExceptRewriterAndComponetView(); +} + +QWidget *DesignDocument::centralWidget() const +{ + return qobject_cast<QWidget*>(parent()); +} + +QString DesignDocument::pathToQt() const +{ + QtSupport::BaseQtVersion *activeQtVersion = QtSupport::QtVersionManager::instance()->version(m_qtVersionId); + if (activeQtVersion && (activeQtVersion->qtVersion() >= QtSupport::QtVersionNumber(4, 7, 1)) + && (activeQtVersion->type() == QLatin1String(QtSupport::Constants::DESKTOPQT) + || activeQtVersion->type() == QLatin1String(QtSupport::Constants::SIMULATORQT))) + return activeQtVersion->qmakeProperty("QT_INSTALL_DATA"); + + return QString(); +} + +const ViewManager &DesignDocument::viewManager() const +{ + return QmlDesignerPlugin::instance()->viewManager(); +} + +ViewManager &DesignDocument::viewManager() +{ + return QmlDesignerPlugin::instance()->viewManager(); +} + +static ComponentTextModifier *createComponentTextModifier(TextModifier *originalModifier, + RewriterView *rewriterView, + const QString &componentText, + const ModelNode &componentNode) +{ + bool explicitComponent = componentText.contains("Component"); + + ModelNode rootModelNode = rewriterView->rootModelNode(); + + int componentStartOffset; + int componentEndOffset; + + int rootStartOffset = rewriterView->nodeOffset(rootModelNode); + + if (explicitComponent) { //the component is explciit we have to find the first definition inside + componentStartOffset = rewriterView->firstDefinitionInsideOffset(componentNode); + componentEndOffset = componentStartOffset + rewriterView->firstDefinitionInsideLength(componentNode); + } else { //the component is implicit + componentStartOffset = rewriterView->nodeOffset(componentNode); + componentEndOffset = componentStartOffset + rewriterView->nodeLength(componentNode); + } + + return new ComponentTextModifier (originalModifier, componentStartOffset, componentEndOffset, rootStartOffset); +} + +bool DesignDocument::loadSubComponent(const ModelNode &componentNode) +{ + QString componentText = rewriterView()->extractText(QList<ModelNode>() << componentNode).value(componentNode); + + if (componentText.isEmpty()) + return false; + + if (!componentNode.isRootNode()) { + Q_ASSERT(m_currentModel == m_documentModel); + //change to subcomponent model + if (m_inFileComponentTextModifier) + delete m_inFileComponentTextModifier.data(); + + m_inFileComponentTextModifier = createComponentTextModifier(m_documentTextModifier.data(), rewriterView(), componentText, componentNode); + + changeToInFileComponentModel(); + } + + return true; +} + +/*! + Returns any errors that happened when parsing the latest qml file. + */ +QList<RewriterView::Error> DesignDocument::qmlSyntaxErrors() const +{ + return m_rewriterView->errors(); +} + +bool DesignDocument::hasQmlSyntaxErrors() const +{ + return !m_currentModel->rewriterView()->errors().isEmpty(); +} + +QString DesignDocument::displayName() const +{ + return fileName(); +} + +QString DesignDocument::simplfiedDisplayName() const +{ + if (rootModelNode().id().isEmpty()) { + return rootModelNode().id(); + } else { + return rootModelNode().simplifiedTypeName(); + } + + QStringList list = displayName().split(QLatin1Char('/')); + return list.last(); +} + +void DesignDocument::updateFileName(const QString & /*oldFileName*/, const QString &newFileName) +{ + if (m_documentModel) + m_documentModel->setFileUrl(QUrl::fromLocalFile(newFileName)); + + if (m_inFileComponentModel) + m_inFileComponentModel->setFileUrl(QUrl::fromLocalFile(newFileName)); + + viewManager().setItemLibraryViewResourcePath(QFileInfo(newFileName).absolutePath()); + + emit displayNameChanged(displayName()); +} + +QString DesignDocument::fileName() const +{ + return editor()->document()->fileName(); +} + +int DesignDocument::qtVersionId() const +{ + return m_qtVersionId; +} + +bool DesignDocument::isDocumentLoaded() const +{ + return m_documentLoaded; +} + +void DesignDocument::resetToDocumentModel() +{ + m_currentModel = m_documentModel; + m_rewriterView->setTextModifier(m_documentTextModifier.data()); +} + +QList<RewriterView::Error> DesignDocument::loadDocument(QPlainTextEdit *edit) +{ + Q_CHECK_PTR(edit); + + connect(edit, SIGNAL(undoAvailable(bool)), + this, SIGNAL(undoAvailable(bool))); + connect(edit, SIGNAL(redoAvailable(bool)), + this, SIGNAL(redoAvailable(bool))); + connect(edit, SIGNAL(modificationChanged(bool)), + this, SIGNAL(dirtyStateChanged(bool))); + + m_documentTextModifier = new BaseTextEditModifier(dynamic_cast<TextEditor::BaseTextEditorWidget*>(plainTextEdit())); + + m_inFileComponentTextModifier.clear(); + + //masterModel = Model::create(textModifier, searchPath, errors); + + updateFileName(QString(), fileName()); + + m_subComponentManager->update(QUrl::fromLocalFile(fileName()), m_currentModel->imports()); + + activateCurrentModel(m_documentTextModifier.data()); + + return rewriterView()->errors(); +} + +void DesignDocument::changeCurrentModelTo(const ModelNode &node) +{ + if (QmlDesignerPlugin::instance()->currentDesignDocument() != this) + return; + + if (rootModelNode() == node) { + changeToDocumentModel(); + } else { + changeToSubComponent(node); + } + + + +// s_clearCrumblePath = false; +// while (m_formEditorView->crumblePath()->dataForLastIndex().value<CrumbleBarInfo>().modelNode.isValid() && +// !m_formEditorView->crumblePath()->dataForLastIndex().value<CrumbleBarInfo>().modelNode.isRootNode()) +// m_formEditorView->crumblePath()->popElement(); +// if (node.isRootNode() && m_formEditorView->crumblePath()->dataForLastIndex().isValid()) +// m_formEditorView->crumblePath()->popElement(); +// s_clearCrumblePath = true; +} + +void DesignDocument::changeToSubComponent(const ModelNode &componentNode) +{ + Q_ASSERT(m_documentModel); + QWeakPointer<Model> oldModel = m_currentModel; + Q_ASSERT(oldModel.data()); + + if (m_currentModel == m_inFileComponentModel) { + changeToDocumentModel(); + } + + bool subComponentLoaded = loadSubComponent(componentNode); + + if (subComponentLoaded) { + Q_ASSERT(m_documentModel); + Q_ASSERT(m_currentModel); + + activateCurrentModel(m_inFileComponentTextModifier.data()); + } +} + +void DesignDocument::changeToExternalSubComponent(const QString &fileName) +{ + Core::EditorManager::openEditor(fileName); +} + +void DesignDocument::goIntoComponent() +{ + if (!m_currentModel) + return; + + QList<ModelNode> selectedNodes; + if (rewriterView()) + selectedNodes = rewriterView()->selectedModelNodes(); + + s_clearCrumblePath = false; + if (selectedNodes.count() == 1) { + qDebug() << __FUNCTION__ << selectedNodes.first(); + + viewManager().setComponentNode(selectedNodes.first()); + ModelNodeOperations::goIntoComponent(selectedNodes.first()); + } + + s_clearCrumblePath = true; +} + +void DesignDocument::activateCurrentModel(TextModifier *textModifier) +{ + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + + Q_ASSERT(m_documentModel); + Q_ASSERT(m_currentModel); + + if (!plainTextEdit()->parent()) // hack to prevent changing owner of external text edit + m_stackedWidget->addWidget(plainTextEdit()); + + viewManager().attachRewriterView(textModifier); + +// if (s_clearCrumblePath) +// m_formEditorView->crumblePath()->clear(); + +// if (s_pushCrumblePath && +// !differentCrumbleBarOnTop(m_formEditorView.data(), createCrumbleBarInfo().value<CrumbleBarInfo>())) +// m_formEditorView->crumblePath()->pushElement(simplfiedDisplayName(), createCrumbleBarInfo()); + + m_documentLoaded = true; + m_subComponentManager->update(QUrl::fromLocalFile(fileName()), m_currentModel->imports()); + Q_ASSERT(m_documentModel); + QApplication::restoreOverrideCursor(); +} + +void DesignDocument::activateCurrentModel() +{ + if (currentModel() == documentModel()) + activateCurrentModel(m_documentTextModifier.data()); + else + activateCurrentModel(m_inFileComponentTextModifier.data()); +} + +void DesignDocument::activateDocumentModel() +{ + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + + Q_ASSERT(m_documentModel); + Q_ASSERT(m_currentModel); + + if (!plainTextEdit()->parent()) // hack to prevent changing owner of external text edit + m_stackedWidget->addWidget(plainTextEdit()); + + m_currentModel = m_documentModel; + m_documentLoaded = true; + m_subComponentManager->update(QUrl::fromLocalFile(fileName()), m_currentModel->imports()); + Q_ASSERT(m_documentModel); + QApplication::restoreOverrideCursor(); +} + +bool DesignDocument::isUndoAvailable() const +{ + + if (plainTextEdit()) + return plainTextEdit()->document()->isUndoAvailable(); + return false; +} + +bool DesignDocument::isRedoAvailable() const +{ + if (plainTextEdit()) + return plainTextEdit()->document()->isRedoAvailable(); + return false; +} + +void DesignDocument::close() +{ + m_documentLoaded = false; + emit designDocumentClosed(); +} + +void DesignDocument::deleteSelected() +{ + if (!m_currentModel) + return; + + try { + RewriterTransaction transaction(rewriterView()); + QList<ModelNode> toDelete = rewriterView()->selectedModelNodes(); + foreach (ModelNode node, toDelete) { + if (node.isValid() && !node.isRootNode() && QmlObjectNode(node).isValid()) + QmlObjectNode(node).destroy(); + } + + } catch (RewritingException &e) { + QMessageBox::warning(0, tr("Error"), e.description()); + } +} + +void DesignDocument::copySelected() +{ + QScopedPointer<Model> copyModel(Model::create("QtQuick.Rectangle", 1, 0, currentModel())); + copyModel->setFileUrl(currentModel()->fileUrl()); + copyModel->changeImports(currentModel()->imports(), QList<Import>()); + + Q_ASSERT(copyModel); + + DesignDocumentView view; + + m_currentModel->attachView(&view); + + if (view.selectedModelNodes().isEmpty()) + return; + + QList<ModelNode> selectedNodes(view.selectedModelNodes()); + + foreach (const ModelNode &node, selectedNodes) { + foreach (const ModelNode &node2, selectedNodes) { + if (node.isAncestorOf(node2)) + selectedNodes.removeAll(node2); + } + } + + if (selectedNodes.count() == 1) { + ModelNode selectedNode(selectedNodes.first()); + + if (!selectedNode.isValid()) + return; + + m_currentModel->detachView(&view); + + copyModel->attachView(&view); + view.replaceModel(selectedNode); + + Q_ASSERT(view.rootModelNode().isValid()); + Q_ASSERT(view.rootModelNode().type() != "empty"); + + view.toClipboard(); + } else { //multi items selected + m_currentModel->detachView(&view); + copyModel->attachView(&view); + + foreach (ModelNode node, view.rootModelNode().allDirectSubModelNodes()) { + node.destroy(); + } + view.changeRootNodeType("QtQuick.Rectangle", 1, 0); + view.rootModelNode().setId("designer__Selection"); + + foreach (const ModelNode &selectedNode, selectedNodes) { + ModelNode newNode(view.insertModel(selectedNode)); + view.rootModelNode().nodeListProperty("data").reparentHere(newNode); + } + + view.toClipboard(); + } +} + +void DesignDocument::cutSelected() +{ + copySelected(); + deleteSelected(); +} + +static void scatterItem(ModelNode pastedNode, const ModelNode targetNode, int offset = -2000) +{ + + bool scatter = false; + foreach (const ModelNode &childNode, targetNode.allDirectSubModelNodes()) { + if ((childNode.variantProperty("x").value() == pastedNode.variantProperty("x").value()) && + (childNode.variantProperty("y").value() == pastedNode.variantProperty("y").value())) + scatter = true; + } + if (!scatter) + return; + + if (offset == -2000) { + double x = pastedNode.variantProperty("x").value().toDouble(); + double y = pastedNode.variantProperty("y").value().toDouble(); + double targetWidth = 20; + double targetHeight = 20; + x = x + double(qrand()) / RAND_MAX * targetWidth - targetWidth / 2; + y = y + double(qrand()) / RAND_MAX * targetHeight - targetHeight / 2; + pastedNode.variantProperty("x") = int(x); + pastedNode.variantProperty("y") = int(y); + } else { + double x = pastedNode.variantProperty("x").value().toDouble(); + double y = pastedNode.variantProperty("y").value().toDouble(); + x = x + offset; + y = y + offset; + pastedNode.variantProperty("x") = int(x); + pastedNode.variantProperty("y") = int(y); + } +} + +void DesignDocument::paste() +{ + QScopedPointer<Model> pasteModel(Model::create("empty", 1, 0, currentModel())); + pasteModel->setFileUrl(currentModel()->fileUrl()); + pasteModel->changeImports(currentModel()->imports(), QList<Import>()); + + Q_ASSERT(pasteModel); + + if (!pasteModel) + return; + + DesignDocumentView view; + pasteModel->attachView(&view); + + view.fromClipboard(); + + ModelNode rootNode(view.rootModelNode()); + + if (rootNode.type() == "empty") + return; + + if (rootNode.id() == "designer__Selection") { + QList<ModelNode> selectedNodes = rootNode.allDirectSubModelNodes(); + qDebug() << rootNode; + qDebug() << selectedNodes; + pasteModel->detachView(&view); + m_currentModel->attachView(&view); + + ModelNode targetNode; + + if (!view.selectedModelNodes().isEmpty()) + targetNode = view.selectedModelNodes().first(); + + //In case we copy and paste a selection we paste in the parent item + if ((view.selectedModelNodes().count() == selectedNodes.count()) && targetNode.isValid() && targetNode.parentProperty().isValid()) + targetNode = targetNode.parentProperty().parentModelNode(); + + if (!targetNode.isValid()) + targetNode = view.rootModelNode(); + + foreach (const ModelNode &node, selectedNodes) { + foreach (const ModelNode &node2, selectedNodes) { + if (node.isAncestorOf(node2)) + selectedNodes.removeAll(node2); + } + } + + QList<ModelNode> pastedNodeList; + + try { + RewriterTransaction transaction(rewriterView()); + + int offset = double(qrand()) / RAND_MAX * 20 - 10; + + foreach (const ModelNode &node, selectedNodes) { + QString defaultProperty(targetNode.metaInfo().defaultPropertyName()); + ModelNode pastedNode(view.insertModel(node)); + pastedNodeList.append(pastedNode); + scatterItem(pastedNode, targetNode, offset); + targetNode.nodeListProperty(defaultProperty).reparentHere(pastedNode); + } + + view.setSelectedModelNodes(pastedNodeList); + } catch (RewritingException &e) { + qWarning() << e.description(); //silent error + } + } else { + try { + RewriterTransaction transaction(rewriterView()); + + pasteModel->detachView(&view); + m_currentModel->attachView(&view); + ModelNode pastedNode(view.insertModel(rootNode)); + ModelNode targetNode; + + if (!view.selectedModelNodes().isEmpty()) + targetNode = view.selectedModelNodes().first(); + + if (!targetNode.isValid()) + targetNode = view.rootModelNode(); + + if (targetNode.parentProperty().isValid() && + (pastedNode.simplifiedTypeName() == targetNode.simplifiedTypeName()) && + (pastedNode.variantProperty("width").value() == targetNode.variantProperty("width").value()) && + (pastedNode.variantProperty("height").value() == targetNode.variantProperty("height").value())) + + targetNode = targetNode.parentProperty().parentModelNode(); + + QString defaultProperty(targetNode.metaInfo().defaultPropertyName()); + + scatterItem(pastedNode, targetNode); + if (targetNode.nodeListProperty(defaultProperty).isValid()) + targetNode.nodeListProperty(defaultProperty).reparentHere(pastedNode); + + transaction.commit(); + NodeMetaInfo::clearCache(); + + view.setSelectedModelNodes(QList<ModelNode>() << pastedNode); + } catch (RewritingException &e) { + qWarning() << e.description(); //silent error + } + } +} + +void DesignDocument::selectAll() +{ + if (!m_currentModel) + return; + + DesignDocumentView view; + m_currentModel->attachView(&view); + + + QList<ModelNode> allNodesExceptRootNode(view.allModelNodes()); + allNodesExceptRootNode.removeOne(view.rootModelNode()); + view.setSelectedModelNodes(allNodesExceptRootNode); +} + +RewriterView *DesignDocument::rewriterView() const +{ + return m_rewriterView.data(); +} + +void DesignDocument::setEditor(Core::IEditor *editor) +{ + m_textEditor = editor; + connect(editor->document(), + SIGNAL(fileNameChanged(QString,QString)), + SLOT(updateFileName(QString,QString))); +} + +Core::IEditor *DesignDocument::editor() const +{ + return m_textEditor.data(); +} + +TextEditor::ITextEditor *DesignDocument::textEditor() const +{ + return qobject_cast<TextEditor::ITextEditor*>(editor()); +} + +QPlainTextEdit *DesignDocument::plainTextEdit() const +{ + if (editor()) + return qobject_cast<QPlainTextEdit*>(editor()->widget()); + + return 0; +} + +ModelNode DesignDocument::rootModelNode() const +{ + return rewriterView()->rootModelNode(); +} + +void DesignDocument::undo() +{ + if (rewriterView() && !rewriterView()->modificationGroupActive()) + plainTextEdit()->undo(); + + viewManager().resetPropertyEditorView(); +} + +void DesignDocument::redo() +{ + if (rewriterView() && !rewriterView()->modificationGroupActive()) + plainTextEdit()->redo(); + + viewManager().resetPropertyEditorView(); +} + +static inline QtSupport::BaseQtVersion *getActiveQtVersion(DesignDocument *controller) +{ + ProjectExplorer::ProjectExplorerPlugin *projectExplorer = ProjectExplorer::ProjectExplorerPlugin::instance(); + ProjectExplorer::Project *currentProject = projectExplorer->currentProject(); + + if (!currentProject) + return 0; + + controller->disconnect(controller, SLOT(updateActiveQtVersion())); + controller->connect(projectExplorer, SIGNAL(currentProjectChanged(ProjectExplorer::Project*)), controller, SLOT(updateActiveQtVersion())); + + controller->connect(currentProject, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)), controller, SLOT(updateActiveQtVersion())); + + + ProjectExplorer::Target *target = currentProject->activeTarget(); + + if (!target) + return 0; + + controller->connect(target, SIGNAL(kitChanged()), controller, SLOT(updateActiveQtVersion())); + return QtSupport::QtKitInformation::qtVersion(target->kit()); +} + +void DesignDocument::updateActiveQtVersion() +{ + QtSupport::BaseQtVersion *newQtVersion = getActiveQtVersion(this); + + if (!newQtVersion ) { + m_qtVersionId = -1; + return; + } + + if (m_qtVersionId == newQtVersion->uniqueId()) + return; + + m_qtVersionId = newQtVersion->uniqueId(); + + viewManager().setNodeInstanceViewQtPath(pathToQt()); +} + +QString DesignDocument::contextHelpId() const +{ + DesignDocumentView view; + m_currentModel->attachView(&view); + + QList<ModelNode> nodes = view.selectedModelNodes(); + QString helpId; + if (!nodes.isEmpty()) { + helpId = nodes.first().type(); + helpId.replace("QtQuick", "QML"); + } + + return helpId; +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/integration/designdocumentcontroller.h b/src/plugins/qmldesigner/components/integration/designdocument.h index 6d74305e9c..f1147ea69d 100644 --- a/src/plugins/qmldesigner/components/integration/designdocumentcontroller.h +++ b/src/plugins/qmldesigner/components/integration/designdocument.h @@ -27,8 +27,8 @@ ** ****************************************************************************/ -#ifndef DesignDocumentController_h -#define DesignDocumentController_h +#ifndef DesignDocument_h +#define DesignDocument_h #include "rewriterview.h" @@ -44,6 +44,7 @@ #include <componenttextmodifier.h> #include <subcomponentmanager.h> #include <model/viewlogger.h> +#include <viewmanager.h> #include <QObject> #include <QString> @@ -66,49 +67,44 @@ class TextModifier; class QmlObjectNode; struct CrumbleBarInfo; -class DesignDocumentController: public QObject +class DesignDocument: public QObject { Q_OBJECT public: - DesignDocumentController(QObject *parent); - ~DesignDocumentController(); + DesignDocument(QObject *parent = 0); + ~DesignDocument(); QString displayName() const; QString simplfiedDisplayName() const; - QString fileName() const; - void setFileName(const QString &m_fileName); - - QList<RewriterView::Error> loadMaster(QPlainTextEdit *edit); - QList<RewriterView::Error> loadMaster(const QByteArray &qml); - void loadCurrentModel(); + QList<RewriterView::Error> loadDocument(QPlainTextEdit *edit); + void activateCurrentModel(TextModifier *textModifier); + void activateCurrentModel(); + void activateDocumentModel(); void close(); - bool isDirty() const; bool isUndoAvailable() const; bool isRedoAvailable() const; - Model *model() const; - Model *masterModel() const; + Model *currentModel() const; + Model *documentModel() const; + + QString contextHelpId() const; + QList<RewriterView::Error> qmlSyntaxErrors() const; + bool hasQmlSyntaxErrors() const; RewriterView *rewriterView() const; - bool isModelSyncBlocked() const; - void blockModelSync(bool block); + void setEditor(Core::IEditor *editor); + Core::IEditor *editor() const; - QString contextHelpId() const; - QList<RewriterView::Error> qmlErrors() const; - - void setItemLibraryView(ItemLibraryView* m_itemLibraryView); - void setNavigator(NavigatorView* navigatorView); - void setPropertyEditorView(PropertyEditor *propertyEditor); - void setStatesEditorView(StatesEditorView* m_statesEditorView); - void setFormEditorView(FormEditorView *m_formEditorView); - void setNodeInstanceView(NodeInstanceView *m_nodeInstanceView); - void setComponentView(ComponentView *m_componentView); + TextEditor::ITextEditor *textEditor() const; + QPlainTextEdit *plainTextEdit() const; + QString fileName() const; + int qtVersionId() const; // maybe that is not working, because the id should be not cached!!! + bool isDocumentLoaded() const; - void setCrumbleBarInfo(const CrumbleBarInfo &crumbleBarInfo); - static void setBlockCrumbleBar(bool); + void resetToDocumentModel(); signals: void displayNameChanged(const QString &newFileName); @@ -122,8 +118,6 @@ signals: void fileToOpen(const QString &path); public slots: - bool save(QWidget *parent = 0); - void saveAs(QWidget *parent = 0); void deleteSelected(); void copySelected(); void cutSelected(); @@ -131,68 +125,46 @@ public slots: void selectAll(); void undo(); void redo(); - void activeQtVersionChanged(); + void updateActiveQtVersion(); void changeCurrentModelTo(const ModelNode &node); void changeToSubComponent(const ModelNode &node); - void changeToExternalSubComponent(const QString &m_fileName); + void changeToExternalSubComponent(const QString &m_oldFileName); void goIntoComponent(); -#ifdef ENABLE_TEXT_VIEW - void showText(); - void showForm(); -#endif // ENABLE_TEXT_VIEW - private slots: - void doRealSaveAs(const QString &m_fileName); + void updateFileName(const QString &oldFileName, const QString &newFileName); private: // functions - void detachNodeInstanceView(); - void attachNodeInstanceView(); - void changeToMasterModel(); - QVariant createCrumbleBarInfo(); + void changeToDocumentModel(); + void changeToInFileComponentModel(); QWidget *centralWidget() const; QString pathToQt() const; -private: // variables - QWeakPointer<FormEditorView> m_formEditorView; + const ViewManager &viewManager() const; + ViewManager &viewManager(); - QWeakPointer<ItemLibraryView> m_itemLibraryView; - QWeakPointer<NavigatorView> m_navigator; - QWeakPointer<PropertyEditor> m_propertyEditorView; - QWeakPointer<StatesEditorView> m_statesEditorView; + ModelNode rootModelNode() const; + + bool loadSubComponent(const ModelNode &componentNode); + +private: // variables QWeakPointer<QStackedWidget> m_stackedWidget; - QWeakPointer<NodeInstanceView> m_nodeInstanceView; - QWeakPointer<ComponentView> m_componentView; + QWeakPointer<Model> m_documentModel; + QWeakPointer<Model> m_inFileComponentModel; + QWeakPointer<Model> m_currentModel; + QWeakPointer<Core::IEditor> m_textEditor; + QWeakPointer<BaseTextEditModifier> m_documentTextModifier; + QWeakPointer<ComponentTextModifier> m_inFileComponentTextModifier; + QWeakPointer<SubComponentManager> m_subComponentManager; - QWeakPointer<Model> m_model; - QWeakPointer<Model> m_subComponentModel; - QWeakPointer<Model> m_masterModel; - QWeakPointer<QPlainTextEdit> m_textEdit; QWeakPointer<RewriterView> m_rewriterView; - BaseTextEditModifier *m_textModifier; - ComponentTextModifier *m_componentTextModifier; - QWeakPointer<SubComponentManager> m_subComponentManager; - QWeakPointer<Internal::ViewLogger> m_viewLogger; - ModelNode m_componentNode; - QString m_fileName; - QUrl m_searchPath; bool m_documentLoaded; - bool m_syncBlocked; - int m_qt_versionId; - static bool s_clearCrumblePath; - static bool s_pushCrumblePath; -}; - - -struct CrumbleBarInfo { - ModelNode modelNode; - QString fileName; + int m_qtVersionId; }; } // namespace QmlDesigner -Q_DECLARE_METATYPE(QmlDesigner::CrumbleBarInfo) -#endif // DesignDocumentController_h +#endif // DesignDocument_h diff --git a/src/plugins/qmldesigner/components/integration/designdocumentcontroller.cpp b/src/plugins/qmldesigner/components/integration/designdocumentcontroller.cpp deleted file mode 100644 index 02a877fa15..0000000000 --- a/src/plugins/qmldesigner/components/integration/designdocumentcontroller.cpp +++ /dev/null @@ -1,943 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "designdocumentcontroller.h" -#include "designdocumentcontrollerview.h" -#include "xuifiledialog.h" -#include "componentview.h" - -#include <itemlibrarywidget.h> -#include <formeditorwidget.h> -#include <toolbox.h> -#include <metainfo.h> -#include <invalidargumentexception.h> -#include <componentaction.h> -#include <designeractionmanager.h> -#include <qmlobjectnode.h> -#include <rewritingexception.h> -#include <nodelistproperty.h> -#include <variantproperty.h> -#include <rewritingexception.h> -#include <modelnodeoperations.h> -#include <designmodewidget.h> - -#include <projectexplorer/projectexplorer.h> -#include <projectexplorer/project.h> -#include <projectexplorer/target.h> -#include <qmlprojectmanager/qmlprojectrunconfiguration.h> -#include <qtsupport/qtkitinformation.h> -#include <qtsupport/qtsupportconstants.h> -#include <qtsupport/qtversionmanager.h> -#include <utils/crumblepath.h> -#include <utils/fileutils.h> - -#include <QCoreApplication> -#include <QDir> -#include <QFile> -#include <QFileInfo> -#include <QUrl> -#include <QProcess> -#include <QTemporaryFile> -#include <QDebug> -#include <QEvent> - -#include <QBoxLayout> -#include <QComboBox> -#include <QErrorMessage> -#include <QFileDialog> -#include <QLabel> -#include <QMdiArea> -#include <QMdiSubWindow> -#include <QMessageBox> -#include <QUndoStack> -#include <QPlainTextEdit> -#include <QApplication> - -enum { - debug = false -}; - -namespace QmlDesigner { - - -bool DesignDocumentController::s_clearCrumblePath = true; -bool DesignDocumentController::s_pushCrumblePath = true; - - -/** - \class QmlDesigner::DesignDocumentController - - DesignDocumentController acts as a facade to a model representing a qml document, - and the different views/widgets accessing it. - */ -DesignDocumentController::DesignDocumentController(QObject *parent) : - QObject(parent) -{ - m_documentLoaded = false; - m_syncBlocked = false; - - ProjectExplorer::ProjectExplorerPlugin *projectExplorer = ProjectExplorer::ProjectExplorerPlugin::instance(); - connect(projectExplorer, SIGNAL(currentProjectChanged(ProjectExplorer::Project*)), this, SLOT(activeQtVersionChanged())); - activeQtVersionChanged(); -} - -DesignDocumentController::~DesignDocumentController() -{ - delete m_model.data(); - delete m_subComponentModel.data(); - - delete m_rewriterView.data(); - - if (m_componentTextModifier) //componentTextModifier might not be created - delete m_componentTextModifier; -} - -Model *DesignDocumentController::model() const -{ - return m_model.data(); -} - -Model *DesignDocumentController::masterModel() const -{ - return m_masterModel.data(); -} - - -void DesignDocumentController::detachNodeInstanceView() -{ - if (m_nodeInstanceView) - model()->detachView(m_nodeInstanceView.data()); -} - -void DesignDocumentController::attachNodeInstanceView() -{ - if (m_nodeInstanceView) - model()->attachView(m_nodeInstanceView.data()); - if (m_formEditorView) - m_formEditorView->resetView(); -} - -void DesignDocumentController::changeToMasterModel() -{ - m_model->detachView(m_rewriterView.data()); - m_rewriterView->setTextModifier(m_textModifier); - m_model = m_masterModel; - m_model->attachView(m_rewriterView.data()); - m_componentNode = m_rewriterView->rootModelNode(); -} - -QVariant DesignDocumentController::createCrumbleBarInfo() -{ - CrumbleBarInfo info; - info.fileName = fileName(); - info.modelNode = m_componentNode; - return QVariant::fromValue<CrumbleBarInfo>(info); -} - -QWidget *DesignDocumentController::centralWidget() const -{ - return qobject_cast<QWidget*>(parent()); -} - -QString DesignDocumentController::pathToQt() const -{ - QtSupport::BaseQtVersion *activeQtVersion = QtSupport::QtVersionManager::instance()->version(m_qt_versionId); - if (activeQtVersion && (activeQtVersion->qtVersion().majorVersion > 3) - && (activeQtVersion->type() == QLatin1String(QtSupport::Constants::DESKTOPQT) - || activeQtVersion->type() == QLatin1String(QtSupport::Constants::SIMULATORQT))) - return activeQtVersion->qmakeProperty("QT_INSTALL_DATA"); - return QString(); -} - -/*! - Returns whether the model is automatically updated if the text editor changes. - */ -bool DesignDocumentController::isModelSyncBlocked() const -{ - return m_syncBlocked; -} - -/*! - Switches whether the model (and therefore the views) are updated if the text editor - changes. - - If the synchronization is enabled again, the model is automatically resynchronized - with the current state of the text editor. - */ -void DesignDocumentController::blockModelSync(bool block) -{ - if (m_syncBlocked == block) - return; - - m_syncBlocked = block; - - if (m_textModifier) { - if (m_syncBlocked) { - detachNodeInstanceView(); - m_textModifier->deactivateChangeSignals(); - } else { - activeQtVersionChanged(); - changeToMasterModel(); - QmlModelState state; - //We go back to base state (and back again) to avoid side effects from text editing. - if (m_statesEditorView && m_statesEditorView->model()) { - state = m_statesEditorView->currentState(); - m_statesEditorView->setCurrentState(m_statesEditorView->baseState()); - - } - - m_textModifier->reactivateChangeSignals(); - - if (state.isValid() && m_statesEditorView) - m_statesEditorView->setCurrentState(state); - attachNodeInstanceView(); - if (m_propertyEditorView) - m_propertyEditorView->resetView(); - if (m_formEditorView) - m_formEditorView->resetView(); - } - } -} - -/*! - Returns any errors that happened when parsing the latest qml file. - */ -QList<RewriterView::Error> DesignDocumentController::qmlErrors() const -{ - return m_rewriterView->errors(); -} - -void DesignDocumentController::setItemLibraryView(ItemLibraryView* itemLibraryView) -{ - m_itemLibraryView = itemLibraryView; -} - -void DesignDocumentController::setNavigator(NavigatorView* navigatorView) -{ - m_navigator = navigatorView; -} - -void DesignDocumentController::setPropertyEditorView(PropertyEditor *propertyEditor) -{ - m_propertyEditorView = propertyEditor; -} - -void DesignDocumentController::setStatesEditorView(StatesEditorView* statesEditorView) -{ - m_statesEditorView = statesEditorView; -} - -void DesignDocumentController::setFormEditorView(FormEditorView *formEditorView) -{ - m_formEditorView = formEditorView; -} - -void DesignDocumentController::setNodeInstanceView(NodeInstanceView *nodeInstanceView) -{ - m_nodeInstanceView = nodeInstanceView; -} - -void DesignDocumentController::setComponentView(ComponentView *componentView) -{ - m_componentView = componentView; - connect(componentView->action(), SIGNAL(currentComponentChanged(ModelNode)), SLOT(changeCurrentModelTo(ModelNode))); -} - -static inline bool compareCrumbleBarInfo(const CrumbleBarInfo &crumbleBarInfo1, const CrumbleBarInfo &crumbleBarInfo2) -{ - return crumbleBarInfo1.fileName == crumbleBarInfo2.fileName && crumbleBarInfo1.modelNode == crumbleBarInfo2.modelNode; -} - -void DesignDocumentController::setCrumbleBarInfo(const CrumbleBarInfo &crumbleBarInfo) -{ - s_clearCrumblePath = false; - s_pushCrumblePath = false; - while (!compareCrumbleBarInfo(m_formEditorView->crumblePath()->dataForLastIndex().value<CrumbleBarInfo>(), crumbleBarInfo)) - m_formEditorView->crumblePath()->popElement(); - Core::EditorManager::openEditor(crumbleBarInfo.fileName); - s_pushCrumblePath = true; - Internal::DesignModeWidget::instance()->currentDesignDocumentController()->changeToSubComponent(crumbleBarInfo.modelNode); - s_clearCrumblePath = true; -} - -void DesignDocumentController::setBlockCrumbleBar(bool b) -{ - s_clearCrumblePath = !b; - s_pushCrumblePath = !b; -} - -QString DesignDocumentController::displayName() const -{ - if (fileName().isEmpty()) - return tr("-New Form-"); - else - return fileName(); -} - -QString DesignDocumentController::simplfiedDisplayName() const -{ - if (!m_componentNode.isRootNode()) { - if (m_componentNode.id().isEmpty()) { - if (m_formEditorView->rootModelNode().id().isEmpty()) - return m_formEditorView->rootModelNode().simplifiedTypeName(); - return m_formEditorView->rootModelNode().id(); - } - return m_componentNode.id(); - } - - QStringList list = displayName().split(QLatin1Char('/')); - return list.last(); -} - -QString DesignDocumentController::fileName() const -{ - return m_fileName; -} - -void DesignDocumentController::setFileName(const QString &fileName) -{ - m_fileName = fileName; - - if (QFileInfo(fileName).exists()) - m_searchPath = QUrl::fromLocalFile(fileName); - else - m_searchPath = QUrl(fileName); - - if (m_model) - m_model->setFileUrl(m_searchPath); - - if (m_itemLibraryView) - m_itemLibraryView->widget()->setResourcePath(QFileInfo(fileName).absolutePath()); - emit displayNameChanged(displayName()); -} - -QList<RewriterView::Error> DesignDocumentController::loadMaster(QPlainTextEdit *edit) -{ - Q_CHECK_PTR(edit); - - m_textEdit = edit; - - connect(edit, SIGNAL(undoAvailable(bool)), - this, SIGNAL(undoAvailable(bool))); - connect(edit, SIGNAL(redoAvailable(bool)), - this, SIGNAL(redoAvailable(bool))); - connect(edit, SIGNAL(modificationChanged(bool)), - this, SIGNAL(dirtyStateChanged(bool))); - - m_textModifier = new BaseTextEditModifier(dynamic_cast<TextEditor::BaseTextEditorWidget*>(m_textEdit.data())); - - m_componentTextModifier = 0; - - //masterModel = Model::create(textModifier, searchPath, errors); - - m_masterModel = Model::create("QtQuick.Rectangle", 1, 0); - -#if defined(VIEWLOGGER) - m_viewLogger = new Internal::ViewLogger(m_model.data()); - m_masterModel->attachView(m_viewLogger.data()); -#endif - - m_masterModel->setFileUrl(m_searchPath); - - m_subComponentModel = Model::create("QtQuick.Rectangle", 1, 0); - m_subComponentModel->setFileUrl(m_searchPath); - - m_rewriterView = new RewriterView(RewriterView::Amend, m_masterModel.data()); - m_rewriterView->setTextModifier( m_textModifier); - connect(m_rewriterView.data(), SIGNAL(errorsChanged(QList<RewriterView::Error>)), - this, SIGNAL(qmlErrorsChanged(QList<RewriterView::Error>))); - - m_masterModel->attachView(m_rewriterView.data()); - m_model = m_masterModel; - m_componentNode = m_rewriterView->rootModelNode(); - - m_subComponentManager = new SubComponentManager(m_masterModel.data(), this); - m_subComponentManager->update(m_searchPath, m_model->imports()); - - loadCurrentModel(); - - m_masterModel->attachView(m_componentView.data()); - - return m_rewriterView->errors(); -} - -void DesignDocumentController::changeCurrentModelTo(const ModelNode &node) -{ - if (m_componentNode == node) - return; - if (Internal::DesignModeWidget::instance()->currentDesignDocumentController() != this) - return; - s_clearCrumblePath = false; - while (m_formEditorView->crumblePath()->dataForLastIndex().value<CrumbleBarInfo>().modelNode.isValid() && - !m_formEditorView->crumblePath()->dataForLastIndex().value<CrumbleBarInfo>().modelNode.isRootNode()) - m_formEditorView->crumblePath()->popElement(); - if (node.isRootNode() && m_formEditorView->crumblePath()->dataForLastIndex().isValid()) - m_formEditorView->crumblePath()->popElement(); - changeToSubComponent(node); - s_clearCrumblePath = true; -} - -void DesignDocumentController::changeToSubComponent(const ModelNode &componentNode) -{ - Q_ASSERT(m_masterModel); - QWeakPointer<Model> oldModel = m_model; - Q_ASSERT(oldModel.data()); - - if (m_model == m_subComponentModel) - changeToMasterModel(); - - QString componentText = m_rewriterView->extractText(QList<ModelNode>() << componentNode).value(componentNode); - - if (componentText.isEmpty()) - return; - - bool explicitComponent = false; - if (componentText.contains("Component")) { //explicit component - explicitComponent = true; - } - - m_componentNode = componentNode; - if (!componentNode.isRootNode()) { - Q_ASSERT(m_model == m_masterModel); - Q_ASSERT(componentNode.isValid()); - //change to subcomponent model - ModelNode rootModelNode = componentNode.view()->rootModelNode(); - Q_ASSERT(rootModelNode.isValid()); - if (m_componentTextModifier) - delete m_componentTextModifier; - - - int componentStartOffset; - int componentEndOffset; - - int rootStartOffset = m_rewriterView->nodeOffset(rootModelNode); - - if (explicitComponent) { //the component is explciit we have to find the first definition inside - componentStartOffset = m_rewriterView->firstDefinitionInsideOffset(componentNode); - componentEndOffset = componentStartOffset + m_rewriterView->firstDefinitionInsideLength(componentNode); - } else { //the component is implicit - componentStartOffset = m_rewriterView->nodeOffset(componentNode); - componentEndOffset = componentStartOffset + m_rewriterView->nodeLength(componentNode); - } - - m_componentTextModifier = new ComponentTextModifier (m_textModifier, componentStartOffset, componentEndOffset, rootStartOffset); - - - m_model->detachView(m_rewriterView.data()); - - m_rewriterView->setTextModifier(m_componentTextModifier); - - m_subComponentModel->attachView(m_rewriterView.data()); - - Q_ASSERT(m_rewriterView->rootModelNode().isValid()); - - m_model = m_subComponentModel; - } - - Q_ASSERT(m_masterModel); - Q_ASSERT(m_model); - - loadCurrentModel(); - m_componentView->setComponentNode(componentNode); -} - -void DesignDocumentController::changeToExternalSubComponent(const QString &fileName) -{ - s_clearCrumblePath = false; - Core::EditorManager::openEditor(fileName); - s_clearCrumblePath = true; -} - -void DesignDocumentController::goIntoComponent() -{ - if (!m_model) - return; - - QList<ModelNode> selectedNodes; - if (m_formEditorView) - selectedNodes = m_formEditorView->selectedModelNodes(); - - s_clearCrumblePath = false; - if (selectedNodes.count() == 1) - ModelNodeOperations::goIntoComponent(selectedNodes.first()); - s_clearCrumblePath = true; -} - -void DesignDocumentController::loadCurrentModel() -{ - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - - Q_ASSERT(m_masterModel); - Q_ASSERT(m_model); - m_model->setMasterModel(m_masterModel.data()); - m_masterModel->attachView(m_componentView.data()); - - m_nodeInstanceView->setPathToQt(pathToQt()); - m_model->attachView(m_nodeInstanceView.data()); - m_model->attachView(m_navigator.data()); - m_itemLibraryView->widget()->setResourcePath(QFileInfo(m_fileName).absolutePath()); - - m_model->attachView(m_formEditorView.data()); - m_model->attachView(m_itemLibraryView.data()); - - if (!m_textEdit->parent()) // hack to prevent changing owner of external text edit - m_stackedWidget->addWidget(m_textEdit.data()); - - // Will call setCurrentState (formEditorView etc has to be constructed first) - m_model->attachView(m_statesEditorView.data()); - - m_model->attachView(m_propertyEditorView.data()); - - m_model->attachView(DesignerActionManager::view()); - - if (s_clearCrumblePath) - m_formEditorView->crumblePath()->clear(); - - if (s_pushCrumblePath && - !compareCrumbleBarInfo(m_formEditorView->crumblePath()->dataForLastIndex().value<CrumbleBarInfo>(), - createCrumbleBarInfo().value<CrumbleBarInfo>())) - m_formEditorView->crumblePath()->pushElement(simplfiedDisplayName(), createCrumbleBarInfo()); - - m_documentLoaded = true; - m_subComponentManager->update(m_searchPath, m_model->imports()); - Q_ASSERT(m_masterModel); - QApplication::restoreOverrideCursor(); -} - -QList<RewriterView::Error> DesignDocumentController::loadMaster(const QByteArray &qml) -{ - QPlainTextEdit *textEdit = new QPlainTextEdit; - textEdit->setReadOnly(true); - textEdit->setPlainText(QString(qml)); - return loadMaster(textEdit); -} - -void DesignDocumentController::saveAs(QWidget *parent) -{ - QFileInfo oldFileInfo(m_fileName); - XUIFileDialog::runSaveFileDialog(oldFileInfo.path(), parent, this, SLOT(doRealSaveAs(QString))); -} - -void DesignDocumentController::doRealSaveAs(const QString &fileName) -{ - if (fileName.isNull()) - return; - - QFileInfo fileInfo(fileName); - if (fileInfo.exists() && !fileInfo.isWritable()) { - QMessageBox msgBox(centralWidget()); - msgBox.setIcon(QMessageBox::Warning); - msgBox.setText(tr("Cannot save to file \"%1\": permission denied.").arg(fileInfo.baseName())); - msgBox.exec(); - return; - } else if (!fileInfo.exists() && !fileInfo.dir().exists()) { - QMessageBox msgBox(centralWidget()); - msgBox.setIcon(QMessageBox::Warning); - msgBox.setText(tr("Parent folder \"%1\" for file \"%2\" does not exist.") - .arg(fileInfo.dir().dirName()) - .arg(fileInfo.baseName())); - msgBox.exec(); - return; - } - - setFileName(fileName); - save(centralWidget()); -} - -bool DesignDocumentController::isDirty() const -{ - if (m_textEdit) - return m_textEdit->document()->isModified(); - else - return false; -} - -bool DesignDocumentController::isUndoAvailable() const -{ - - if (m_textEdit) - return m_textEdit->document()->isUndoAvailable(); - return false; -} - -bool DesignDocumentController::isRedoAvailable() const -{ - if (m_textEdit) - return m_textEdit->document()->isRedoAvailable(); - return false; -} - -void DesignDocumentController::close() -{ - m_documentLoaded = false; - emit designDocumentClosed(); -} - -void DesignDocumentController::deleteSelected() -{ - if (!m_model) - return; - - try { - if (m_formEditorView) { - RewriterTransaction transaction(m_formEditorView.data()); - QList<ModelNode> toDelete = m_formEditorView->selectedModelNodes(); - foreach (ModelNode node, toDelete) { - if (node.isValid() && !node.isRootNode() && QmlObjectNode(node).isValid()) - QmlObjectNode(node).destroy(); - } - } - } catch (RewritingException &e) { - QMessageBox::warning(0, tr("Error"), e.description()); - } -} - -void DesignDocumentController::copySelected() -{ - QScopedPointer<Model> copyModel(Model::create("QtQuick.Rectangle", 1, 0, model())); - copyModel->setFileUrl(model()->fileUrl()); - copyModel->changeImports(model()->imports(), QList<Import>()); - - Q_ASSERT(copyModel); - - DesignDocumentControllerView view; - - m_model->attachView(&view); - - if (view.selectedModelNodes().isEmpty()) - return; - - QList<ModelNode> selectedNodes(view.selectedModelNodes()); - - foreach (const ModelNode &node, selectedNodes) { - foreach (const ModelNode &node2, selectedNodes) { - if (node.isAncestorOf(node2)) - selectedNodes.removeAll(node2); - } - } - - if (selectedNodes.count() == 1) { - ModelNode selectedNode(selectedNodes.first()); - - if (!selectedNode.isValid()) - return; - - m_model->detachView(&view); - - copyModel->attachView(&view); - view.replaceModel(selectedNode); - - Q_ASSERT(view.rootModelNode().isValid()); - Q_ASSERT(view.rootModelNode().type() != "empty"); - - view.toClipboard(); - } else { //multi items selected - m_model->detachView(&view); - copyModel->attachView(&view); - - foreach (ModelNode node, view.rootModelNode().allDirectSubModelNodes()) { - node.destroy(); - } - view.changeRootNodeType("QtQuick.Rectangle", 1, 0); - view.rootModelNode().setId("designer__Selection"); - - foreach (const ModelNode &selectedNode, selectedNodes) { - ModelNode newNode(view.insertModel(selectedNode)); - view.rootModelNode().nodeListProperty("data").reparentHere(newNode); - } - - view.toClipboard(); - } -} - -void DesignDocumentController::cutSelected() -{ - copySelected(); - deleteSelected(); -} - -static void scatterItem(ModelNode pastedNode, const ModelNode targetNode, int offset = -2000) -{ - - bool scatter = false; - foreach (const ModelNode &childNode, targetNode.allDirectSubModelNodes()) { - if ((childNode.variantProperty("x").value() == pastedNode.variantProperty("x").value()) && - (childNode.variantProperty("y").value() == pastedNode.variantProperty("y").value())) - scatter = true; - } - if (!scatter) - return; - - if (offset == -2000) { - double x = pastedNode.variantProperty("x").value().toDouble(); - double y = pastedNode.variantProperty("y").value().toDouble(); - double targetWidth = 20; - double targetHeight = 20; - x = x + double(qrand()) / RAND_MAX * targetWidth - targetWidth / 2; - y = y + double(qrand()) / RAND_MAX * targetHeight - targetHeight / 2; - pastedNode.variantProperty("x") = int(x); - pastedNode.variantProperty("y") = int(y); - } else { - double x = pastedNode.variantProperty("x").value().toDouble(); - double y = pastedNode.variantProperty("y").value().toDouble(); - x = x + offset; - y = y + offset; - pastedNode.variantProperty("x") = int(x); - pastedNode.variantProperty("y") = int(y); - } -} - -void DesignDocumentController::paste() -{ - QScopedPointer<Model> pasteModel(Model::create("empty", 1, 0, model())); - pasteModel->setFileUrl(model()->fileUrl()); - pasteModel->changeImports(model()->imports(), QList<Import>()); - - Q_ASSERT(pasteModel); - - if (!pasteModel) - return; - - DesignDocumentControllerView view; - pasteModel->attachView(&view); - - view.fromClipboard(); - - ModelNode rootNode(view.rootModelNode()); - - if (rootNode.type() == "empty") - return; - - if (rootNode.id() == "designer__Selection") { - QList<ModelNode> selectedNodes = rootNode.allDirectSubModelNodes(); - qDebug() << rootNode; - qDebug() << selectedNodes; - pasteModel->detachView(&view); - m_model->attachView(&view); - - ModelNode targetNode; - - if (!view.selectedModelNodes().isEmpty()) - targetNode = view.selectedModelNodes().first(); - - //In case we copy and paste a selection we paste in the parent item - if ((view.selectedModelNodes().count() == selectedNodes.count()) && targetNode.isValid() && targetNode.parentProperty().isValid()) - targetNode = targetNode.parentProperty().parentModelNode(); - - if (!targetNode.isValid()) - targetNode = view.rootModelNode(); - - foreach (const ModelNode &node, selectedNodes) { - foreach (const ModelNode &node2, selectedNodes) { - if (node.isAncestorOf(node2)) - selectedNodes.removeAll(node2); - } - } - - QList<ModelNode> pastedNodeList; - - try { - RewriterTransaction transaction(m_formEditorView.data()); - - int offset = double(qrand()) / RAND_MAX * 20 - 10; - - foreach (const ModelNode &node, selectedNodes) { - QString defaultProperty(targetNode.metaInfo().defaultPropertyName()); - ModelNode pastedNode(view.insertModel(node)); - pastedNodeList.append(pastedNode); - scatterItem(pastedNode, targetNode, offset); - targetNode.nodeListProperty(defaultProperty).reparentHere(pastedNode); - } - - view.setSelectedModelNodes(pastedNodeList); - } catch (RewritingException &e) { - qWarning() << e.description(); //silent error - } - } else { - try { - RewriterTransaction transaction(m_formEditorView.data()); - - pasteModel->detachView(&view); - m_model->attachView(&view); - ModelNode pastedNode(view.insertModel(rootNode)); - ModelNode targetNode; - - if (!view.selectedModelNodes().isEmpty()) - targetNode = view.selectedModelNodes().first(); - - if (!targetNode.isValid()) - targetNode = view.rootModelNode(); - - if (targetNode.parentProperty().isValid() && - (pastedNode.simplifiedTypeName() == targetNode.simplifiedTypeName()) && - (pastedNode.variantProperty("width").value() == targetNode.variantProperty("width").value()) && - (pastedNode.variantProperty("height").value() == targetNode.variantProperty("height").value())) - - targetNode = targetNode.parentProperty().parentModelNode(); - - QString defaultProperty(targetNode.metaInfo().defaultPropertyName()); - - scatterItem(pastedNode, targetNode); - if (targetNode.nodeListProperty(defaultProperty).isValid()) - targetNode.nodeListProperty(defaultProperty).reparentHere(pastedNode); - - transaction.commit(); - NodeMetaInfo::clearCache(); - - view.setSelectedModelNodes(QList<ModelNode>() << pastedNode); - } catch (RewritingException &e) { - qWarning() << e.description(); //silent error - } - } -} - -void DesignDocumentController::selectAll() -{ - if (!m_model) - return; - - DesignDocumentControllerView view; - m_model->attachView(&view); - - - QList<ModelNode> allNodesExceptRootNode(view.allModelNodes()); - allNodesExceptRootNode.removeOne(view.rootModelNode()); - view.setSelectedModelNodes(allNodesExceptRootNode); -} - -RewriterView *DesignDocumentController::rewriterView() const -{ - return m_rewriterView.data(); -} - -void DesignDocumentController::undo() -{ - if (m_rewriterView && !m_rewriterView->modificationGroupActive()) - m_textEdit->undo(); - m_propertyEditorView->resetView(); -} - -void DesignDocumentController::redo() -{ - if (m_rewriterView && !m_rewriterView->modificationGroupActive()) - m_textEdit->redo(); - m_propertyEditorView->resetView(); -} - -static inline QtSupport::BaseQtVersion *getActiveQtVersion(DesignDocumentController *controller) -{ - ProjectExplorer::ProjectExplorerPlugin *projectExplorer = ProjectExplorer::ProjectExplorerPlugin::instance(); - ProjectExplorer::Project *currentProject = projectExplorer->currentProject(); - - if (!currentProject) - return 0; - - controller->disconnect(controller, SLOT(activeQtVersionChanged())); - controller->connect(projectExplorer, SIGNAL(currentProjectChanged(ProjectExplorer::Project*)), controller, SLOT(activeQtVersionChanged())); - - controller->connect(currentProject, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)), controller, SLOT(activeQtVersionChanged())); - - - ProjectExplorer::Target *target = currentProject->activeTarget(); - - if (!target) - return 0; - - controller->connect(target, SIGNAL(kitChanged()), controller, SLOT(activeQtVersionChanged())); - return QtSupport::QtKitInformation::qtVersion(target->kit()); -} - -void DesignDocumentController::activeQtVersionChanged() -{ - QtSupport::BaseQtVersion *newQtVersion = getActiveQtVersion(this); - - if (!newQtVersion ) { - m_qt_versionId = -1; - return; - } - - if (m_qt_versionId == newQtVersion->uniqueId()) - return; - - m_qt_versionId = newQtVersion->uniqueId(); - - if (m_nodeInstanceView) - m_nodeInstanceView->setPathToQt(pathToQt()); -} - -#ifdef ENABLE_TEXT_VIEW -void DesignDocumentController::showText() -{ - m_stackedWidget->setCurrentWidget(m_textEdit.data()); -} -#endif // ENABLE_TEXT_VIEW - -#ifdef ENABLE_TEXT_VIEW -void DesignDocumentController::showForm() -{ - m_stackedWidget->setCurrentWidget(m_formEditorView->widget()); -} -#endif // ENABLE_TEXT_VIEW - -bool DesignDocumentController::save(QWidget *parent) -{ - // qDebug() << "Saving document to file \"" << fileName << "\"..."; - // - if (m_fileName.isEmpty()) { - saveAs(parent); - return true; - } - Utils::FileSaver saver(m_fileName, QIODevice::Text); - if (m_model) - saver.write(m_textEdit->toPlainText().toLatin1()); - if (!saver.finalize(parent ? parent : m_stackedWidget.data())) - return false; - if (m_model) - m_textEdit->setPlainText(m_textEdit->toPlainText()); // clear undo/redo history - - return true; -} - - -QString DesignDocumentController::contextHelpId() const -{ - DesignDocumentControllerView view; - m_model->attachView(&view); - - QList<ModelNode> nodes = view.selectedModelNodes(); - QString helpId; - if (!nodes.isEmpty()) { - helpId = nodes.first().type(); - helpId.replace("QtQuick", "QML"); - } - - return helpId; -} - -} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.cpp b/src/plugins/qmldesigner/components/integration/designdocumentview.cpp index 344d6958f3..1d74563da1 100644 --- a/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.cpp +++ b/src/plugins/qmldesigner/components/integration/designdocumentview.cpp @@ -27,7 +27,7 @@ ** ****************************************************************************/ -#include "designdocumentcontrollerview.h" +#include "designdocumentview.h" #include <rewriterview.h> #include <basetexteditmodifier.h> #include <metainfo.h> @@ -40,79 +40,88 @@ namespace QmlDesigner { -void DesignDocumentControllerView::nodeCreated(const ModelNode & /*createdNode*/) {} -void DesignDocumentControllerView::nodeAboutToBeRemoved(const ModelNode & /*removedNode*/) {} -void DesignDocumentControllerView::nodeRemoved(const ModelNode & /*removedNode*/, const NodeAbstractProperty & /*parentProperty*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {} -void DesignDocumentControllerView::nodeAboutToBeReparented(const ModelNode & /*node*/, const NodeAbstractProperty & /*newPropertyParent*/, const NodeAbstractProperty & /*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {} -void DesignDocumentControllerView::nodeReparented(const ModelNode & /*node*/, const NodeAbstractProperty & /*newPropertyParent*/, const NodeAbstractProperty & /*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {} -void DesignDocumentControllerView::nodeIdChanged(const ModelNode& /*node*/, const QString& /*newId*/, const QString& /*oldId*/) {} -void DesignDocumentControllerView::propertiesAboutToBeRemoved(const QList<AbstractProperty>& /*propertyList*/) {} -void DesignDocumentControllerView::propertiesRemoved(const QList<AbstractProperty>& /*propertyList*/) {} -void DesignDocumentControllerView::variantPropertiesChanged(const QList<VariantProperty>& /*propertyList*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {} -void DesignDocumentControllerView::bindingPropertiesChanged(const QList<BindingProperty>& /*propertyList*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {} -void DesignDocumentControllerView::rootNodeTypeChanged(const QString & /*type*/, int /*majorVersion*/, int /*minorVersion*/) {} - -void DesignDocumentControllerView::selectedNodesChanged(const QList<ModelNode> & /*selectedNodeList*/, +DesignDocumentView::DesignDocumentView(QObject *parent) + : AbstractView(parent), m_modelMerger(this) +{ +} + +DesignDocumentView::~DesignDocumentView() +{ +} + +void DesignDocumentView::nodeCreated(const ModelNode & /*createdNode*/) {} +void DesignDocumentView::nodeAboutToBeRemoved(const ModelNode & /*removedNode*/) {} +void DesignDocumentView::nodeRemoved(const ModelNode & /*removedNode*/, const NodeAbstractProperty & /*parentProperty*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {} +void DesignDocumentView::nodeAboutToBeReparented(const ModelNode & /*node*/, const NodeAbstractProperty & /*newPropertyParent*/, const NodeAbstractProperty & /*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {} +void DesignDocumentView::nodeReparented(const ModelNode & /*node*/, const NodeAbstractProperty & /*newPropertyParent*/, const NodeAbstractProperty & /*oldPropertyParent*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {} +void DesignDocumentView::nodeIdChanged(const ModelNode& /*node*/, const QString& /*newId*/, const QString& /*oldId*/) {} +void DesignDocumentView::propertiesAboutToBeRemoved(const QList<AbstractProperty>& /*propertyList*/) {} +void DesignDocumentView::propertiesRemoved(const QList<AbstractProperty>& /*propertyList*/) {} +void DesignDocumentView::variantPropertiesChanged(const QList<VariantProperty>& /*propertyList*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {} +void DesignDocumentView::bindingPropertiesChanged(const QList<BindingProperty>& /*propertyList*/, AbstractView::PropertyChangeFlags /*propertyChange*/) {} +void DesignDocumentView::rootNodeTypeChanged(const QString & /*type*/, int /*majorVersion*/, int /*minorVersion*/) {} + +void DesignDocumentView::selectedNodesChanged(const QList<ModelNode> & /*selectedNodeList*/, const QList<ModelNode> & /*lastSelectedNodeList*/) {} -void DesignDocumentControllerView::nodeOrderChanged(const NodeListProperty & /*listProperty*/, const ModelNode & /*movedNode*/, int /*oldIndex*/) {} +void DesignDocumentView::nodeOrderChanged(const NodeListProperty & /*listProperty*/, const ModelNode & /*movedNode*/, int /*oldIndex*/) {} -void DesignDocumentControllerView::scriptFunctionsChanged(const ModelNode &/*node*/, const QStringList &/*scriptFunctionList*/) +void DesignDocumentView::scriptFunctionsChanged(const ModelNode &/*node*/, const QStringList &/*scriptFunctionList*/) { } -void DesignDocumentControllerView::instancePropertyChange(const QList<QPair<ModelNode, QString> > &/*propertyList*/) +void DesignDocumentView::instancePropertyChange(const QList<QPair<ModelNode, QString> > &/*propertyList*/) { } -void DesignDocumentControllerView::instancesCompleted(const QVector<ModelNode> &/*completedNodeList*/) +void DesignDocumentView::instancesCompleted(const QVector<ModelNode> &/*completedNodeList*/) { } -void DesignDocumentControllerView::instanceInformationsChange(const QMultiHash<ModelNode, InformationName> &/*informationChangeHash*/) +void DesignDocumentView::instanceInformationsChange(const QMultiHash<ModelNode, InformationName> &/*informationChangeHash*/) { } -void DesignDocumentControllerView::instancesRenderImageChanged(const QVector<ModelNode> &/*nodeList*/) +void DesignDocumentView::instancesRenderImageChanged(const QVector<ModelNode> &/*nodeList*/) { } -void DesignDocumentControllerView::instancesPreviewImageChanged(const QVector<ModelNode> &/*nodeList*/) +void DesignDocumentView::instancesPreviewImageChanged(const QVector<ModelNode> &/*nodeList*/) { } -void DesignDocumentControllerView::instancesChildrenChanged(const QVector<ModelNode> &/*nodeList*/) +void DesignDocumentView::instancesChildrenChanged(const QVector<ModelNode> &/*nodeList*/) { } -void DesignDocumentControllerView::instancesToken(const QString &/*tokenName*/, int /*tokenNumber*/, const QVector<ModelNode> &/*nodeVector*/) +void DesignDocumentView::instancesToken(const QString &/*tokenName*/, int /*tokenNumber*/, const QVector<ModelNode> &/*nodeVector*/) { } -void DesignDocumentControllerView::nodeSourceChanged(const ModelNode &, const QString & /*newNodeSource*/) +void DesignDocumentView::nodeSourceChanged(const ModelNode &, const QString & /*newNodeSource*/) { } -void DesignDocumentControllerView::rewriterBeginTransaction() +void DesignDocumentView::rewriterBeginTransaction() { } -void DesignDocumentControllerView::rewriterEndTransaction() +void DesignDocumentView::rewriterEndTransaction() { } -void DesignDocumentControllerView::actualStateChanged(const ModelNode &/*node*/) +void DesignDocumentView::actualStateChanged(const ModelNode &/*node*/) { } -void DesignDocumentControllerView::importsChanged(const QList<Import> &/*addedImports*/, const QList<Import> &/*removedImports*/) +void DesignDocumentView::importsChanged(const QList<Import> &/*addedImports*/, const QList<Import> &/*removedImports*/) { } @@ -131,7 +140,7 @@ static QByteArray stringListToArray(const QStringList &stringList) return str.toLatin1(); } -void DesignDocumentControllerView::toClipboard() const +void DesignDocumentView::toClipboard() const { QClipboard *clipboard = QApplication::clipboard(); @@ -146,7 +155,7 @@ void DesignDocumentControllerView::toClipboard() const clipboard->setMimeData(data); } -void DesignDocumentControllerView::fromClipboard() +void DesignDocumentView::fromClipboard() { QClipboard *clipboard = QApplication::clipboard(); fromText(clipboard->text()); @@ -158,7 +167,7 @@ void DesignDocumentControllerView::fromClipboard() } -QString DesignDocumentControllerView::toText() const +QString DesignDocumentView::toText() const { QScopedPointer<Model> outputModel(Model::create("QtQuick.Rectangle", 1, 0, model())); outputModel->setFileUrl(model()->fileUrl()); @@ -178,7 +187,7 @@ QString DesignDocumentControllerView::toText() const QScopedPointer<RewriterView> rewriterView(new RewriterView(RewriterView::Amend, 0)); rewriterView->setCheckSemanticErrors(false); rewriterView->setTextModifier(&modifier); - outputModel->attachView(rewriterView.data()); + outputModel->setRewriterView(rewriterView.data()); ModelMerger merger(rewriterView.data()); @@ -190,7 +199,7 @@ QString DesignDocumentControllerView::toText() const return rewriterView->extractText(QList<ModelNode>() << rewriterNode).value(rewriterNode); } -void DesignDocumentControllerView::fromText(QString text) +void DesignDocumentView::fromText(QString text) { QScopedPointer<Model> inputModel(Model::create("QtQuick.Rectangle", 1, 0, model())); inputModel->setFileUrl(model()->fileUrl()); @@ -205,7 +214,7 @@ void DesignDocumentControllerView::fromText(QString text) QScopedPointer<RewriterView> rewriterView(new RewriterView(RewriterView::Amend, 0)); rewriterView->setCheckSemanticErrors(false); rewriterView->setTextModifier(&modifier); - inputModel->attachView(rewriterView.data()); + inputModel->setRewriterView(rewriterView.data()); if (rewriterView->errors().isEmpty() && rewriterView->rootModelNode().isValid()) { ModelMerger merger(this); @@ -213,4 +222,9 @@ void DesignDocumentControllerView::fromText(QString text) } } +QWidget *DesignDocumentView::widget() +{ + return 0; +} + }// namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.h b/src/plugins/qmldesigner/components/integration/designdocumentview.h index 8fe4776617..154cd4df0c 100644 --- a/src/plugins/qmldesigner/components/integration/designdocumentcontrollerview.h +++ b/src/plugins/qmldesigner/components/integration/designdocumentview.h @@ -27,20 +27,20 @@ ** ****************************************************************************/ -#ifndef DESIGNDOCUMENTCONTROLLERVIEW_H -#define DESIGNDOCUMENTCONTROLLERVIEW_H +#ifndef DesignDocumentVIEW_H +#define DesignDocumentVIEW_H #include <abstractview.h> #include <modelmerger.h> namespace QmlDesigner { -class DesignDocumentControllerView : public AbstractView +class DesignDocumentView : public AbstractView { Q_OBJECT public: - DesignDocumentControllerView(QObject *parent = 0) - : AbstractView(parent), m_modelMerger(this) {} + DesignDocumentView(QObject *parent = 0); + ~DesignDocumentView(); virtual void nodeCreated(const ModelNode &createdNode); virtual void nodeAboutToBeRemoved(const ModelNode &removedNode); @@ -87,10 +87,12 @@ public: QString toText() const; void fromText(QString text); + QWidget *widget(); + private: ModelMerger m_modelMerger; }; }// namespace QmlDesigner -#endif // DESIGNDOCUMENTCONTROLLERVIEW_H +#endif // DesignDocumentVIEW_H diff --git a/src/plugins/qmldesigner/components/integration/integration.pri b/src/plugins/qmldesigner/components/integration/integration.pri index 66efed8971..586bf12324 100644 --- a/src/plugins/qmldesigner/components/integration/integration.pri +++ b/src/plugins/qmldesigner/components/integration/integration.pri @@ -1,8 +1,8 @@ VPATH += $$PWD INCLUDEPATH += $$PWD SOURCES += \ - designdocumentcontroller.cpp \ - designdocumentcontrollerview.cpp \ + designdocument.cpp \ + designdocumentview.cpp \ utilitypanelcontroller.cpp \ stackedutilitypanelcontroller.cpp \ componentaction.cpp \ @@ -10,8 +10,8 @@ SOURCES += \ xuifiledialog.cpp HEADERS += \ - designdocumentcontrollerview.h \ - designdocumentcontroller.h \ + designdocumentview.h \ + designdocument.h \ utilitypanelcontroller.h \ stackedutilitypanelcontroller.h \ componentaction.h \ diff --git a/src/plugins/qmldesigner/components/integration/stackedutilitypanelcontroller.cpp b/src/plugins/qmldesigner/components/integration/stackedutilitypanelcontroller.cpp index bf374b46e9..496163d146 100644 --- a/src/plugins/qmldesigner/components/integration/stackedutilitypanelcontroller.cpp +++ b/src/plugins/qmldesigner/components/integration/stackedutilitypanelcontroller.cpp @@ -29,7 +29,7 @@ #include <QStackedWidget> -#include "designdocumentcontroller.h" +#include "designdocument.h" #include "stackedutilitypanelcontroller.h" namespace QmlDesigner { @@ -43,12 +43,12 @@ StackedUtilityPanelController::StackedUtilityPanelController(QObject* parent): m_stackedWidget->setFrameStyle(QFrame::NoFrame); } -void StackedUtilityPanelController::show(DesignDocumentController* designDocumentController) +void StackedUtilityPanelController::show(DesignDocument* DesignDocument) { - if (!designDocumentController) + if (!DesignDocument) return; - QWidget* page = stackedPageWidget(designDocumentController); + QWidget* page = stackedPageWidget(DesignDocument); if (!m_stackedWidget->children().contains(page)) m_stackedWidget->addWidget(page); @@ -57,9 +57,9 @@ void StackedUtilityPanelController::show(DesignDocumentController* designDocumen page->show(); } -void StackedUtilityPanelController::close(DesignDocumentController* designDocumentController) +void StackedUtilityPanelController::close(DesignDocument* DesignDocument) { - QWidget* page = stackedPageWidget(designDocumentController); + QWidget* page = stackedPageWidget(DesignDocument); if (m_stackedWidget->children().contains(page)) { page->hide(); diff --git a/src/plugins/qmldesigner/components/integration/stackedutilitypanelcontroller.h b/src/plugins/qmldesigner/components/integration/stackedutilitypanelcontroller.h index 52f8fd37a6..c76209a9dd 100644 --- a/src/plugins/qmldesigner/components/integration/stackedutilitypanelcontroller.h +++ b/src/plugins/qmldesigner/components/integration/stackedutilitypanelcontroller.h @@ -34,7 +34,7 @@ namespace QmlDesigner { -class DesignDocumentController; +class DesignDocument; class StackedUtilityPanelController : public UtilityPanelController { @@ -44,12 +44,12 @@ public: StackedUtilityPanelController(QObject* parent = 0); public slots: - void show(DesignDocumentController* designDocumentController); - void close(DesignDocumentController* designDocumentController); + void show(DesignDocument* DesignDocument); + void close(DesignDocument* DesignDocument); protected: virtual QWidget* contentWidget() const; - virtual QWidget* stackedPageWidget(DesignDocumentController* designDocumentController) const = 0; + virtual QWidget* stackedPageWidget(DesignDocument* DesignDocument) const = 0; private: class QStackedWidget* m_stackedWidget; diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp index f46c771d2b..64a3144a37 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.cpp @@ -33,7 +33,7 @@ namespace QmlDesigner { -ItemLibraryView::ItemLibraryView(QObject* parent) : AbstractView(parent), m_widget(new ItemLibraryWidget) +ItemLibraryView::ItemLibraryView(QObject* parent) : AbstractView(parent) { } @@ -43,8 +43,11 @@ ItemLibraryView::~ItemLibraryView() } -ItemLibraryWidget *ItemLibraryView::widget() +QWidget *ItemLibraryView::widget() { + if (m_widget.isNull()) + m_widget = new ItemLibraryWidget; + return m_widget.data(); } @@ -191,6 +194,14 @@ void ItemLibraryView::actualStateChanged(const ModelNode &/*node*/) { } +void ItemLibraryView::setResourcePath(const QString &resourcePath) +{ + if (m_widget.isNull()) + m_widget = new ItemLibraryWidget; + + m_widget->setResourcePath(resourcePath); +} + void ItemLibraryView::updateImports() { m_widget->updateModel(); diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.h index a11d808c0c..fefde31e3a 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryview.h @@ -48,7 +48,7 @@ public: ItemLibraryView(QObject* parent = 0); ~ItemLibraryView(); - ItemLibraryWidget *widget(); + QWidget *widget(); // AbstractView void modelAttached(Model *model); @@ -90,6 +90,8 @@ public: void actualStateChanged(const ModelNode &node); + void setResourcePath(const QString &resourcePath); + protected: void updateImports(); diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp index 54cb6c154c..46b582b33f 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatorview.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatorview.cpp @@ -94,7 +94,7 @@ NavigatorView::~NavigatorView() delete m_widget.data(); } -NavigatorWidget *NavigatorView::widget() +QWidget *NavigatorView::widget() { return m_widget.data(); } @@ -270,7 +270,7 @@ void NavigatorView::changeToComponent(const QModelIndex &index) { if (index.isValid() && m_treeModel->data(index, Qt::UserRole).isValid()) { ModelNode doubleClickNode = m_treeModel->nodeForIndex(index); - if (doubleClickNode.metaInfo().isComponent()) + if (doubleClickNode.metaInfo().isFileComponent()) Core::EditorManager::openEditor(doubleClickNode.metaInfo().componentFileName()); } } diff --git a/src/plugins/qmldesigner/components/navigator/navigatorview.h b/src/plugins/qmldesigner/components/navigator/navigatorview.h index 55beb6d7db..35c5ab8fa2 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatorview.h +++ b/src/plugins/qmldesigner/components/navigator/navigatorview.h @@ -56,7 +56,7 @@ public: NavigatorView(QObject* parent = 0); ~NavigatorView(); - NavigatorWidget *widget(); + QWidget *widget(); // AbstractView void modelAttached(Model *model); diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp index 19b686f435..873894f2b2 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditor.cpp @@ -991,7 +991,6 @@ void PropertyEditor::select(const ModelNode &node) QWidget *PropertyEditor::widget() { - delayedResetView(); return m_stackedWidget; } diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp index 02d6290457..39058210ad 100644 --- a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp +++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp @@ -53,17 +53,15 @@ namespace QmlDesigner { StatesEditorView::StatesEditorView(QObject *parent) : QmlModelView(parent), m_statesEditorModel(new StatesEditorModel(this)), + m_statesEditorWidget(new StatesEditorWidget(this, m_statesEditorModel.data())), m_lastIndex(-1) { Q_ASSERT(m_statesEditorModel); // base state } -StatesEditorWidget *StatesEditorView::widget() +QWidget *StatesEditorView::widget() { - if (m_statesEditorWidget.isNull()) - m_statesEditorWidget = new StatesEditorWidget(this, m_statesEditorModel.data()); - return m_statesEditorWidget.data(); } diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h index f32520bc2e..2ab6a23454 100644 --- a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h +++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.h @@ -76,7 +76,7 @@ public: void instancesPreviewImageChanged(const QVector<ModelNode> &nodeList); - StatesEditorWidget *widget(); + QWidget *widget(); public slots: void synchonizeCurrentStateFromWidget(); @@ -84,6 +84,7 @@ public slots: void removeState(int nodeId); private: + StatesEditorWidget *statesEditorWidget() const; void resetModel(); void addState(); void duplicateCurrentState(); diff --git a/src/plugins/qmldesigner/designercore/designercore-lib.pri b/src/plugins/qmldesigner/designercore/designercore-lib.pri index b7339a1465..96609f2ac6 100644 --- a/src/plugins/qmldesigner/designercore/designercore-lib.pri +++ b/src/plugins/qmldesigner/designercore/designercore-lib.pri @@ -75,7 +75,8 @@ SOURCES += $$PWD/model/abstractview.cpp \ $$PWD/model/rewriteactioncompressor.cpp \ $$PWD/model/qmltextgenerator.cpp \ $$PWD/model/modelmerger.cpp \ - $$PWD/exceptions/rewritingexception.cpp + $$PWD/exceptions/rewritingexception.cpp \ + $$PWD/model/viewmanager.cpp HEADERS += $$PWD/include/qmldesignercorelib_global.h \ $$PWD/include/abstractview.h \ @@ -145,7 +146,8 @@ HEADERS += $$PWD/include/qmldesignercorelib_global.h \ $$PWD/include/modelmerger.h \ $$PWD/include/mathutils.h \ $$PWD/include/customnotifications.h \ - $$PWD/include/rewritingexception.h + $$PWD/include/rewritingexception.h \ + $$PWD/include/viewmanager.h contains(CONFIG, plugin) { # If core.pri has been included in the qmldesigner plugin diff --git a/src/plugins/qmldesigner/designercore/filemanager/qmlwarningdialog.cpp b/src/plugins/qmldesigner/designercore/filemanager/qmlwarningdialog.cpp index 0bf1dedc15..da730a0355 100644 --- a/src/plugins/qmldesigner/designercore/filemanager/qmlwarningdialog.cpp +++ b/src/plugins/qmldesigner/designercore/filemanager/qmlwarningdialog.cpp @@ -50,7 +50,7 @@ void QmlWarningDialog::okButtonPressed() bool QmlWarningDialog::warningsEnabled() const { #ifndef QMLDESIGNER_TEST - DesignerSettings settings = BauhausPlugin::pluginInstance()->settings(); + DesignerSettings settings = QmlDesignerPlugin::instance()->settings(); return settings.warningsInDesigner; #else return false; @@ -60,9 +60,9 @@ bool QmlWarningDialog::warningsEnabled() const void QmlWarningDialog::checkBoxToggled(bool b) { #ifndef QMLDESIGNER_TEST - DesignerSettings settings = BauhausPlugin::pluginInstance()->settings(); + DesignerSettings settings = QmlDesignerPlugin::instance()->settings(); settings.warningsInDesigner = b; - BauhausPlugin::pluginInstance()->setSettings(settings); + QmlDesignerPlugin::instance()->setSettings(settings); #else Q_UNUSED(b); #endif diff --git a/src/plugins/qmldesigner/designercore/include/abstractview.h b/src/plugins/qmldesigner/designercore/include/abstractview.h index 5b45b1a1b2..0f4ef6d0af 100644 --- a/src/plugins/qmldesigner/designercore/include/abstractview.h +++ b/src/plugins/qmldesigner/designercore/include/abstractview.h @@ -77,6 +77,7 @@ public: virtual ~AbstractView(); Model* model() const; + bool isAttached() const; RewriterTransaction beginRewriterTransaction(); @@ -104,7 +105,7 @@ public: ModelNode modelNodeForInternalId(qint32 internalId); bool hasModelNodeForInternalId(qint32 internalId) const; - QList<ModelNode> allModelNodes(); + QList<ModelNode> allModelNodes() const; void emitCustomNotification(const QString &identifier); void emitCustomNotification(const QString &identifier, const QList<ModelNode> &nodeList); @@ -179,6 +180,8 @@ public: void resetView(); + virtual QWidget *widget() = 0; + protected: void setModel(Model * model); void removeModel(); diff --git a/src/plugins/qmldesigner/designercore/include/model.h b/src/plugins/qmldesigner/designercore/include/model.h index 6cfedd43f1..257998c012 100644 --- a/src/plugins/qmldesigner/designercore/include/model.h +++ b/src/plugins/qmldesigner/designercore/include/model.h @@ -58,6 +58,7 @@ class ModelState; class NodeAnchors; class AbstractProperty; class RewriterView; +class NodeInstanceView; typedef QList<QPair<QString, QVariant> > PropertyListType; @@ -80,9 +81,6 @@ public: static Model *create(QString type, int major = 1, int minor = 1, Model *metaInfoPropxyModel = 0); - Model *masterModel() const; - void setMasterModel(Model *model); - QUrl fileUrl() const; void setFileUrl(const QUrl &url); @@ -103,6 +101,10 @@ public: QString pathForImport(const Import &import); RewriterView *rewriterView() const; + void setRewriterView(RewriterView *rewriterView); + + NodeInstanceView *nodeInstanceView() const; + void setNodeInstanceView(NodeInstanceView *nodeInstanceView); Model *metaInfoProxyModel(); diff --git a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h index 2be9671a98..e23737899f 100644 --- a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h +++ b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h @@ -143,6 +143,8 @@ public: void sendToken(const QString &token, int number, const QVector<ModelNode> &nodeVector); + QWidget *widget(); + signals: void qmlPuppetCrashed(); diff --git a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h index d78e72cd26..4652f961df 100644 --- a/src/plugins/qmldesigner/designercore/include/nodemetainfo.h +++ b/src/plugins/qmldesigner/designercore/include/nodemetainfo.h @@ -68,7 +68,7 @@ public: NodeMetaInfo &operator=(const NodeMetaInfo &other); bool isValid() const; - bool isComponent() const; + bool isFileComponent() const; bool hasProperty(const QString &propertyName) const; QStringList propertyNames() const; QStringList directPropertyNames() const; diff --git a/src/plugins/qmldesigner/designercore/include/rewriterview.h b/src/plugins/qmldesigner/designercore/include/rewriterview.h index 76444cace5..bb0fd292bd 100644 --- a/src/plugins/qmldesigner/designercore/include/rewriterview.h +++ b/src/plugins/qmldesigner/designercore/include/rewriterview.h @@ -163,6 +163,9 @@ public: void setTextModifier(TextModifier *textModifier); QString textModifierContent() const; + void reactivateTextMofifierChangeSignals(); + void deactivateTextMofifierChangeSignals(); + Internal::ModelNodePositionStorage *positionStorage() const { return m_positionStorage; } @@ -182,6 +185,7 @@ public: int firstDefinitionInsideOffset(const ModelNode &node) const; int firstDefinitionInsideLength(const ModelNode &node) const; bool modificationGroupActive(); + ModelNode nodeAtTextCursorPosition(int cursorPosition) const; bool renameId(const QString& oldId, const QString& newId); @@ -198,6 +202,8 @@ public: QString pathForImport(const Import &import); + QWidget *widget(); + signals: void errorsChanged(const QList<RewriterView::Error> &errors); diff --git a/src/plugins/qmldesigner/designercore/include/viewmanager.h b/src/plugins/qmldesigner/designercore/include/viewmanager.h new file mode 100644 index 0000000000..481c050d33 --- /dev/null +++ b/src/plugins/qmldesigner/designercore/include/viewmanager.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLDESIGNER_VIEWMANAGER_H +#define QMLDESIGNER_VIEWMANAGER_H + +#include "abstractview.h" + +#include <rewriterview.h> +#include <nodeinstanceview.h> +#include <itemlibraryview.h> +#include <navigatorview.h> +#include <stateseditorview.h> +#include <formeditorview.h> +#include <propertyeditor.h> +#include <componentview.h> +#include <model/viewlogger.h> + +namespace QmlDesigner { + +class DesignDocument; + +namespace Internal { + class DesignModeWidget; +} + +class ViewManager +{ +public: + ViewManager(); + + void attachRewriterView(TextModifier *textModifier); + void detachRewriterView(); + + void attachComponentView(); + void detachComponentView(); + + void attachViewsExceptRewriterAndComponetView(); + void detachViewsExceptRewriterAndComponetView(); + + void setItemLibraryViewResourcePath(const QString &resourcePath); + void setComponentNode(const ModelNode &componentNode); + void setNodeInstanceViewQtPath(const QString & qtPath); + + void resetPropertyEditorView(); + + QWidget *formEditorWidget(); + QWidget *propertyEditorWidget(); + QWidget *itemLibraryWidget(); + QWidget *navigatorWidget(); + QWidget *statesEditorWidget(); + + void pushFileOnCrambleBar(const QString &fileName); + void pushInFileComponentOnCrambleBar(const QString &componentId); + void nextFileIsCalledInternally(); + +private: // functions + Q_DISABLE_COPY(ViewManager) + + void attachNodeInstanceView(); + void attachItemLibraryView(); + + + + Model *currentModel() const; + Model *documentModel() const; + DesignDocument *currentDesignDocument() const; + QString pathToQt() const; + + void switchStateEditorViewToBaseState(); + void switchStateEditorViewToSavedState(); + +private: // variables + QmlModelState m_savedState; + Internal::ViewLogger m_viewLogger; + ComponentView m_componentView; + FormEditorView m_formEditorView; + ItemLibraryView m_itemLibraryView; + NavigatorView m_navigatorView; + PropertyEditor m_propertyEditorView; + StatesEditorView m_statesEditorView; + NodeInstanceView m_nodeInstanceView; + + QList<QWeakPointer<AbstractView> > m_additionalViews; +}; + +} // namespace QmlDesigner + +#endif // QMLDESIGNER_VIEWMANAGER_H diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp index d98a5cd09e..2cc73251dc 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp @@ -1219,4 +1219,9 @@ void NodeInstanceView::sendToken(const QString &token, int number, const QVector nodeInstanceServer()->token(TokenCommand(token, number, instanceIdVector)); } +QWidget *NodeInstanceView::widget() +{ + return 0; +} + } diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp index 0eb345f03b..175f4dc3a0 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp @@ -327,29 +327,10 @@ public: ~NodeMetaInfoPrivate() {} bool isValid() const; - - bool isComponent() const - { - return m_isComponent; - } - - QStringList properties() const - { - return m_properties; - } - - QStringList localProperties() const - { - return m_localProperties; - } - - QString defaultPropertyName() const - { - if (!m_defaultPropertyName.isEmpty()) - return m_defaultPropertyName; - return QLatin1String("data"); - } - + bool isFileComponent() const; + QStringList properties() const; + QStringList localProperties() const; + QString defaultPropertyName() const; QString propertyType(const QString &propertyName) const; void setupPrototypes(); @@ -364,17 +345,10 @@ public: bool cleverCheckType(const QString &otherType) const; QVariant::Type variantTypeId(const QString &properyName) const; - int majorVersion() const - { return m_majorVersion; } - - int minorVersion() const - { return m_minorVersion; } - - QString qualfiedTypeName() const - { return m_qualfiedTypeName; } - - Model *model() const - { return m_model; } + int majorVersion() const; + int minorVersion() const; + QString qualfiedTypeName() const; + Model *model() const; QString cppPackageName() const; @@ -384,20 +358,11 @@ public: static Pointer create(Model *model, const QString &type, int maj = -1, int min = -1); - QSet<QString> &prototypeCachePositives() - { - return m_prototypeCachePositives; - } + QSet<QString> &prototypeCachePositives(); + QSet<QString> &prototypeCacheNegatives(); - QSet<QString> &prototypeCacheNegatives() - { - return m_prototypeCacheNegatives; - } + static void clearCache(); - static void clearCache() - { - m_nodeMetaInfoCache.clear(); - } private: NodeMetaInfoPrivate(Model *model, QString type, int maj = -1, int min = -1); @@ -415,7 +380,7 @@ private: int m_majorVersion; int m_minorVersion; bool m_isValid; - bool m_isComponent; + bool m_isFileComponent; QStringList m_properties; QStringList m_propertyTypes; QStringList m_localProperties; @@ -434,6 +399,42 @@ private: QHash<QString, NodeMetaInfoPrivate::Pointer> NodeMetaInfoPrivate::m_nodeMetaInfoCache; +bool NodeMetaInfoPrivate::isFileComponent() const +{ + return m_isFileComponent; +} + +QStringList NodeMetaInfoPrivate::properties() const +{ + return m_properties; +} + +QStringList NodeMetaInfoPrivate::localProperties() const +{ + return m_localProperties; +} + +QSet<QString> &NodeMetaInfoPrivate::prototypeCachePositives() +{ + return m_prototypeCachePositives; +} + +QSet<QString> &NodeMetaInfoPrivate::prototypeCacheNegatives() +{ + return m_prototypeCacheNegatives; +} + +void NodeMetaInfoPrivate::clearCache() +{ + m_nodeMetaInfoCache.clear(); +} + +QString NodeMetaInfoPrivate::defaultPropertyName() const +{ + if (!m_defaultPropertyName.isEmpty()) + return m_defaultPropertyName; + return QLatin1String("data"); +} static inline QString stringIdentifier( const QString &type, int maj, int min) { @@ -463,7 +464,7 @@ NodeMetaInfoPrivate::NodeMetaInfoPrivate() : m_isValid(false) NodeMetaInfoPrivate::NodeMetaInfoPrivate(Model *model, QString type, int maj, int min) : m_qualfiedTypeName(type), m_majorVersion(maj), - m_minorVersion(min), m_isValid(false), m_isComponent(false), + m_minorVersion(min), m_isValid(false), m_isFileComponent(false), m_model(model) { if (context()) { @@ -493,7 +494,7 @@ NodeMetaInfoPrivate::NodeMetaInfoPrivate(Model *model, QString type, int maj, in return; } } else { - m_isComponent = true; + m_isFileComponent = true; } setupPropertyInfo(getTypes(objectValue, context())); setupLocalPropertyInfo(getTypes(objectValue, context(), true)); @@ -731,7 +732,7 @@ bool NodeMetaInfoPrivate::cleverCheckType(const QString &otherType) const if (otherType == qualfiedTypeName()) return true; - if (isComponent()) + if (isFileComponent()) return false; QStringList split = otherType.split('.'); @@ -793,6 +794,26 @@ QVariant::Type NodeMetaInfoPrivate::variantTypeId(const QString &properyName) co return QVariant::nameToType(typeName.toLatin1().data()); } +int NodeMetaInfoPrivate::majorVersion() const +{ + return m_majorVersion; +} + +int NodeMetaInfoPrivate::minorVersion() const +{ + return m_minorVersion; +} + +QString NodeMetaInfoPrivate::qualfiedTypeName() const +{ + return m_qualfiedTypeName; +} + +Model *NodeMetaInfoPrivate::model() const +{ + return m_model; +} + QStringList NodeMetaInfoPrivate::keysForEnum(const QString &enumName) const { @@ -807,7 +828,7 @@ QStringList NodeMetaInfoPrivate::keysForEnum(const QString &enumName) const QString NodeMetaInfoPrivate::cppPackageName() const { - if (!isComponent()) { + if (!isFileComponent()) { if (const CppComponentValue *qmlObject = getCppComponentValue()) return qmlObject->moduleName(); } @@ -816,7 +837,7 @@ QString NodeMetaInfoPrivate::cppPackageName() const QString NodeMetaInfoPrivate::componentSource() const { - if (isComponent()) { + if (isFileComponent()) { const ASTObjectValue * astObjectValue = value_cast<ASTObjectValue>(getObjectValue()); if (astObjectValue) return astObjectValue->document()->source().mid(astObjectValue->typeName()->identifierToken.begin(), @@ -827,7 +848,7 @@ QString NodeMetaInfoPrivate::componentSource() const QString NodeMetaInfoPrivate::componentFileName() const { - if (isComponent()) { + if (isFileComponent()) { const ASTObjectValue * astObjectValue = value_cast<ASTObjectValue>(getObjectValue()); if (astObjectValue) { QString fileName; @@ -890,7 +911,7 @@ QString NodeMetaInfoPrivate::propertyType(const QString &propertyName) const void NodeMetaInfoPrivate::setupPrototypes() { QList<const ObjectValue *> objects; - if (m_isComponent) + if (m_isFileComponent) objects = PrototypeIterator(getObjectValue(), context()).all(); else objects = PrototypeIterator(getCppComponentValue(), context()).all(); @@ -927,7 +948,7 @@ QList<TypeDescription> NodeMetaInfoPrivate::prototypes() const const QmlJS::CppComponentValue *NodeMetaInfoPrivate::getNearestCppComponentValue() const { - if (m_isComponent) + if (m_isFileComponent) return findQmlPrototype(getObjectValue(), context()); return getCppComponentValue(); } @@ -973,9 +994,9 @@ bool NodeMetaInfo::isValid() const return m_privateData->isValid(); } -bool NodeMetaInfo::isComponent() const +bool NodeMetaInfo::isFileComponent() const { - return m_privateData->isComponent(); + return m_privateData->isFileComponent(); } bool NodeMetaInfo::hasProperty(const QString &propertyName) const diff --git a/src/plugins/qmldesigner/designercore/model/abstractview.cpp b/src/plugins/qmldesigner/designercore/model/abstractview.cpp index 16a7abd0af..3788854486 100644 --- a/src/plugins/qmldesigner/designercore/model/abstractview.cpp +++ b/src/plugins/qmldesigner/designercore/model/abstractview.cpp @@ -132,6 +132,11 @@ Model* AbstractView::model() const return m_model.data(); } +bool AbstractView::isAttached() const +{ + return model(); +} + /*! \brief is called if a view is being attached to a model \param model which is being attached @@ -362,7 +367,7 @@ void AbstractView::resetView() currentModel->attachView(this); } -QList<ModelNode> AbstractView::allModelNodes() +QList<ModelNode> AbstractView::allModelNodes() const { return toModelNodeList(model()->d->allNodes()); } diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp index 41958022ab..8e8036f5bc 100644 --- a/src/plugins/qmldesigner/designercore/model/model.cpp +++ b/src/plugins/qmldesigner/designercore/model/model.cpp @@ -1525,12 +1525,13 @@ void ModelPrivate::setRewriterView(RewriterView *rewriterView) Q_ASSERT(!(rewriterView && m_rewriterView)); + if (m_rewriterView) + m_rewriterView->modelAboutToBeDetached(model()); + m_rewriterView = rewriterView; if (rewriterView) rewriterView->modelAttached(model()); - else if (m_rewriterView) - m_rewriterView->modelAboutToBeDetached(model()); } RewriterView *ModelPrivate::rewriterView() const @@ -1730,6 +1731,21 @@ RewriterView *Model::rewriterView() const return d->rewriterView(); } +void Model::setRewriterView(RewriterView *rewriterView) +{ + d->setRewriterView(rewriterView); +} + +NodeInstanceView *Model::nodeInstanceView() const +{ + return d->nodeInstanceView(); +} + +void Model::setNodeInstanceView(NodeInstanceView *nodeInstanceView) +{ + d->setNodeInstanceView(nodeInstanceView); +} + /*! \brief Returns the model that is used for metainfo \return Return itself if not other metaInfoProxyModel does exist @@ -1755,16 +1771,6 @@ Model *Model::create(const QString &rootType) } #endif -Model *Model::masterModel() const -{ - return d->m_masterModel.data(); -} - -void Model::setMasterModel(Model *model) -{ - d->m_masterModel = model; -} - /*! \brief Returns the URL against which relative URLs within the model should be resolved. \return The base URL. @@ -1834,13 +1840,11 @@ void Model::attachView(AbstractView *view) // Internal::WriteLocker locker(d); RewriterView *rewriterView = qobject_cast<RewriterView*>(view); if (rewriterView) { - d->setRewriterView(rewriterView); return; } NodeInstanceView *nodeInstanceView = qobject_cast<NodeInstanceView*>(view); if (nodeInstanceView) { - d->setNodeInstanceView(nodeInstanceView); return; } @@ -1862,13 +1866,11 @@ void Model::detachView(AbstractView *view, ViewNotification emitDetachNotify) RewriterView *rewriterView = qobject_cast<RewriterView*>(view); if (rewriterView) { - d->setRewriterView(0); return; } NodeInstanceView *nodeInstanceView = qobject_cast<NodeInstanceView*>(view); if (nodeInstanceView) { - d->setNodeInstanceView(0); return; } diff --git a/src/plugins/qmldesigner/designercore/model/model_p.h b/src/plugins/qmldesigner/designercore/model/model_p.h index b1cfcdc0c8..70a321fb56 100644 --- a/src/plugins/qmldesigner/designercore/model/model_p.h +++ b/src/plugins/qmldesigner/designercore/model/model_p.h @@ -212,6 +212,8 @@ public: void setRewriterView(RewriterView *rewriterView); RewriterView *rewriterView() const; + + void setNodeInstanceView(NodeInstanceView *nodeInstanceView); NodeInstanceView *nodeInstanceView() const; @@ -229,7 +231,6 @@ private: //functions private: Model *m_q; MetaInfo m_metaInfo; - QList<Import> m_imports; QList<QWeakPointer<AbstractView> > m_viewList; QList<InternalNodePointer> m_selectedNodeList; @@ -237,17 +238,11 @@ private: QHash<qint32, InternalNodePointer> m_internalIdNodeHash; QSet<InternalNodePointer> m_nodeSet; InternalNodePointer m_acutalStateNode; - - InternalNodePointer m_rootInternalNode; - QUrl m_fileUrl; - - QWeakPointer<Model> m_masterModel; QWeakPointer<RewriterView> m_rewriterView; QWeakPointer<NodeInstanceView> m_nodeInstanceView; QWeakPointer<Model> m_metaInfoProxyModel; - bool m_writeLock; qint32 m_internalIdCounter; }; diff --git a/src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp b/src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp index 16a5ca6dfd..543fe5bbf8 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlmodelview.cpp @@ -229,7 +229,7 @@ QmlItemNode QmlModelView::createQmlItemNode(const ItemLibraryEntry &itemLibraryE QScopedPointer<RewriterView> rewriterView(new RewriterView(RewriterView::Amend, 0)); rewriterView->setCheckSemanticErrors(false); rewriterView->setTextModifier(&modifier); - inputModel->attachView(rewriterView.data()); + inputModel->setRewriterView(rewriterView.data()); if (rewriterView->errors().isEmpty() && rewriterView->rootModelNode().isValid()) { ModelNode rootModelNode = rewriterView->rootModelNode(); diff --git a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp index e726d1074f..47e9862408 100644 --- a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp +++ b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp @@ -472,6 +472,16 @@ QString RewriterView::textModifierContent() const return QString(); } +void RewriterView::reactivateTextMofifierChangeSignals() +{ + textModifier()->reactivateChangeSignals(); +} + +void RewriterView::deactivateTextMofifierChangeSignals() +{ + textModifier()->deactivateChangeSignals(); +} + void RewriterView::applyModificationGroupChanges() { Q_ASSERT(transactionLevel == 0); @@ -615,6 +625,31 @@ bool RewriterView::modificationGroupActive() return m_modificationGroupActive; } +static bool isInNodeDefinition(int nodeTextOffset, int nodeTextLength, int cursorPosition) +{ + return (nodeTextOffset <= cursorPosition) && (nodeTextOffset + nodeTextLength > cursorPosition); +} + +ModelNode RewriterView::nodeAtTextCursorPosition(int cursorPosition) const +{ + const QList<ModelNode> allNodes = allModelNodes(); + + ModelNode nearestNode; + int nearestNodeTextOffset = -1; + + foreach (const ModelNode ¤tNode, allNodes) { + const int nodeTextOffset = nodeOffset(currentNode); + const int nodeTextLength = nodeLength(currentNode); + if (isInNodeDefinition(nodeTextOffset, nodeTextLength, cursorPosition) + && (nodeTextOffset > nearestNodeTextOffset)) { + nearestNode = currentNode; + nearestNodeTextOffset = nodeTextOffset; + } + } + + return nearestNode; +} + bool RewriterView::renameId(const QString& oldId, const QString& newId) { if (textModifier()) @@ -698,6 +733,10 @@ QString RewriterView::pathForImport(const Import &import) return QString(); } +QWidget *RewriterView::widget() +{ + return 0; +} void RewriterView::qmlTextChanged() { diff --git a/src/plugins/qmldesigner/designercore/model/viewlogger.cpp b/src/plugins/qmldesigner/designercore/model/viewlogger.cpp index 53f9dcf683..0618142c78 100644 --- a/src/plugins/qmldesigner/designercore/model/viewlogger.cpp +++ b/src/plugins/qmldesigner/designercore/model/viewlogger.cpp @@ -285,5 +285,10 @@ void ViewLogger::actualStateChanged(const ModelNode &node) { m_output << time() << indent("actualStateChanged:") << node << endl; } + +QWidget *ViewLogger::widget() +{ + return 0; +} } // namespace Internal } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designercore/model/viewlogger.h b/src/plugins/qmldesigner/designercore/model/viewlogger.h index 64d5ec0d32..845b6ff421 100644 --- a/src/plugins/qmldesigner/designercore/model/viewlogger.h +++ b/src/plugins/qmldesigner/designercore/model/viewlogger.h @@ -42,7 +42,7 @@ class ViewLogger : public QmlDesigner::AbstractView { Q_OBJECT public: - ViewLogger(QObject *parent); + ViewLogger(QObject *parent = 0); void modelAttached(Model *model); void modelAboutToBeDetached(Model *model); @@ -87,6 +87,8 @@ public: void actualStateChanged(const ModelNode &node); + QWidget *widget(); + protected: QString time() const; diff --git a/src/plugins/qmldesigner/designercore/model/viewmanager.cpp b/src/plugins/qmldesigner/designercore/model/viewmanager.cpp new file mode 100644 index 0000000000..08c1a7824b --- /dev/null +++ b/src/plugins/qmldesigner/designercore/model/viewmanager.cpp @@ -0,0 +1,194 @@ +#include "viewmanager.h" + +#include "designdocument.h" +#include "componentaction.h" +#include "itemlibrarywidget.h" +#include "designmodewidget.h" +#include "formeditorwidget.h" +#include "toolbox.h" +#include "designeractionmanager.h" + +#include <qmldesigner/qmldesignerplugin.h> + +#include <utils/crumblepath.h> +#include <qtsupport/baseqtversion.h> +#include <qtsupport/qtversionmanager.h> +#include <qtsupport/qtsupportconstants.h> + +namespace QmlDesigner { + +ViewManager::ViewManager() +{ + //QObject::connect(&m_nodeInstanceView, SIGNAL(qmlPuppetCrashed()), designModeWidget, SLOT(qmlPuppetCrashed())); + //QObject::connect(m_formEditorView.crumblePath(), SIGNAL(elementClicked(QVariant)), designModeWidget, SLOT(onCrumblePathElementClicked(QVariant))); + m_formEditorView.formEditorWidget()->toolBox()->addLeftSideAction(m_componentView.action()); // ugly hack +} + +DesignDocument *ViewManager::currentDesignDocument() const +{ + return QmlDesignerPlugin::instance()->documentManager().currentDesignDocument(); +} + +QString ViewManager::pathToQt() const +{ + QtSupport::BaseQtVersion *activeQtVersion = QtSupport::QtVersionManager::instance()->version(currentDesignDocument()->qtVersionId()); + if (activeQtVersion && (activeQtVersion->qtVersion() >= QtSupport::QtVersionNumber(4, 7, 1)) + && (activeQtVersion->type() == QLatin1String(QtSupport::Constants::DESKTOPQT) + || activeQtVersion->type() == QLatin1String(QtSupport::Constants::SIMULATORQT))) + return activeQtVersion->qmakeProperty("QT_INSTALL_DATA"); + + return QString(); +} + +void ViewManager::attachNodeInstanceView() +{ + setNodeInstanceViewQtPath(pathToQt()); + currentModel()->setNodeInstanceView(&m_nodeInstanceView); +} + +void ViewManager::attachRewriterView(TextModifier *textModifier) +{ + if (currentDesignDocument()->rewriterView()) { + currentDesignDocument()->rewriterView()->setTextModifier(textModifier); + currentDesignDocument()->rewriterView()->reactivateTextMofifierChangeSignals(); + currentModel()->setRewriterView(currentDesignDocument()->rewriterView()); + } +} + +void ViewManager::detachRewriterView() +{ + if (currentDesignDocument()->rewriterView()) { + currentDesignDocument()->rewriterView()->deactivateTextMofifierChangeSignals(); + currentModel()->setRewriterView(0); + } +} + +void ViewManager::switchStateEditorViewToBaseState() +{ + if (m_statesEditorView.isAttached()) { + m_savedState = m_statesEditorView.currentState(); + m_statesEditorView.setCurrentState(m_statesEditorView.baseState()); + } +} + +void ViewManager::switchStateEditorViewToSavedState() +{ + if (m_savedState.isValid() && m_statesEditorView.isAttached()) + m_statesEditorView.setCurrentState(m_savedState); +} + +void ViewManager::resetPropertyEditorView() +{ + m_propertyEditorView.resetView(); +} + +void ViewManager::detachViewsExceptRewriterAndComponetView() +{ + switchStateEditorViewToBaseState(); + currentModel()->detachView(DesignerActionManager::view()); + currentModel()->detachView(&m_formEditorView); + currentModel()->detachView(&m_navigatorView); + currentModel()->detachView(&m_itemLibraryView); + currentModel()->detachView(&m_statesEditorView); + currentModel()->detachView(&m_propertyEditorView); + currentModel()->setNodeInstanceView(0); +} + +void ViewManager::attachItemLibraryView() +{ + setItemLibraryViewResourcePath(QFileInfo(currentDesignDocument()->fileName()).absolutePath()); + currentModel()->attachView(&m_itemLibraryView); +} + +void ViewManager::attachComponentView() +{ + documentModel()->attachView(&m_componentView); + QObject::connect(m_componentView.action(), SIGNAL(currentComponentChanged(ModelNode)), currentDesignDocument(), SLOT(changeCurrentModelTo(ModelNode))); +} + +void ViewManager::detachComponentView() +{ + QObject::disconnect(m_componentView.action(), SIGNAL(currentComponentChanged(ModelNode)), currentDesignDocument(), SLOT(changeCurrentModelTo(ModelNode))); + documentModel()->detachView(&m_componentView); +} + +void ViewManager::attachViewsExceptRewriterAndComponetView() +{ + attachNodeInstanceView(); + currentModel()->attachView(&m_formEditorView); + currentModel()->attachView(&m_navigatorView); + attachItemLibraryView(); + currentModel()->attachView(&m_statesEditorView); + currentModel()->attachView(&m_propertyEditorView); + currentModel()->attachView(DesignerActionManager::view()); + switchStateEditorViewToSavedState(); +} + +void ViewManager::setItemLibraryViewResourcePath(const QString &resourcePath) +{ + m_itemLibraryView.setResourcePath(resourcePath); +} + +void ViewManager::setComponentNode(const ModelNode &componentNode) +{ + qDebug() << __FUNCTION__ << componentNode; + m_componentView.setComponentNode(componentNode); +} + +void ViewManager::setNodeInstanceViewQtPath(const QString &qtPath) +{ + m_nodeInstanceView.setPathToQt(qtPath); +} + +QWidget *ViewManager::formEditorWidget() +{ + return m_formEditorView.widget(); +} + +QWidget *ViewManager::propertyEditorWidget() +{ + return m_propertyEditorView.widget(); +} + +QWidget *ViewManager::itemLibraryWidget() +{ + return m_itemLibraryView.widget(); +} + +QWidget *ViewManager::navigatorWidget() +{ + return m_navigatorView.widget(); +} + +QWidget *ViewManager::statesEditorWidget() +{ + return m_statesEditorView.widget(); +} + +void ViewManager::pushFileOnCrambleBar(const QString &fileName) +{ + m_formEditorView.formEditorWidget()->formEditorCrumbleBar()->pushFile(fileName); +} + +void ViewManager::pushInFileComponentOnCrambleBar(const QString &componentId) + +{ + m_formEditorView.formEditorWidget()->formEditorCrumbleBar()->pushInFileComponent(componentId); +} + +void ViewManager::nextFileIsCalledInternally() +{ + m_formEditorView.formEditorWidget()->formEditorCrumbleBar()->nextFileIsCalledInternally(); +} + +Model *ViewManager::currentModel() const +{ + return currentDesignDocument()->currentModel(); +} + +Model *ViewManager::documentModel() const +{ + return currentDesignDocument()->documentModel(); +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/designmodewidget.cpp b/src/plugins/qmldesigner/designmodewidget.cpp index 25eb26fe1f..48760de9cb 100644 --- a/src/plugins/qmldesigner/designmodewidget.cpp +++ b/src/plugins/qmldesigner/designmodewidget.cpp @@ -31,14 +31,13 @@ #include "qmldesignerconstants.h" #include "styledoutputpaneplaceholder.h" #include "designmodecontext.h" +#include "qmldesignerplugin.h" #include <model.h> #include <rewriterview.h> -#include <formeditorwidget.h> -#include <stateseditorwidget.h> -#include <itemlibrarywidget.h> #include <componentaction.h> #include <toolbox.h> +#include <itemlibrarywidget.h> #include <coreplugin/coreconstants.h> #include <coreplugin/designmode.h> @@ -93,8 +92,6 @@ const char SB_OPENDOCUMENTS[] = "OpenDocuments"; namespace QmlDesigner { namespace Internal { -DesignModeWidget *DesignModeWidget::s_instance = 0; - DocumentWarningWidget::DocumentWarningWidget(DesignModeWidget *parent) : Utils::FakeToolTip(parent), m_errorMessage(new QLabel(tr("Placeholder"), this)), @@ -137,13 +134,13 @@ void DocumentWarningWidget::setError(const RewriterView::Error &error) class ItemLibrarySideBarItem : public Core::SideBarItem { public: - explicit ItemLibrarySideBarItem(ItemLibraryWidget *widget, const QString &id); + explicit ItemLibrarySideBarItem(QWidget *widget, const QString &id); virtual ~ItemLibrarySideBarItem(); virtual QList<QToolButton *> createToolBarWidgets(); }; -ItemLibrarySideBarItem::ItemLibrarySideBarItem(ItemLibraryWidget *widget, const QString &id) : Core::SideBarItem(widget, id) {} +ItemLibrarySideBarItem::ItemLibrarySideBarItem(QWidget *widget, const QString &id) : Core::SideBarItem(widget, id) {} ItemLibrarySideBarItem::~ItemLibrarySideBarItem() { @@ -158,13 +155,13 @@ QList<QToolButton *> ItemLibrarySideBarItem::createToolBarWidgets() class NavigatorSideBarItem : public Core::SideBarItem { public: - explicit NavigatorSideBarItem(NavigatorWidget *widget, const QString &id); + explicit NavigatorSideBarItem(QWidget *widget, const QString &id); virtual ~NavigatorSideBarItem(); virtual QList<QToolButton *> createToolBarWidgets(); }; -NavigatorSideBarItem::NavigatorSideBarItem(NavigatorWidget *widget, const QString &id) : Core::SideBarItem(widget, id) {} +NavigatorSideBarItem::NavigatorSideBarItem(QWidget *widget, const QString &id) : Core::SideBarItem(widget, id) {} NavigatorSideBarItem::~NavigatorSideBarItem() { @@ -185,7 +182,6 @@ void DocumentWarningWidget::goToError() // ---------- DesignModeWidget DesignModeWidget::DesignModeWidget(QWidget *parent) : QWidget(parent), - m_syncWithTextEdit(false), m_mainSplitter(0), m_leftSideBar(0), m_rightSideBar(0), @@ -196,41 +192,10 @@ DesignModeWidget::DesignModeWidget(QWidget *parent) : m_navigatorHistoryCounter(-1), m_keepNavigatorHistory(false) { - s_instance = this; - m_undoAction = new QAction(tr("&Undo"), this); - connect(m_undoAction, SIGNAL(triggered()), this, SLOT(undo())); - m_redoAction = new QAction(tr("&Redo"), this); - connect(m_redoAction, SIGNAL(triggered()), this, SLOT(redo())); - m_deleteAction = new Utils::ParameterAction(tr("Delete"), tr("Delete \"%1\""), Utils::ParameterAction::EnabledWithParameter, this); - connect(m_deleteAction, SIGNAL(triggered()), this, SLOT(deleteSelected())); - m_cutAction = new Utils::ParameterAction(tr("Cu&t"), tr("Cut \"%1\""), Utils::ParameterAction::EnabledWithParameter, this); - connect(m_cutAction, SIGNAL(triggered()), this, SLOT(cutSelected())); - m_copyAction = new Utils::ParameterAction(tr("&Copy"), tr("Copy \"%1\""), Utils::ParameterAction::EnabledWithParameter, this); - connect(m_copyAction, SIGNAL(triggered()), this, SLOT(copySelected())); - m_pasteAction = new Utils::ParameterAction(tr("&Paste"), tr("Paste \"%1\""), Utils::ParameterAction::EnabledWithParameter, this); - connect(m_pasteAction, SIGNAL(triggered()), this, SLOT(paste())); - m_selectAllAction = new Utils::ParameterAction(tr("Select &All"), tr("Select All \"%1\""), Utils::ParameterAction::EnabledWithParameter, this); - connect(m_selectAllAction, SIGNAL(triggered()), this, SLOT(selectAll())); - m_hideSidebarsAction = new QAction(tr("Toggle Full Screen"), this); - connect(m_hideSidebarsAction, SIGNAL(triggered()), this, SLOT(toggleSidebars())); - m_restoreDefaultViewAction = new QAction(tr("&Restore Default View"), this); - m_goIntoComponentAction = new QAction(tr("&Go into Component"), this); - connect(m_restoreDefaultViewAction, SIGNAL(triggered()), SLOT(restoreDefaultView())); - connect(m_goIntoComponentAction, SIGNAL(triggered()), SLOT(goIntoComponent())); - m_toggleLeftSidebarAction = new QAction(tr("Toggle &Left Sidebar"), this); - connect(m_toggleLeftSidebarAction, SIGNAL(triggered()), SLOT(toggleLeftSidebar())); - m_toggleRightSidebarAction = new QAction(tr("Toggle &Right Sidebar"), this); - connect(m_toggleRightSidebarAction, SIGNAL(triggered()), SLOT(toggleRightSidebar())); - m_outputPlaceholderSplitter = new Core::MiniSplitter; m_outputPanePlaceholder = new StyledOutputpanePlaceHolder(Core::DesignMode::instance(), m_outputPlaceholderSplitter); } -DesignModeWidget::~DesignModeWidget() -{ - s_instance = 0; -} - void DesignModeWidget::restoreDefaultView() { QSettings *settings = Core::ICore::settings(); @@ -265,19 +230,17 @@ void DesignModeWidget::toggleSidebars() m_leftSideBar->setVisible(m_showSidebars); if (m_rightSideBar) m_rightSideBar->setVisible(m_showSidebars); - if (!m_statesEditorView.isNull()) - m_statesEditorView->widget()->setVisible(m_showSidebars); + + viewManager().statesEditorWidget()->setVisible(m_showSidebars); } void DesignModeWidget::showEditor(Core::IEditor *editor) { - if (m_textEditor && editor) - if (m_textEditor->document()->fileName() != editor->document()->fileName()) { - if (!m_keepNavigatorHistory) - addNavigatorHistoryEntry(editor->document()->fileName()); - setupNavigatorHistory(); - } + if (textEditor() + && editor + && textEditor()->document()->fileName() != editor->document()->fileName()) + setupNavigatorHistory(editor); // // Prevent recursive calls to function by explicitly managing initialization status @@ -291,132 +254,16 @@ void DesignModeWidget::showEditor(Core::IEditor *editor) setup(); } - QString fileName; - QPlainTextEdit *textEdit = 0; - TextEditor::ITextEditor *textEditor = 0; - - if (editor) { - fileName = editor->document()->fileName(); - textEdit = qobject_cast<QPlainTextEdit*>(editor->widget()); - textEditor = qobject_cast<TextEditor::ITextEditor*>(editor); - if (textEditor) - m_fakeToolBar->addEditor(textEditor); - } - - if (debug) - qDebug() << Q_FUNC_INFO << fileName; - - if (textEdit) - m_currentTextEdit = textEdit; - - if (textEditor) - m_textEditor = textEditor; - DesignDocumentController *document = 0; - if (textEdit && textEditor && fileName.endsWith(QLatin1String(".qml"))) { - if (m_documentHash.contains(textEdit)) { - document = m_documentHash.value(textEdit).data(); - } else { - DesignDocumentController *newDocument = new DesignDocumentController(this); + if (textEditor()) + m_fakeToolBar->addEditor(textEditor()); - newDocument->setNodeInstanceView(m_nodeInstanceView.data()); - newDocument->setPropertyEditorView(m_propertyEditorView.data()); - newDocument->setNavigator(m_navigatorView.data()); - newDocument->setStatesEditorView(m_statesEditorView.data()); - newDocument->setItemLibraryView(m_itemLibraryView.data()); - newDocument->setFormEditorView(m_formEditorView.data()); - newDocument->setComponentView(m_componentView.data()); - - newDocument->setFileName(fileName); - - document = newDocument; - - m_documentHash.insert(textEdit, document); - } - } - setCurrentDocument(document); + setCurrentDesignDocument(currentDesignDocument()); m_initStatus = Initialized; } -void DesignModeWidget::closeEditors(QList<Core::IEditor*> editors) -{ - foreach (Core::IEditor* editor, editors) { - if (QPlainTextEdit *textEdit = qobject_cast<QPlainTextEdit*>(editor->widget())) { - if (m_currentTextEdit.data() == textEdit) - setCurrentDocument(0); - if (m_documentHash.contains(textEdit)) { - if (debug) - qDebug() << Q_FUNC_INFO << editor->document()->fileName(); - DesignDocumentController *document = m_documentHash.take(textEdit).data(); - delete document; - } - } - } -} - -QAction *DesignModeWidget::undoAction() const -{ - return m_undoAction; -} - -QAction *DesignModeWidget::redoAction() const -{ - return m_redoAction; -} - -QAction *DesignModeWidget::deleteAction() const -{ - return m_deleteAction; -} - -QAction *DesignModeWidget::cutAction() const -{ - return m_cutAction; -} - -QAction *DesignModeWidget::copyAction() const -{ - return m_copyAction; -} - -QAction *DesignModeWidget::pasteAction() const -{ - return m_pasteAction; -} - -QAction *DesignModeWidget::selectAllAction() const -{ - return m_selectAllAction; -} - -QAction *DesignModeWidget::hideSidebarsAction() const -{ - return m_hideSidebarsAction; -} - -QAction *DesignModeWidget::toggleLeftSidebarAction() const -{ - return m_toggleLeftSidebarAction; -} - -QAction *DesignModeWidget::toggleRightSidebarAction() const -{ - return m_toggleRightSidebarAction; -} - - -QAction *DesignModeWidget::restoreDefaultViewAction() const -{ - return m_restoreDefaultViewAction; -} - -QAction *DesignModeWidget::goIntoComponentAction() const -{ - return m_goIntoComponentAction; -} - void DesignModeWidget::readSettings() { QSettings *settings = Core::ICore::settings(); @@ -443,98 +290,25 @@ void DesignModeWidget::saveSettings() settings->endGroup(); } -void DesignModeWidget::undo() -{ - if (m_currentDesignDocumentController) - m_currentDesignDocumentController->undo(); -} - -void DesignModeWidget::redo() -{ - if (m_currentDesignDocumentController) - m_currentDesignDocumentController->redo(); -} - -void DesignModeWidget::deleteSelected() -{ - if (m_currentDesignDocumentController) - m_currentDesignDocumentController->deleteSelected(); -} - -void DesignModeWidget::cutSelected() -{ - if (m_currentDesignDocumentController) - m_currentDesignDocumentController->cutSelected(); -} - -void DesignModeWidget::copySelected() -{ - if (m_currentDesignDocumentController) - m_currentDesignDocumentController->copySelected(); -} - -void DesignModeWidget::paste() -{ - if (m_currentDesignDocumentController) - m_currentDesignDocumentController->paste(); -} - -void DesignModeWidget::selectAll() -{ - if (m_currentDesignDocumentController) - m_currentDesignDocumentController->selectAll(); -} - -void DesignModeWidget::closeCurrentEditor() -{ -} - -void DesignModeWidget::undoAvailable(bool isAvailable) -{ - DesignDocumentController *documentController = qobject_cast<DesignDocumentController*>(sender()); - if (m_currentDesignDocumentController && - m_currentDesignDocumentController.data() == documentController) { - m_undoAction->setEnabled(isAvailable); - } -} - -void DesignModeWidget::redoAvailable(bool isAvailable) -{ - DesignDocumentController *documentController = qobject_cast<DesignDocumentController*>(sender()); - if (m_currentDesignDocumentController && - m_currentDesignDocumentController.data() == documentController) { - m_redoAction->setEnabled(isAvailable); - } -} - -void DesignModeWidget::goIntoComponent() -{ - if (m_currentDesignDocumentController) - m_currentDesignDocumentController->goIntoComponent(); -} - -void DesignModeWidget::enable() +void DesignModeWidget::enableWidgets() { if (debug) qDebug() << Q_FUNC_INFO; m_warningWidget->setVisible(false); - m_formEditorView->widget()->setEnabled(true); - m_statesEditorView->widget()->setEnabled(true); + viewManager().formEditorWidget()->setEnabled(true); + viewManager().statesEditorWidget()->setEnabled(true); m_leftSideBar->setEnabled(true); m_rightSideBar->setEnabled(true); m_isDisabled = false; } -void DesignModeWidget::disable(const QList<RewriterView::Error> &errors) +void DesignModeWidget::disableWidgets() { if (debug) qDebug() << Q_FUNC_INFO; - Q_ASSERT(!errors.isEmpty()); - m_warningWidget->setError(errors.first()); - m_warningWidget->setVisible(true); - m_warningWidget->move(width() / 2, height() / 2); - m_formEditorView->widget()->setEnabled(false); - m_statesEditorView->widget()->setEnabled(false); + + viewManager().formEditorWidget()->setEnabled(false); + viewManager().statesEditorWidget()->setEnabled(false); m_leftSideBar->setEnabled(false); m_rightSideBar->setEnabled(false); m_isDisabled = true; @@ -545,112 +319,27 @@ void DesignModeWidget::updateErrorStatus(const QList<RewriterView::Error> &error if (debug) qDebug() << Q_FUNC_INFO << errors.count(); - if (m_isDisabled && errors.isEmpty()) - enable(); - else if (!errors.isEmpty()) - disable(errors); + if (m_isDisabled && errors.isEmpty()) { + enableWidgets(); + } else if (!errors.isEmpty()) { + disableWidgets(); + showErrorMessage(errors); + } } -void DesignModeWidget::setAutoSynchronization(bool sync) +TextEditor::ITextEditor *DesignModeWidget::textEditor() const { - if (debug) - qDebug() << Q_FUNC_INFO << sync; - - RewriterView *rewriter = m_currentDesignDocumentController->rewriterView(); - - m_currentDesignDocumentController->blockModelSync(!sync); - - if (sync) { - if (rewriter && m_currentDesignDocumentController->model()) - rewriter->setSelectedModelNodes(QList<ModelNode>()); - // text editor -> visual editor - if (!m_currentDesignDocumentController->model()) { - m_currentDesignDocumentController->loadMaster(m_currentTextEdit.data()); - } else { - m_currentDesignDocumentController->loadCurrentModel(); - m_componentView->resetView(); - } - - QList<RewriterView::Error> errors = m_currentDesignDocumentController->qmlErrors(); - if (errors.isEmpty()) { - // set selection to text cursor - const int cursorPos = m_currentTextEdit->textCursor().position(); - ModelNode node = nodeForPosition(cursorPos); - if (rewriter && node.isValid()) - rewriter->setSelectedModelNodes(QList<ModelNode>() << node); - enable(); - } else { - disable(errors); - } - - connect(m_currentDesignDocumentController.data(), SIGNAL(qmlErrorsChanged(QList<RewriterView::Error>)), - this, SLOT(updateErrorStatus(QList<RewriterView::Error>))); - - } else { - if (m_currentDesignDocumentController->model() && m_currentDesignDocumentController->qmlErrors().isEmpty()) { - RewriterView *rewriter = m_currentDesignDocumentController->rewriterView(); - // visual editor -> text editor - ModelNode selectedNode; - if (!rewriter->selectedModelNodes().isEmpty()) - selectedNode = rewriter->selectedModelNodes().first(); - - if (selectedNode.isValid()) { - const int nodeOffset = rewriter->nodeOffset(selectedNode); - if (nodeOffset > 0) { - const ModelNode currentSelectedNode - = nodeForPosition(m_currentTextEdit->textCursor().position()); - if (currentSelectedNode != selectedNode) { - int line, column; - m_textEditor->convertPosition(nodeOffset, &line, &column); - m_textEditor->gotoLine(line, column); - } - } - } - } - - disconnect(m_currentDesignDocumentController.data(), SIGNAL(qmlErrorsChanged(QList<RewriterView::Error>)), - this, SLOT(updateErrorStatus(QList<RewriterView::Error>))); - } + return currentDesignDocument()->textEditor(); } -void DesignModeWidget::setCurrentDocument(DesignDocumentController *newDesignDocumentController) +void DesignModeWidget::setCurrentDesignDocument(DesignDocument *newDesignDocument) { if (debug) - qDebug() << Q_FUNC_INFO << newDesignDocumentController; + qDebug() << Q_FUNC_INFO << newDesignDocument; - if (m_currentDesignDocumentController.data() == newDesignDocumentController) - return; - if (m_currentDesignDocumentController) { - setAutoSynchronization(false); - saveSettings(); - } + //viewManager().setDesignDocument(newDesignDocument); - if (currentDesignDocumentController()) { - disconnect(currentDesignDocumentController(), SIGNAL(undoAvailable(bool)), - this, SLOT(undoAvailable(bool))); - disconnect(currentDesignDocumentController(), SIGNAL(redoAvailable(bool)), - this, SLOT(redoAvailable(bool))); - } - - m_currentDesignDocumentController = newDesignDocumentController; - - if (currentDesignDocumentController()) { - connect(currentDesignDocumentController(), SIGNAL(undoAvailable(bool)), - this, SLOT(undoAvailable(bool))); - connect(currentDesignDocumentController(), SIGNAL(redoAvailable(bool)), - this, SLOT(redoAvailable(bool))); - } - - if (m_currentDesignDocumentController) { - setAutoSynchronization(true); - m_undoAction->setEnabled(m_currentDesignDocumentController->isUndoAvailable()); - m_redoAction->setEnabled(m_currentDesignDocumentController->isRedoAvailable()); - } else { - //detach all views - m_undoAction->setEnabled(false); - m_redoAction->setEnabled(false); - } } void DesignModeWidget::setup() @@ -687,20 +376,6 @@ void DesignModeWidget::setup() } } - m_nodeInstanceView = new NodeInstanceView(this); - connect(m_nodeInstanceView.data(), SIGNAL(qmlPuppetCrashed()), this, SLOT(qmlPuppetCrashed())); - // Sidebar takes ownership - m_navigatorView = new NavigatorView; - m_propertyEditorView = new PropertyEditor(this); - m_itemLibraryView = new ItemLibraryView(this); - - m_statesEditorView = new StatesEditorView(this); - - m_formEditorView = new FormEditorView(this); - connect(m_formEditorView->crumblePath(), SIGNAL(elementClicked(QVariant)), this, SLOT(onCrumblePathElementClicked(QVariant))); - - m_componentView = new ComponentView(this); - m_formEditorView->widget()->toolBox()->addLeftSideAction(m_componentView->action()); m_fakeToolBar = Core::EditorManager::createToolBar(this); m_mainSplitter = new MiniSplitter(this); @@ -710,9 +385,9 @@ void DesignModeWidget::setup() m_warningWidget = new DocumentWarningWidget(this); m_warningWidget->setVisible(false); - Core::SideBarItem *navigatorItem = new NavigatorSideBarItem(m_navigatorView->widget(), QLatin1String(SB_NAVIGATOR)); - Core::SideBarItem *libraryItem = new ItemLibrarySideBarItem(m_itemLibraryView->widget(), QLatin1String(SB_LIBRARY)); - Core::SideBarItem *propertiesItem = new Core::SideBarItem(m_propertyEditorView->widget(), QLatin1String(SB_PROPERTIES)); + Core::SideBarItem *navigatorItem = new NavigatorSideBarItem(viewManager().navigatorWidget(), QLatin1String(SB_NAVIGATOR)); + Core::SideBarItem *libraryItem = new ItemLibrarySideBarItem(viewManager().itemLibraryWidget(), QLatin1String(SB_LIBRARY)); + Core::SideBarItem *propertiesItem = new Core::SideBarItem(viewManager().propertyEditorWidget(), QLatin1String(SB_PROPERTIES)); // default items m_sideBarItems << navigatorItem << libraryItem << propertiesItem; @@ -748,7 +423,9 @@ void DesignModeWidget::setup() connect(m_fakeToolBar, SIGNAL(closeClicked()), this, SLOT(closeCurrentEditor())); connect(m_fakeToolBar, SIGNAL(goForwardClicked()), this, SLOT(onGoForwardClicked())); connect(m_fakeToolBar, SIGNAL(goBackClicked()), this, SLOT(onGoBackClicked())); - setupNavigatorHistory(); + + if (currentDesignDocument()) + setupNavigatorHistory(currentDesignDocument()->textEditor()); // right area: QWidget *centerWidget = new QWidget; @@ -758,16 +435,16 @@ void DesignModeWidget::setup() rightLayout->setSpacing(0); rightLayout->addWidget(m_fakeToolBar); //### we now own these here - rightLayout->addWidget(m_statesEditorView->widget()); + rightLayout->addWidget(viewManager().statesEditorWidget()); - FormEditorContext *formEditorContext = new FormEditorContext(m_formEditorView->widget()); + FormEditorContext *formEditorContext = new FormEditorContext(viewManager().formEditorWidget()); Core::ICore::addContextObject(formEditorContext); - NavigatorContext *navigatorContext = new NavigatorContext(m_navigatorView->widget()); + NavigatorContext *navigatorContext = new NavigatorContext(viewManager().navigatorWidget()); Core::ICore::addContextObject(navigatorContext); // editor and output panes - m_outputPlaceholderSplitter->addWidget(m_formEditorView->widget()); + m_outputPlaceholderSplitter->addWidget(viewManager().formEditorWidget()); m_outputPlaceholderSplitter->addWidget(m_outputPanePlaceholder); m_outputPlaceholderSplitter->setStretchFactor(0, 10); m_outputPlaceholderSplitter->setStretchFactor(1, 0); @@ -791,7 +468,7 @@ void DesignModeWidget::setup() mainLayout->addWidget(m_mainSplitter); m_warningWidget->setVisible(false); - m_statesEditorView->widget()->setEnabled(true); + viewManager().statesEditorWidget()->setEnabled(true); m_leftSideBar->setEnabled(true); m_rightSideBar->setEnabled(true); m_leftSideBar->setCloseWhenEmpty(true); @@ -800,7 +477,6 @@ void DesignModeWidget::setup() readSettings(); show(); - QApplication::processEvents(); } void DesignModeWidget::updateAvailableSidebarItemsRight() @@ -827,8 +503,10 @@ void DesignModeWidget::qmlPuppetCrashed() { QList<RewriterView::Error> errorList; RewriterView::Error error(tr("Qt Quick emulation layer crashed")); - errorList << error; - disable(errorList); + errorList.append(error); + + disableWidgets(); + showErrorMessage(errorList); } void DesignModeWidget::onGoBackClicked() @@ -851,17 +529,16 @@ void DesignModeWidget::onGoForwardClicked() } } -void DesignModeWidget::onCrumblePathElementClicked(const QVariant &data) +DesignDocument *DesignModeWidget::currentDesignDocument() const { - currentDesignDocumentController()->setCrumbleBarInfo(data.value<CrumbleBarInfo>()); + return QmlDesignerPlugin::instance()->documentManager().currentDesignDocument(); } -DesignModeWidget *DesignModeWidget::instance() +ViewManager &DesignModeWidget::viewManager() { - return s_instance; + return QmlDesignerPlugin::instance()->viewManager(); } - void DesignModeWidget::resizeEvent(QResizeEvent *event) { if (m_warningWidget) @@ -869,35 +546,11 @@ void DesignModeWidget::resizeEvent(QResizeEvent *event) QWidget::resizeEvent(event); } - -bool DesignModeWidget::isInNodeDefinition(int nodeOffset, int nodeLength, int cursorPos) const { - return (nodeOffset <= cursorPos) && (nodeOffset + nodeLength > cursorPos); -} - - -ModelNode DesignModeWidget::nodeForPosition(int cursorPos) const +void DesignModeWidget::setupNavigatorHistory(Core::IEditor *editor) { - RewriterView *rewriter = m_currentDesignDocumentController->rewriterView(); - QList<ModelNode> nodes = rewriter->allModelNodes(); - - ModelNode bestNode; - int bestNodeOffset = -1; - - foreach (const ModelNode &node, nodes) { - const int nodeOffset = rewriter->nodeOffset(node); - const int nodeLength = rewriter->nodeLength(node); - if (isInNodeDefinition(nodeOffset, nodeLength, cursorPos) - && (nodeOffset > bestNodeOffset)) { - bestNode = node; - bestNodeOffset = nodeOffset; - } - } - - return bestNode; -} + if (!m_keepNavigatorHistory) + addNavigatorHistoryEntry(editor->document()->fileName()); -void DesignModeWidget::setupNavigatorHistory() -{ const bool canGoBack = m_navigatorHistoryCounter > 0; const bool canGoForward = m_navigatorHistoryCounter < (m_navigatorHistory.size() - 1); m_fakeToolBar->setCanGoBack(canGoBack); @@ -914,13 +567,30 @@ void DesignModeWidget::addNavigatorHistoryEntry(const QString &fileName) ++m_navigatorHistoryCounter; } +void DesignModeWidget::showErrorMessage(const QList<RewriterView::Error> &errors) +{ + Q_ASSERT(!errors.isEmpty()); + m_warningWidget->setError(errors.first()); + m_warningWidget->setVisible(true); + m_warningWidget->move(width() / 2, height() / 2); +} QString DesignModeWidget::contextHelpId() const { - if (m_currentDesignDocumentController) - return m_currentDesignDocumentController->contextHelpId(); + if (currentDesignDocument()) + return currentDesignDocument()->contextHelpId(); return QString(); } +void DesignModeWidget::initialize() +{ + if (m_initStatus == NotInitialized) { + m_initStatus = Initializing; + setup(); + } + + m_initStatus = Initialized; +} + } // namespace Internal } // namespace Designer diff --git a/src/plugins/qmldesigner/designmodewidget.h b/src/plugins/qmldesigner/designmodewidget.h index 14c746198a..c4d59da3f7 100644 --- a/src/plugins/qmldesigner/designmodewidget.h +++ b/src/plugins/qmldesigner/designmodewidget.h @@ -35,7 +35,7 @@ #include <utils/faketooltip.h> #include <texteditor/itexteditor.h> -#include <designdocumentcontroller.h> +#include <designdocument.h> #include <itemlibraryview.h> #include <navigatorwidget.h> #include <navigatorview.h> @@ -103,54 +103,34 @@ class DesignModeWidget : public QWidget public: explicit DesignModeWidget(QWidget *parent = 0); - ~DesignModeWidget(); void showEditor(Core::IEditor *editor); void closeEditors(const QList<Core::IEditor*> editors); QString contextHelpId() const; - QAction *undoAction() const; - QAction *redoAction() const; - QAction *deleteAction() const; - QAction *cutAction() const; - QAction *copyAction() const; - QAction *pasteAction() const; - QAction *selectAllAction() const; - QAction *hideSidebarsAction() const; - QAction *toggleLeftSidebarAction() const; - QAction *toggleRightSidebarAction() const; - QAction *restoreDefaultViewAction() const; - QAction *goIntoComponentAction() const; + void initialize(); + void readSettings(); void saveSettings(); - void setAutoSynchronization(bool sync); - TextEditor::ITextEditor *textEditor() const {return m_textEditor.data(); } + TextEditor::ITextEditor *textEditor() const; - static DesignModeWidget *instance(); - DesignDocumentController *currentDesignDocumentController() const {return m_currentDesignDocumentController.data(); } + DesignDocument *currentDesignDocument() const; + ViewManager &viewManager(); -private slots: - void undo(); - void redo(); - void deleteSelected(); - void cutSelected(); - void copySelected(); - void paste(); - void selectAll(); - void closeCurrentEditor(); + void enableWidgets(); + void disableWidgets(); + void showErrorMessage(const QList<RewriterView::Error> &errors); + +public slots: + void updateErrorStatus(const QList<RewriterView::Error> &errors); + void restoreDefaultView(); void toggleSidebars(); void toggleLeftSidebar(); void toggleRightSidebar(); - void restoreDefaultView(); - void undoAvailable(bool isAvailable); - void redoAvailable(bool isAvailable); - void goIntoComponent(); - void enable(); - void disable(const QList<RewriterView::Error> &errors); - void updateErrorStatus(const QList<RewriterView::Error> &errors); +private slots: void updateAvailableSidebarItemsLeft(); void updateAvailableSidebarItemsRight(); @@ -160,49 +140,20 @@ private slots: void onGoBackClicked(); void onGoForwardClicked(); - void onCrumblePathElementClicked(const QVariant &data); - protected: void resizeEvent(QResizeEvent *event); -private: - void setCurrentDocument(DesignDocumentController *newDesignDocumentController); - //QStackedWidget *m_documentWidgetStack; - QHash<QPlainTextEdit*,QWeakPointer<DesignDocumentController> > m_documentHash; - QWeakPointer<DesignDocumentController> m_currentDesignDocumentController; - QWeakPointer<QPlainTextEdit> m_currentTextEdit; - - QAction *m_undoAction; - QAction *m_redoAction; - QAction *m_deleteAction; - QAction *m_cutAction; - QAction *m_copyAction; - QAction *m_pasteAction; - QAction *m_selectAllAction; - QAction *m_hideSidebarsAction; - QAction *m_restoreDefaultViewAction; - QAction *m_toggleLeftSidebarAction; - QAction *m_toggleRightSidebarAction; - QAction *m_goIntoComponentAction; - - QWeakPointer<ItemLibraryView> m_itemLibraryView; - QWeakPointer<NavigatorView> m_navigatorView; - QWeakPointer<PropertyEditor> m_propertyEditorView; - QWeakPointer<StatesEditorView> m_statesEditorView; - QWeakPointer<FormEditorView> m_formEditorView; - QWeakPointer<ComponentView> m_componentView; - QWeakPointer<NodeInstanceView> m_nodeInstanceView; - - bool m_syncWithTextEdit; +private: // functions + enum InitializeStatus { NotInitialized, Initializing, Initialized }; + void setCurrentDesignDocument(DesignDocument *newDesignDocument); void setup(); bool isInNodeDefinition(int nodeOffset, int nodeLength, int cursorPos) const; QmlDesigner::ModelNode nodeForPosition(int cursorPos) const; - void setupNavigatorHistory(); + void setupNavigatorHistory(Core::IEditor *editor); void addNavigatorHistoryEntry(const QString &fileName); - QWeakPointer<TextEditor::ITextEditor> m_textEditor; - +private: // variables QSplitter *m_mainSplitter; Core::SideBar *m_leftSideBar; Core::SideBar *m_rightSideBar; @@ -213,15 +164,12 @@ private: bool m_isDisabled; bool m_showSidebars; - enum InitializeStatus { NotInitialized, Initializing, Initialized }; InitializeStatus m_initStatus; DocumentWarningWidget *m_warningWidget; QStringList m_navigatorHistory; int m_navigatorHistoryCounter; bool m_keepNavigatorHistory; - - static DesignModeWidget *s_instance; }; } // namespace Internal diff --git a/src/plugins/qmldesigner/documentmanager.cpp b/src/plugins/qmldesigner/documentmanager.cpp new file mode 100644 index 0000000000..4a7af81f42 --- /dev/null +++ b/src/plugins/qmldesigner/documentmanager.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "documentmanager.h" + +#include <coreplugin/designmode.h> +#include <coreplugin/modemanager.h> +#include <qmljseditor/qmljseditorconstants.h> + +namespace QmlDesigner { + +DocumentManager::DocumentManager() + : QObject() +{ +} + +DocumentManager::~DocumentManager() +{ + foreach (const QWeakPointer<DesignDocument> &designDocument, m_designDocumentHash) + delete designDocument.data(); +} + +void DocumentManager::setCurrentDesignDocument(Core::IEditor *editor) +{ + if (editor) { + m_currentDesignDocument = m_designDocumentHash.value(editor); + if (m_currentDesignDocument == 0) { + m_currentDesignDocument = new DesignDocument; + m_designDocumentHash.insert(editor, m_currentDesignDocument); + m_currentDesignDocument->setEditor(editor); + } + } else { + m_currentDesignDocument->resetToDocumentModel(); + m_currentDesignDocument.clear(); + } +} + +DesignDocument *DocumentManager::currentDesignDocument() const +{ + return m_currentDesignDocument.data(); +} + +bool DocumentManager::hasCurrentDesignDocument() const +{ + return m_currentDesignDocument.data(); +} + +void DocumentManager::removeEditors(QList<Core::IEditor *> editors) +{ + foreach (Core::IEditor *editor, editors) + delete m_designDocumentHash.take(editor).data(); +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/documentmanager.h b/src/plugins/qmldesigner/documentmanager.h new file mode 100644 index 0000000000..43a6f67584 --- /dev/null +++ b/src/plugins/qmldesigner/documentmanager.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + + +#ifndef QMLDESIGNER_DOCUMENTMANAGER_H +#define QMLDESIGNER_DOCUMENTMANAGER_H + +#include <QObject> +#include <QList> + +#include <designdocument.h> + +namespace Core { +class IEditor; +} + +namespace QmlDesigner { + +class DocumentManager : public QObject +{ + Q_OBJECT +public: + DocumentManager(); + ~DocumentManager(); + + void setCurrentDesignDocument(Core::IEditor*editor); + DesignDocument *currentDesignDocument() const; + bool hasCurrentDesignDocument() const; + + void removeEditors(QList<Core::IEditor*> editors); + +private: + QHash<Core::IEditor *,QWeakPointer<DesignDocument> > m_designDocumentHash; + QWeakPointer<DesignDocument> m_currentDesignDocument; +}; + +} // namespace QmlDesigner + +#endif // QMLDESIGNER_DOCUMENTMANAGER_H diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp index 0d6d6463da..fcd556b4cf 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.cpp +++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp @@ -52,6 +52,8 @@ #include <coreplugin/mimedatabase.h> #include <coreplugin/modemanager.h> +#include <projectexplorer/projectexplorerconstants.h> + #include <extensionsystem/pluginmanager.h> #include <utils/hostosinfo.h> @@ -66,9 +68,18 @@ #include <QProcessEnvironment> namespace QmlDesigner { -namespace Internal { -BauhausPlugin *BauhausPlugin::m_pluginInstance = 0; +QmlDesignerPlugin *QmlDesignerPlugin::m_instance = 0; + +static bool isQmlFile(Core::IEditor *editor) +{ + return editor && editor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID; +} + +static bool isInDesignerMode() +{ + return Core::ModeManager::currentMode() == Core::DesignMode::instance(); +} bool shouldAssertInException() { @@ -76,15 +87,8 @@ bool shouldAssertInException() return !processEnvironment.value("QMLDESIGNER_ASSERT_ON_EXCEPTION").isEmpty(); } -BauhausPlugin::BauhausPlugin() : - m_designMode(0), - m_isActive(false), - m_revertToSavedAction(new QAction(this)), - m_saveAction(new QAction(this)), - m_saveAsAction(new QAction(this)), - m_closeCurrentEditorAction(new QAction(this)), - m_closeAllEditorsAction(new QAction(this)), - m_closeOtherEditorsAction(new QAction(this)) +QmlDesignerPlugin::QmlDesignerPlugin() : + m_isActive(false) { // Exceptions should never ever assert: they are handled in a number of @@ -101,9 +105,11 @@ BauhausPlugin::BauhausPlugin() : Exception::setShouldAssert(shouldAssertInException()); } -BauhausPlugin::~BauhausPlugin() +QmlDesignerPlugin::~QmlDesignerPlugin() { Core::ICore::removeContextObject(m_context); + m_context = 0; + m_instance = 0; } //////////////////////////////////////////////////// @@ -111,7 +117,7 @@ BauhausPlugin::~BauhausPlugin() // INHERITED FROM ExtensionSystem::Plugin // //////////////////////////////////////////////////// -bool BauhausPlugin::initialize(const QStringList & /*arguments*/, QString *errorMessage/* = 0*/) // =0; +bool QmlDesignerPlugin::initialize(const QStringList & /*arguments*/, QString *errorMessage/* = 0*/) // =0; { const Core::Context switchContext(QmlDesigner::Constants::C_QMLDESIGNER, QmlJSEditor::Constants::C_QMLJSEDITOR_ID); @@ -121,7 +127,7 @@ bool BauhausPlugin::initialize(const QStringList & /*arguments*/, QString *error switchAction, QmlDesigner::Constants::SWITCH_TEXT_DESIGN, switchContext); command->setDefaultKeySequence(QKeySequence(Qt::Key_F4)); - m_pluginInstance = this; + m_instance = this; const QString pluginPath = Utils::HostOsInfo::isMacHost() ? QString(QCoreApplication::applicationDirPath() + "/../PlugIns/QmlDesigner") @@ -132,7 +138,7 @@ bool BauhausPlugin::initialize(const QStringList & /*arguments*/, QString *error createDesignModeWidget(); connect(switchAction, SIGNAL(triggered()), this, SLOT(switchTextDesign())); - addAutoReleasedObject(new SettingsPage); + addAutoReleasedObject(new Internal::SettingsPage); m_settings.fromSettings(Core::ICore::settings()); @@ -142,240 +148,295 @@ bool BauhausPlugin::initialize(const QStringList & /*arguments*/, QString *error return true; } -void BauhausPlugin::createDesignModeWidget() +void QmlDesignerPlugin::createDesignModeWidget() { - m_editorManager = Core::ICore::editorManager(); - Core::ActionContainer *editMenu = Core::ActionManager::actionContainer(Core::Constants::M_EDIT); - - m_mainWidget = new DesignModeWidget; + m_mainWidget = new Internal::DesignModeWidget; - m_context = new DesignModeContext(m_mainWidget); + m_context = new Internal::DesignModeContext(m_mainWidget); Core::ICore::addContextObject(m_context); Core::Context qmlDesignerMainContext(Constants::C_QMLDESIGNER); Core::Context qmlDesignerFormEditorContext(Constants::C_QMLFORMEDITOR); Core::Context qmlDesignerNavigatorContext(Constants::C_QMLNAVIGATOR); - // Revert to saved - Core::ActionManager::registerAction(m_revertToSavedAction, - Core::Constants::REVERTTOSAVED, qmlDesignerMainContext); - connect(m_revertToSavedAction, SIGNAL(triggered()), m_editorManager, SLOT(revertToSaved())); - - //Save - Core::ActionManager::registerAction(m_saveAction, Core::Constants::SAVE, qmlDesignerMainContext); - connect(m_saveAction, SIGNAL(triggered()), m_editorManager, SLOT(saveDocument())); - - //Save As - Core::ActionManager::registerAction(m_saveAsAction, Core::Constants::SAVEAS, qmlDesignerMainContext); - connect(m_saveAsAction, SIGNAL(triggered()), m_editorManager, SLOT(saveDocumentAs())); - - //Close Editor - Core::ActionManager::registerAction(m_closeCurrentEditorAction, Core::Constants::CLOSE, qmlDesignerMainContext); - connect(m_closeCurrentEditorAction, SIGNAL(triggered()), m_editorManager, SLOT(closeEditor())); - - //Close All - Core::ActionManager::registerAction(m_closeAllEditorsAction, Core::Constants::CLOSEALL, qmlDesignerMainContext); - connect(m_closeAllEditorsAction, SIGNAL(triggered()), m_editorManager, SLOT(closeAllEditors())); - - //Close All Others Action - Core::ActionManager::registerAction(m_closeOtherEditorsAction, Core::Constants::CLOSEOTHERS, qmlDesignerMainContext); - connect(m_closeOtherEditorsAction, SIGNAL(triggered()), m_editorManager, SLOT(closeOtherEditors())); - - // Undo / Redo - Core::ActionManager::registerAction(m_mainWidget->undoAction(), Core::Constants::UNDO, qmlDesignerMainContext); - Core::ActionManager::registerAction(m_mainWidget->redoAction(), Core::Constants::REDO, qmlDesignerMainContext); - - Core::Command *command; - - //GoIntoComponent - command = Core::ActionManager::registerAction(m_mainWidget->goIntoComponentAction(), - Constants::GO_INTO_COMPONENT, qmlDesignerMainContext); - command->setDefaultKeySequence(QKeySequence(Qt::Key_F2)); - - //Edit Menu - - command = Core::ActionManager::registerAction(m_mainWidget->deleteAction(), - QmlDesigner::Constants::DELETE, qmlDesignerFormEditorContext); - command = Core::ActionManager::registerAction(m_mainWidget->deleteAction(), - QmlDesigner::Constants::DELETE, qmlDesignerNavigatorContext); - command->setDefaultKeySequence(QKeySequence::Delete); - command->setAttribute(Core::Command::CA_Hide); // don't show delete in other modes - editMenu->addAction(command, Core::Constants::G_EDIT_COPYPASTE); - - command = Core::ActionManager::registerAction(m_mainWidget->cutAction(), - Core::Constants::CUT, qmlDesignerFormEditorContext); - command = Core::ActionManager::registerAction(m_mainWidget->cutAction(), - Core::Constants::CUT, qmlDesignerNavigatorContext); - command->setDefaultKeySequence(QKeySequence::Cut); - editMenu->addAction(command, Core::Constants::G_EDIT_COPYPASTE); - - command = Core::ActionManager::registerAction(m_mainWidget->copyAction(), - Core::Constants::COPY, qmlDesignerFormEditorContext); - command = Core::ActionManager::registerAction(m_mainWidget->copyAction(), - Core::Constants::COPY, qmlDesignerNavigatorContext); - command->setDefaultKeySequence(QKeySequence::Copy); - editMenu->addAction(command, Core::Constants::G_EDIT_COPYPASTE); - - command = Core::ActionManager::registerAction(m_mainWidget->pasteAction(), - Core::Constants::PASTE, qmlDesignerFormEditorContext); - command = Core::ActionManager::registerAction(m_mainWidget->pasteAction(), - Core::Constants::PASTE, qmlDesignerNavigatorContext); - command->setDefaultKeySequence(QKeySequence::Paste); - editMenu->addAction(command, Core::Constants::G_EDIT_COPYPASTE); - - command = Core::ActionManager::registerAction(m_mainWidget->selectAllAction(), - Core::Constants::SELECTALL, qmlDesignerFormEditorContext); - command = Core::ActionManager::registerAction(m_mainWidget->selectAllAction(), - Core::Constants::SELECTALL, qmlDesignerNavigatorContext); - - command->setDefaultKeySequence(QKeySequence::SelectAll); - editMenu->addAction(command, Core::Constants::G_EDIT_SELECTALL); - - Core::ActionContainer *viewsMenu = Core::ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS); - - command = Core::ActionManager::registerAction(m_mainWidget->toggleLeftSidebarAction(), - Constants::TOGGLE_LEFT_SIDEBAR, qmlDesignerMainContext); - command->setAttribute(Core::Command::CA_Hide); - command->setDefaultKeySequence(QKeySequence("Ctrl+Alt+0")); - viewsMenu->addAction(command); - - command = Core::ActionManager::registerAction(m_mainWidget->toggleRightSidebarAction(), - Constants::TOGGLE_RIGHT_SIDEBAR, qmlDesignerMainContext); - command->setAttribute(Core::Command::CA_Hide); - command->setDefaultKeySequence(QKeySequence("Ctrl+Alt+Shift+0")); - viewsMenu->addAction(command); - - command = Core::ActionManager::registerAction(m_mainWidget->restoreDefaultViewAction(), - Constants::RESTORE_DEFAULT_VIEW, qmlDesignerMainContext); - command->setAttribute(Core::Command::CA_Hide); - viewsMenu->addAction(command); - - command = Core::ActionManager::registerAction(m_mainWidget->hideSidebarsAction(), - Core::Constants::TOGGLE_SIDEBAR, qmlDesignerMainContext); - - if (Utils::HostOsInfo::isMacHost()) { - // add second shortcut to trigger delete - QAction *deleteAction = new QAction(m_mainWidget); - deleteAction->setShortcut(QKeySequence(QLatin1String("Backspace"))); - connect(deleteAction, SIGNAL(triggered()), m_mainWidget->deleteAction(), - SIGNAL(triggered())); - m_mainWidget->addAction(deleteAction); - } + m_context->context().add(qmlDesignerMainContext); + m_context->context().add(qmlDesignerFormEditorContext); + m_context->context().add(qmlDesignerNavigatorContext); + m_context->context().add(ProjectExplorer::Constants::LANG_QMLJS); + + m_shortCutManager.registerActions(); + + connect(Core::ICore::editorManager(), + SIGNAL(currentEditorChanged(Core::IEditor*)), + this, + SLOT(onCurrentEditorChanged(Core::IEditor*))); - connect(m_editorManager, SIGNAL(currentEditorChanged(Core::IEditor*)), - this, SLOT(updateEditor(Core::IEditor*))); + connect(Core::ICore::editorManager(), + SIGNAL(editorsClosed(QList<Core::IEditor*>)), + this, + SLOT(onTextEditorsClosed(QList<Core::IEditor*>))); - connect(m_editorManager, SIGNAL(editorsClosed(QList<Core::IEditor*>)), - this, SLOT(textEditorsClosed(QList<Core::IEditor*>))); +// connect(Core::ICore::editorManager(), SIGNAL(currentEditorChanged(Core::IEditor*)), +// &m_documentManager, SLOT(currentTextEditorChanged(Core::IEditor*))); - connect(Core::ICore::instance(), SIGNAL(contextChanged(Core::IContext*,Core::Context)), - this, SLOT(contextChanged(Core::IContext*,Core::Context))); +// connect(Core::ICore::instance(), SIGNAL(contextChanged(Core::IContext*,Core::Context)), +// this, SLOT(contextChanged(Core::IContext*,Core::Context))); + + connect(Core::ModeManager::instance(), + SIGNAL(currentModeChanged(Core::IMode*,Core::IMode*)), + SLOT(onCurrentModeChanged(Core::IMode*,Core::IMode*))); } -void BauhausPlugin::updateEditor(Core::IEditor *editor) +void QmlDesignerPlugin::showDesigner() { - if (editor && editor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID - && Core::ModeManager::currentMode() == m_designMode) - { - m_mainWidget->showEditor(editor); + Q_ASSERT(!m_documentManager.hasCurrentDesignDocument()); + + m_shortCutManager.disconnectUndoActions(currentDesignDocument()); + + m_documentManager.setCurrentDesignDocument(Core::EditorManager::currentEditor()); + + m_shortCutManager.connectUndoActions(currentDesignDocument()); + + m_mainWidget->initialize(); + + if (m_documentManager.hasCurrentDesignDocument()) { + activateAutoSynchronization(); + m_viewManager.pushFileOnCrambleBar(m_documentManager.currentDesignDocument()->fileName()); + } + + m_shortCutManager.updateUndoActions(currentDesignDocument()); +} + +void QmlDesignerPlugin::hideDesigner() +{ + if (currentDesignDocument()->currentModel() + && !currentDesignDocument()->hasQmlSyntaxErrors()) + jumpTextCursorToSelectedModelNode(); + + + if (m_documentManager.hasCurrentDesignDocument()) { + deactivateAutoSynchronization(); + m_mainWidget->saveSettings(); } + + m_shortCutManager.disconnectUndoActions(currentDesignDocument()); + + m_documentManager.setCurrentDesignDocument(0); + + m_shortCutManager.updateUndoActions(0); } -void BauhausPlugin::contextChanged(Core::IContext *context, const Core::Context &additionalContexts) +void QmlDesignerPlugin::changeEditor() { - Q_UNUSED(context) + if (m_documentManager.hasCurrentDesignDocument()) { + deactivateAutoSynchronization(); + m_mainWidget->saveSettings(); + } + + m_shortCutManager.disconnectUndoActions(currentDesignDocument()); + + m_documentManager.setCurrentDesignDocument(Core::EditorManager::currentEditor()); + + m_mainWidget->initialize(); + + m_shortCutManager.connectUndoActions(currentDesignDocument()); - foreach (Core::Id id, additionalContexts) { - if (m_context->context().contains(id)) { - m_isActive = true; - m_mainWidget->showEditor(Core::EditorManager::currentEditor()); - return; + if (m_documentManager.hasCurrentDesignDocument()) { + m_viewManager.pushFileOnCrambleBar(m_documentManager.currentDesignDocument()->fileName()); + activateAutoSynchronization(); + } + + m_shortCutManager.updateUndoActions(currentDesignDocument()); +} + +void QmlDesignerPlugin::jumpTextCursorToSelectedModelNode() +{ + // visual editor -> text editor + ModelNode selectedNode; + if (!currentDesignDocument()->rewriterView()->selectedModelNodes().isEmpty()) + selectedNode = currentDesignDocument()->rewriterView()->selectedModelNodes().first(); + + if (selectedNode.isValid()) { + const int nodeOffset = currentDesignDocument()->rewriterView()->nodeOffset(selectedNode); + if (nodeOffset > 0) { + const ModelNode currentSelectedNode + = currentDesignDocument()->rewriterView()->nodeAtTextCursorPosition(currentDesignDocument()->plainTextEdit()->textCursor().position()); + if (currentSelectedNode != selectedNode) { + int line, column; + currentDesignDocument()->textEditor()->convertPosition(nodeOffset, &line, &column); + currentDesignDocument()->textEditor()->gotoLine(line, column); + } } } +} - if (m_isActive) { - m_isActive = false; - m_mainWidget->showEditor(0); +void QmlDesignerPlugin::selectModelNodeUnderTextCursor() +{ + const int cursorPos = currentDesignDocument()->plainTextEdit()->textCursor().position(); + ModelNode node = currentDesignDocument()->rewriterView()->nodeAtTextCursorPosition(cursorPos); + if (currentDesignDocument()->rewriterView() && node.isValid()) { + currentDesignDocument()->rewriterView()->setSelectedModelNodes(QList<ModelNode>() << node); } } -void BauhausPlugin::textEditorsClosed(QList<Core::IEditor*> editors) +void QmlDesignerPlugin::activateAutoSynchronization() { - m_mainWidget->closeEditors(editors); + // text editor -> visual editor + if (!currentDesignDocument()->isDocumentLoaded()) { + currentDesignDocument()->loadDocument(currentDesignDocument()->plainTextEdit()); + } else { + currentDesignDocument()->activateCurrentModel(); + } + + resetModelSelection(); + + + QList<RewriterView::Error> errors = currentDesignDocument()->qmlSyntaxErrors(); + if (errors.isEmpty()) { + viewManager().attachComponentView(); + viewManager().attachViewsExceptRewriterAndComponetView(); + selectModelNodeUnderTextCursor(); + m_mainWidget->enableWidgets(); + } else { + m_mainWidget->disableWidgets(); + m_mainWidget->showErrorMessage(errors); + } + + + connect(currentDesignDocument()->rewriterView(), + SIGNAL(errorsChanged(QList<RewriterView::Error>)), + m_mainWidget, + SLOT(updateErrorStatus(QList<RewriterView::Error>))); } -// copied from EditorManager::updateActions -void BauhausPlugin::updateActions(Core::IEditor* editor) +void QmlDesignerPlugin::deactivateAutoSynchronization() { - Core::IEditor *curEditor = editor; - int openedCount = m_editorManager->openedEditors().count() - + m_editorManager->openedEditorsModel()->restoredEditors().count(); - - QString fName; - if (curEditor) { - if (!curEditor->document()->fileName().isEmpty()) { - QFileInfo fi(curEditor->document()->fileName()); - fName = fi.fileName(); - } else { - fName = curEditor->displayName(); - } + viewManager().detachViewsExceptRewriterAndComponetView(); + viewManager().detachComponentView(); + + disconnect(currentDesignDocument()->rewriterView(), + SIGNAL(errorsChanged(QList<RewriterView::Error>)), + m_mainWidget, + SLOT(updateErrorStatus(QList<RewriterView::Error>))); + +} + +void QmlDesignerPlugin::resetModelSelection() +{ + if (currentDesignDocument()->rewriterView() && currentDesignDocument()->currentModel()) + currentDesignDocument()->rewriterView()->setSelectedModelNodes(QList<ModelNode>()); +} + + + +void QmlDesignerPlugin::onCurrentEditorChanged(Core::IEditor *editor) +{ + if (editor + && editor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID + && isInDesignerMode()) + { + m_shortCutManager.updateActions(editor); + changeEditor(); } +} - m_saveAction->setEnabled(curEditor != 0 && curEditor->document()->isModified()); - m_saveAsAction->setEnabled(curEditor != 0 && curEditor->document()->isSaveAsAllowed()); - m_revertToSavedAction->setEnabled(curEditor != 0 - && !curEditor->document()->fileName().isEmpty() - && curEditor->document()->isModified()); - - QString quotedName; - if (!fName.isEmpty()) - quotedName = '"' + fName + '"'; - m_saveAsAction->setText(tr("Save %1 As...").arg(quotedName)); - m_saveAction->setText(tr("&Save %1").arg(quotedName)); - m_revertToSavedAction->setText(tr("Revert %1 to Saved").arg(quotedName)); - - m_closeCurrentEditorAction->setEnabled(curEditor != 0); - m_closeCurrentEditorAction->setText(tr("Close %1").arg(quotedName)); - m_closeAllEditorsAction->setEnabled(openedCount > 0); - m_closeOtherEditorsAction->setEnabled(openedCount > 1); - m_closeOtherEditorsAction->setText((openedCount > 1 ? tr("Close All Except %1").arg(quotedName) : tr("Close Others"))); +static bool isDesignerMode(Core::IMode *mode) +{ + return mode == Core::DesignMode::instance(); } -void BauhausPlugin::extensionsInitialized() +void QmlDesignerPlugin::onCurrentModeChanged(Core::IMode *newMode, Core::IMode *oldMode) { - m_designMode = Core::DesignMode::instance(); + if ((currentDesignDocument() + && Core::EditorManager::currentEditor() == currentDesignDocument()->editor()) + && isDesignerMode(newMode)) + return; + + if (!isDesignerMode(newMode) && isDesignerMode(oldMode)) + hideDesigner(); + else if (Core::EditorManager::currentEditor() + && isDesignerMode(newMode) + && isQmlFile(Core::EditorManager::currentEditor())) + showDesigner(); + else if (currentDesignDocument()) + hideDesigner(); - m_mimeTypes << "application/x-qml"; +} - m_designMode->registerDesignWidget(m_mainWidget, m_mimeTypes, m_context->context()); - connect(m_designMode, SIGNAL(actionsUpdated(Core::IEditor*)), SLOT(updateActions(Core::IEditor*))); +DesignDocument *QmlDesignerPlugin::currentDesignDocument() const +{ + return m_documentManager.currentDesignDocument(); } -BauhausPlugin *BauhausPlugin::pluginInstance() +Internal::DesignModeWidget *QmlDesignerPlugin::mainWidget() const { - return m_pluginInstance; + return m_mainWidget; } -void BauhausPlugin::switchTextDesign() +void QmlDesignerPlugin::onTextEditorsClosed(QList<Core::IEditor*> editors) +{ + if (m_documentManager.hasCurrentDesignDocument() + && editors.contains(m_documentManager.currentDesignDocument()->textEditor())) + hideDesigner(); + + m_documentManager.removeEditors(editors); +} + +void QmlDesignerPlugin::extensionsInitialized() +{ + QStringList mimeTypes; + mimeTypes.append("application/x-qml"); + + Core::DesignMode::instance()->registerDesignWidget(m_mainWidget, mimeTypes, m_context->context()); + connect(Core::DesignMode::instance(), + SIGNAL(actionsUpdated(Core::IEditor*)), + &m_shortCutManager, + SLOT(updateActions(Core::IEditor*))); +} + +QmlDesignerPlugin *QmlDesignerPlugin::instance() +{ + return m_instance; +} + +DocumentManager &QmlDesignerPlugin::documentManager() +{ + return m_documentManager; +} + +const DocumentManager &QmlDesignerPlugin::documentManager() const +{ + return m_documentManager; +} + +ViewManager &QmlDesignerPlugin::viewManager() +{ + return m_viewManager; +} + +const ViewManager &QmlDesignerPlugin::viewManager() const +{ + return m_viewManager; +} + +void QmlDesignerPlugin::switchTextDesign() { if (Core::ModeManager::currentMode()->id() == Core::Constants::MODE_EDIT) { Core::IEditor *editor = Core::EditorManager::currentEditor(); - if (editor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) { + if (editor->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) Core::ModeManager::activateMode(Core::Constants::MODE_DESIGN); - m_mainWidget->setFocus(); - } } else if (Core::ModeManager::currentMode()->id() == Core::Constants::MODE_DESIGN) { Core::ModeManager::activateMode(Core::Constants::MODE_EDIT); } } -DesignerSettings BauhausPlugin::settings() +DesignerSettings QmlDesignerPlugin::settings() { m_settings.fromSettings(Core::ICore::settings()); return m_settings; } -void BauhausPlugin::setSettings(const DesignerSettings &s) +void QmlDesignerPlugin::setSettings(const DesignerSettings &s) { if (s != m_settings) { m_settings = s; @@ -384,6 +445,5 @@ void BauhausPlugin::setSettings(const DesignerSettings &s) } } -} -Q_EXPORT_PLUGIN(QmlDesigner::Internal::BauhausPlugin) +Q_EXPORT_PLUGIN(QmlDesigner::QmlDesignerPlugin) diff --git a/src/plugins/qmldesigner/qmldesignerplugin.h b/src/plugins/qmldesigner/qmldesignerplugin.h index b42d4cd553..e20b68e06f 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.h +++ b/src/plugins/qmldesigner/qmldesignerplugin.h @@ -35,6 +35,10 @@ #include <extensionsystem/iplugin.h> +#include "documentmanager.h" +#include "viewmanager.h" +#include "shortcutmanager.h" + #include <QWeakPointer> #include <QStringList> @@ -51,60 +55,70 @@ namespace Core { } namespace QmlDesigner { -namespace Internal { +namespace Internal { class DesignModeWidget; class DesignModeContext; +} -class BauhausPlugin : public ExtensionSystem::IPlugin +class QmlDesignerPlugin : public ExtensionSystem::IPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "QmlDesigner.json") public: - BauhausPlugin(); - virtual ~BauhausPlugin(); + QmlDesignerPlugin(); + virtual ~QmlDesignerPlugin(); //Plugin virtual bool initialize(const QStringList &arguments, QString *errorMessage = 0); virtual void extensionsInitialized(); - static BauhausPlugin *pluginInstance(); + static QmlDesignerPlugin *instance(); + + DocumentManager &documentManager(); + const DocumentManager &documentManager() const; + + ViewManager &viewManager(); + const ViewManager &viewManager() const; DesignerSettings settings(); void setSettings(const DesignerSettings &s); -private slots: + DesignDocument *currentDesignDocument() const; + Internal::DesignModeWidget *mainWidget() const; +private slots: void switchTextDesign(); - void textEditorsClosed(QList<Core::IEditor *> editors); - void updateActions(Core::IEditor* editor); - void updateEditor(Core::IEditor *editor); - void contextChanged(Core::IContext *context, const Core::Context &additionalContexts); + void onTextEditorsClosed(QList<Core::IEditor *> editors); + void onCurrentEditorChanged(Core::IEditor *editor); + void onCurrentModeChanged(Core::IMode *mode, Core::IMode *oldMode); -private: +private: // functions void createDesignModeWidget(); - - QStringList m_mimeTypes; - DesignModeWidget *m_mainWidget; + void showDesigner(); + void hideDesigner(); + void changeEditor(); + void jumpTextCursorToSelectedModelNode(); + void selectModelNodeUnderTextCursor(); + void activateAutoSynchronization(); + void deactivateAutoSynchronization(); + void resetModelSelection(); + +private: // variables + ViewManager m_viewManager; + DocumentManager m_documentManager; + ShortCutManager m_shortCutManager; + + Internal::DesignModeWidget *m_mainWidget; QmlDesigner::PluginManager m_pluginManager; - static BauhausPlugin *m_pluginInstance; + static QmlDesignerPlugin *m_instance; DesignerSettings m_settings; - DesignModeContext *m_context; - Core::DesignMode *m_designMode; - Core::EditorManager *m_editorManager; + Internal::DesignModeContext *m_context; bool m_isActive; - - QAction *m_revertToSavedAction; - QAction *m_saveAction; - QAction *m_saveAsAction; - QAction *m_closeCurrentEditorAction; - QAction *m_closeAllEditorsAction; - QAction *m_closeOtherEditorsAction; }; -} // namespace Internal } // namespace QmlDesigner #endif // QMLDESIGNERPLUGIN_H diff --git a/src/plugins/qmldesigner/qmldesignerplugin.pri b/src/plugins/qmldesigner/qmldesignerplugin.pri index efe34c0bff..7c52f0aaf4 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.pri +++ b/src/plugins/qmldesigner/qmldesignerplugin.pri @@ -1,16 +1,20 @@ HEADERS += $$PWD/qmldesignerconstants.h \ + $$PWD/shortcutmanager.h \ $$PWD/qmldesignerplugin.h \ $$PWD/designmodewidget.h \ $$PWD/designersettings.h \ $$PWD/settingspage.h \ $$PWD/designmodecontext.h \ + $$PWD/documentmanager.h \ $$PWD/styledoutputpaneplaceholder.h SOURCES += $$PWD/qmldesignerplugin.cpp \ + $$PWD/shortcutmanager.cpp \ $$PWD/designmodewidget.cpp \ $$PWD/designersettings.cpp \ $$PWD/settingspage.cpp \ $$PWD/designmodecontext.cpp \ + $$PWD/documentmanager.cpp \ $$PWD/styledoutputpaneplaceholder.cpp FORMS += $$PWD/settingspage.ui diff --git a/src/plugins/qmldesigner/settingspage.cpp b/src/plugins/qmldesigner/settingspage.cpp index d103a80b37..221919cffa 100644 --- a/src/plugins/qmldesigner/settingspage.cpp +++ b/src/plugins/qmldesigner/settingspage.cpp @@ -95,7 +95,7 @@ SettingsPage::SettingsPage() : QWidget *SettingsPage::createPage(QWidget *parent) { m_widget = new SettingsPageWidget(parent); - m_widget->setSettings(BauhausPlugin::pluginInstance()->settings()); + m_widget->setSettings(QmlDesignerPlugin::instance()->settings()); if (m_searchKeywords.isEmpty()) m_searchKeywords = m_widget->searchKeywords(); return m_widget; @@ -105,7 +105,7 @@ void SettingsPage::apply() { if (!m_widget) // page was never shown return; - BauhausPlugin::pluginInstance()->setSettings(m_widget->settings()); + QmlDesignerPlugin::instance()->setSettings(m_widget->settings()); } bool SettingsPage::matches(const QString &s) const diff --git a/src/plugins/qmldesigner/shortcutmanager.cpp b/src/plugins/qmldesigner/shortcutmanager.cpp new file mode 100644 index 0000000000..3852f4958c --- /dev/null +++ b/src/plugins/qmldesigner/shortcutmanager.cpp @@ -0,0 +1,326 @@ +#include "shortcutmanager.h" + +#include <coreplugin/actionmanager/actionmanager.h> +#include <coreplugin/actionmanager/actioncontainer.h> +#include <coreplugin/icore.h> +#include <coreplugin/editormanager/openeditorsmodel.h> +#include <coreplugin/coreconstants.h> +#include <utils/hostosinfo.h> + +#include "qmldesignerconstants.h" +#include "designdocument.h" +#include "qmldesignerplugin.h" +#include "designmodewidget.h" + + +namespace QmlDesigner { + +ShortCutManager::ShortCutManager() + : QObject(), + m_revertToSavedAction(0), + m_saveAction(0), + m_saveAsAction(0), + m_closeCurrentEditorAction(0), + m_closeAllEditorsAction(0), + m_closeOtherEditorsAction(0), + m_undoAction(tr("&Undo"), 0), + m_redoAction(tr("&Redo"), 0), + m_deleteAction(tr("Delete"), tr("Delete \"%1\""), Utils::ParameterAction::EnabledWithParameter), + m_cutAction(tr("Cu&t"), tr("Cut \"%1\""), Utils::ParameterAction::EnabledWithParameter), + m_copyAction(tr("&Copy"), tr("Copy \"%1\""), Utils::ParameterAction::EnabledWithParameter), + m_pasteAction(tr("&Paste"), tr("Paste \"%1\""), Utils::ParameterAction::EnabledWithParameter), + m_selectAllAction(tr("Select &All"), tr("Select All \"%1\""), Utils::ParameterAction::EnabledWithParameter), + m_hideSidebarsAction(tr("Toggle Full Screen"), 0), + m_restoreDefaultViewAction(tr("&Restore Default View"), 0), + m_toggleLeftSidebarAction(tr("Toggle &Left Sidebar"), 0), + m_toggleRightSidebarAction(tr("Toggle &Right Sidebar"), 0), + m_goIntoComponentAction (tr("&Go into Component"), 0) +{ + +} + +void ShortCutManager::registerActions() +{ + Core::ActionContainer *editMenu = Core::ActionManager::actionContainer(Core::Constants::M_EDIT); + + Core::Context qmlDesignerMainContext(Constants::C_QMLDESIGNER); + Core::Context qmlDesignerFormEditorContext(Constants::C_QMLFORMEDITOR); + Core::Context qmlDesignerNavigatorContext(Constants::C_QMLNAVIGATOR); + + connect(&m_undoAction, SIGNAL(triggered()), this, SLOT(undo())); + + connect(&m_redoAction, SIGNAL(triggered()), this, SLOT(redo())); + + connect(&m_deleteAction, SIGNAL(triggered()), this, SLOT(deleteSelected())); + + connect(&m_cutAction, SIGNAL(triggered()), this, SLOT(cutSelected())); + + connect(&m_copyAction, SIGNAL(triggered()), this, SLOT(copySelected())); + + connect(&m_pasteAction, SIGNAL(triggered()), this, SLOT(paste())); + + connect(&m_selectAllAction, SIGNAL(triggered()), this, SLOT(selectAll())); + + connect(&m_hideSidebarsAction, SIGNAL(triggered()), this, SLOT(toggleSidebars())); + + connect(&m_restoreDefaultViewAction, + SIGNAL(triggered()), + QmlDesignerPlugin::instance()->mainWidget(), + SLOT(restoreDefaultView())); + + connect(&m_goIntoComponentAction, SIGNAL(triggered()), SLOT(goIntoComponent())); + + connect(&m_toggleLeftSidebarAction, + SIGNAL(triggered()), + QmlDesignerPlugin::instance()->mainWidget(), + SLOT(toggleLeftSidebar())); + + connect(&m_toggleRightSidebarAction, + SIGNAL(triggered()), + QmlDesignerPlugin::instance()->mainWidget(), + SLOT(toggleRightSidebar())); + + // Revert to saved + Core::ActionManager::registerAction(&m_revertToSavedAction,Core::Constants::REVERTTOSAVED, qmlDesignerMainContext); + connect(&m_revertToSavedAction, SIGNAL(triggered()), Core::ICore::editorManager(), SLOT(revertToSaved())); + + //Save + Core::ActionManager::registerAction(&m_saveAction, Core::Constants::SAVE, qmlDesignerMainContext); + connect(&m_saveAction, SIGNAL(triggered()), Core::ICore::editorManager(), SLOT(saveDocument())); + + //Save As + Core::ActionManager::registerAction(&m_saveAsAction, Core::Constants::SAVEAS, qmlDesignerMainContext); + connect(&m_saveAsAction, SIGNAL(triggered()), Core::ICore::editorManager(), SLOT(saveDocumentAs())); + + //Close Editor + Core::ActionManager::registerAction(&m_closeCurrentEditorAction, Core::Constants::CLOSE, qmlDesignerMainContext); + connect(&m_closeCurrentEditorAction, SIGNAL(triggered()), Core::ICore::editorManager(), SLOT(closeEditor())); + + //Close All + Core::ActionManager::registerAction(&m_closeAllEditorsAction, Core::Constants::CLOSEALL, qmlDesignerMainContext); + connect(&m_closeAllEditorsAction, SIGNAL(triggered()), Core::ICore::editorManager(), SLOT(closeAllEditors())); + + //Close All Others Action + Core::ActionManager::registerAction(&m_closeOtherEditorsAction, Core::Constants::CLOSEOTHERS, qmlDesignerMainContext); + connect(&m_closeOtherEditorsAction, SIGNAL(triggered()), Core::ICore::editorManager(), SLOT(closeOtherEditors())); + + // Undo / Redo + Core::ActionManager::registerAction(&m_undoAction, Core::Constants::UNDO, qmlDesignerMainContext); + Core::ActionManager::registerAction(&m_redoAction, Core::Constants::REDO, qmlDesignerMainContext); + + Core::Command *command; + + //GoIntoComponent + command = Core::ActionManager::registerAction(&m_goIntoComponentAction, + Constants::GO_INTO_COMPONENT, qmlDesignerMainContext); + command->setDefaultKeySequence(QKeySequence(Qt::Key_F2)); + + //Edit Menu + + command = Core::ActionManager::registerAction(&m_deleteAction, QmlDesigner::Constants::DELETE, qmlDesignerFormEditorContext); + command = Core::ActionManager::registerAction(&m_deleteAction, QmlDesigner::Constants::DELETE, qmlDesignerNavigatorContext); + command->setDefaultKeySequence(QKeySequence::Delete); + command->setAttribute(Core::Command::CA_Hide); // don't show delete in other modes + editMenu->addAction(command, Core::Constants::G_EDIT_COPYPASTE); + + command = Core::ActionManager::registerAction(&m_cutAction, Core::Constants::CUT, qmlDesignerFormEditorContext); + command = Core::ActionManager::registerAction(&m_cutAction, Core::Constants::CUT, qmlDesignerNavigatorContext); + command->setDefaultKeySequence(QKeySequence::Cut); + editMenu->addAction(command, Core::Constants::G_EDIT_COPYPASTE); + + command = Core::ActionManager::registerAction(&m_copyAction, Core::Constants::COPY, qmlDesignerFormEditorContext); + command = Core::ActionManager::registerAction(&m_copyAction, Core::Constants::COPY, qmlDesignerNavigatorContext); + command->setDefaultKeySequence(QKeySequence::Copy); + editMenu->addAction(command, Core::Constants::G_EDIT_COPYPASTE); + + command = Core::ActionManager::registerAction(&m_pasteAction, Core::Constants::PASTE, qmlDesignerFormEditorContext); + command = Core::ActionManager::registerAction(&m_pasteAction, Core::Constants::PASTE, qmlDesignerNavigatorContext); + command->setDefaultKeySequence(QKeySequence::Paste); + editMenu->addAction(command, Core::Constants::G_EDIT_COPYPASTE); + + command = Core::ActionManager::registerAction(&m_selectAllAction, Core::Constants::SELECTALL, qmlDesignerFormEditorContext); + command = Core::ActionManager::registerAction(&m_selectAllAction, Core::Constants::SELECTALL, qmlDesignerNavigatorContext); + + command->setDefaultKeySequence(QKeySequence::SelectAll); + editMenu->addAction(command, Core::Constants::G_EDIT_SELECTALL); + + Core::ActionContainer *viewsMenu = Core::ActionManager::actionContainer(Core::Constants::M_WINDOW_VIEWS); + + command = Core::ActionManager::registerAction(&m_toggleLeftSidebarAction, Constants::TOGGLE_LEFT_SIDEBAR, qmlDesignerMainContext); + command->setAttribute(Core::Command::CA_Hide); + command->setDefaultKeySequence(QKeySequence("Ctrl+Alt+0")); + viewsMenu->addAction(command); + + command = Core::ActionManager::registerAction(&m_toggleRightSidebarAction, Constants::TOGGLE_RIGHT_SIDEBAR, qmlDesignerMainContext); + command->setAttribute(Core::Command::CA_Hide); + command->setDefaultKeySequence(QKeySequence("Ctrl+Alt+Shift+0")); + viewsMenu->addAction(command); + + command = Core::ActionManager::registerAction(&m_restoreDefaultViewAction, Constants::RESTORE_DEFAULT_VIEW, qmlDesignerMainContext); + command->setAttribute(Core::Command::CA_Hide); + viewsMenu->addAction(command); + + command = Core::ActionManager::registerAction(&m_hideSidebarsAction, Core::Constants::TOGGLE_SIDEBAR, qmlDesignerMainContext); + + if (Utils::HostOsInfo::isMacHost()) { + // add second shortcut to trigger delete + QAction *deleteAction = new QAction(this); + deleteAction->setShortcut(QKeySequence(QLatin1String("Backspace"))); + connect(deleteAction, + SIGNAL(triggered()), + &m_deleteAction, + SIGNAL(triggered())); + } +} + +void ShortCutManager::updateActions(Core::IEditor* editor) +{ + Core::IEditor *currentEditor = editor; + int openedCount = Core::ICore::editorManager()->openedEditors().count() + + Core::ICore::editorManager()->openedEditorsModel()->restoredEditors().count(); + + QString fileName; + if (currentEditor) { + if (!currentEditor->document()->fileName().isEmpty()) { + QFileInfo fileInfo(currentEditor->document()->fileName()); + fileName = fileInfo.fileName(); + } else { + fileName = currentEditor->displayName(); + } + } + + m_saveAction.setEnabled(currentEditor != 0 && currentEditor->document()->isModified()); + m_saveAsAction.setEnabled(currentEditor != 0 && currentEditor->document()->isSaveAsAllowed()); + m_revertToSavedAction.setEnabled(currentEditor != 0 + && !currentEditor->document()->fileName().isEmpty() + && currentEditor->document()->isModified()); + + QString quotedName; + if (!fileName.isEmpty()) + quotedName = '"' + fileName + '"'; + + m_saveAsAction.setText(tr("Save %1 As...").arg(quotedName)); + m_saveAction.setText(tr("&Save %1").arg(quotedName)); + m_revertToSavedAction.setText(tr("Revert %1 to Saved").arg(quotedName)); + + m_closeCurrentEditorAction.setEnabled(currentEditor != 0); + m_closeCurrentEditorAction.setText(tr("Close %1").arg(quotedName)); + m_closeAllEditorsAction.setEnabled(openedCount > 0); + m_closeOtherEditorsAction.setEnabled(openedCount > 1); + m_closeOtherEditorsAction.setText((openedCount > 1 ? tr("Close All Except %1").arg(quotedName) : tr("Close Others"))); +} + +void ShortCutManager::undo() +{ + if (currentDesignDocument()) + currentDesignDocument()->undo(); +} + +void ShortCutManager::redo() +{ + if (currentDesignDocument()) + currentDesignDocument()->redo(); +} + +void ShortCutManager::deleteSelected() +{ + if (currentDesignDocument()) + currentDesignDocument()->deleteSelected(); +} + +void ShortCutManager::cutSelected() +{ + if (currentDesignDocument()) + currentDesignDocument()->cutSelected(); +} + +void ShortCutManager::copySelected() +{ + if (currentDesignDocument()) + currentDesignDocument()->copySelected(); +} + +void ShortCutManager::paste() +{ + if (currentDesignDocument()) + currentDesignDocument()->paste(); +} + +void ShortCutManager::selectAll() +{ + if (currentDesignDocument()) + currentDesignDocument()->selectAll(); +} + +void ShortCutManager::toggleSidebars() +{ + QmlDesignerPlugin::instance()->mainWidget()->toggleSidebars(); +} + +void ShortCutManager::toggleLeftSidebar() +{ + QmlDesignerPlugin::instance()->mainWidget()->toggleLeftSidebar(); +} + +void ShortCutManager::toggleRightSidebar() +{ + QmlDesignerPlugin::instance()->mainWidget()->toggleRightSidebar(); +} + +void ShortCutManager::connectUndoActions(DesignDocument *designDocument) +{ + if (designDocument) { + connect(designDocument, SIGNAL(undoAvailable(bool)), this, SLOT(undoAvailable(bool))); + connect(designDocument, SIGNAL(redoAvailable(bool)), this, SLOT(redoAvailable(bool))); + } +} + +void ShortCutManager::disconnectUndoActions(DesignDocument *designDocument) +{ + if (currentDesignDocument()) { + disconnect(designDocument, SIGNAL(undoAvailable(bool)), this, SLOT(undoAvailable(bool))); + disconnect(designDocument, SIGNAL(redoAvailable(bool)), this, SLOT(redoAvailable(bool))); + } +} + +void ShortCutManager::updateUndoActions(DesignDocument *designDocument) +{ + if (designDocument) { + m_undoAction.setEnabled(designDocument->isUndoAvailable()); + m_redoAction.setEnabled(designDocument->isRedoAvailable()); + } else { + m_undoAction.setEnabled(false); + m_redoAction.setEnabled(false); + } +} + +DesignDocument *ShortCutManager::currentDesignDocument() const +{ + return QmlDesignerPlugin::instance()->currentDesignDocument(); +} + +void ShortCutManager::undoAvailable(bool isAvailable) +{ + DesignDocument *documentController = qobject_cast<DesignDocument*>(sender()); + if (currentDesignDocument() && + currentDesignDocument() == documentController) { + m_undoAction.setEnabled(isAvailable); + } +} + +void ShortCutManager::redoAvailable(bool isAvailable) +{ + DesignDocument *documentController = qobject_cast<DesignDocument*>(sender()); + if (currentDesignDocument() && + currentDesignDocument() == documentController) { + m_redoAction.setEnabled(isAvailable); + } +} + +void ShortCutManager::goIntoComponent() +{ + if (currentDesignDocument()) + currentDesignDocument()->goIntoComponent(); +} + +} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/shortcutmanager.h b/src/plugins/qmldesigner/shortcutmanager.h new file mode 100644 index 0000000000..03a5450eb6 --- /dev/null +++ b/src/plugins/qmldesigner/shortcutmanager.h @@ -0,0 +1,72 @@ +#ifndef QMLDESIGNER_SHORTCUTMANAGER_H +#define QMLDESIGNER_SHORTCUTMANAGER_H + +#include <QObject> +#include <QAction> +#include <utils/parameteraction.h> + + +namespace Core { + class IEditor; +} + +namespace QmlDesigner { + +class DesignDocument; + +class ShortCutManager : public QObject +{ + Q_OBJECT + +public: + ShortCutManager(); + + void registerActions(); + + void connectUndoActions(DesignDocument *designDocument); + void disconnectUndoActions(DesignDocument *designDocument); + void updateUndoActions(DesignDocument *designDocument); + DesignDocument *currentDesignDocument() const; + +public slots: + void updateActions(Core::IEditor* editor); + +private slots: + void undo(); + void redo(); + void deleteSelected(); + void cutSelected(); + void copySelected(); + void paste(); + void selectAll(); + void toggleSidebars(); + void toggleLeftSidebar(); + void toggleRightSidebar(); + void undoAvailable(bool isAvailable); + void redoAvailable(bool isAvailable); + void goIntoComponent(); + +private: + QAction m_revertToSavedAction; + QAction m_saveAction; + QAction m_saveAsAction; + QAction m_closeCurrentEditorAction; + QAction m_closeAllEditorsAction; + QAction m_closeOtherEditorsAction; + QAction m_undoAction; + QAction m_redoAction; + Utils::ParameterAction m_deleteAction; + Utils::ParameterAction m_cutAction; + Utils::ParameterAction m_copyAction; + Utils::ParameterAction m_pasteAction; + Utils::ParameterAction m_selectAllAction; + QAction m_hideSidebarsAction; + QAction m_restoreDefaultViewAction; + QAction m_toggleLeftSidebarAction; + QAction m_toggleRightSidebarAction; + QAction m_goIntoComponentAction; +}; + +} // namespace QmlDesigner + +#endif // QMLDESIGNER_SHORTCUTMANAGER_H |