1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at info@qt.nokia.com.
31 **************************************************************************/
33 #include "designdocumentcontroller.h"
34 #include "designdocumentcontrollerview.h"
35 #include "xuifiledialog.h"
36 #include "componentview.h"
37 #include "subcomponentmanager.h"
38 #include "model/viewlogger.h"
40 #include <qt4projectmanager/qt4buildconfiguration.h>
42 #include <itemlibraryview.h>
43 #include <itemlibrarywidget.h>
44 #include <navigatorview.h>
45 #include <stateseditorview.h>
46 #include <formeditorview.h>
47 #include <propertyeditor.h>
48 #include <formeditorwidget.h>
49 #include <basetexteditmodifier.h>
50 #include <componenttextmodifier.h>
52 #include <invalidargumentexception.h>
53 #include <componentview.h>
54 #include <componentaction.h>
55 #include <qmlobjectnode.h>
56 #include <rewriterview.h>
57 #include <rewritingexception.h>
58 #include <nodelistproperty.h>
59 #include <variantproperty.h>
60 #include <rewritingexception.h>
61 #include <model/modelnodecontextmenu.h>
63 #include <utils/fileutils.h>
65 #include <QtCore/QCoreApplication>
66 #include <QtCore/QDir>
67 #include <QtCore/QFile>
68 #include <QtCore/QFileInfo>
69 #include <QtCore/QUrl>
70 #include <QtCore/QProcess>
71 #include <QtCore/QTemporaryFile>
72 #include <QtCore/QtDebug>
73 #include <QtCore/QEvent>
75 #include <QtGui/QBoxLayout>
76 #include <QtGui/QComboBox>
77 #include <QtGui/QErrorMessage>
78 #include <QtGui/QFileDialog>
79 #include <QtGui/QLabel>
80 #include <QtGui/QMdiArea>
81 #include <QtGui/QMdiSubWindow>
82 #include <QtGui/QMessageBox>
83 #include <QtGui/QUndoStack>
84 #include <QtGui/QPlainTextEdit>
85 #include <QtGui/QApplication>
87 #include <projectexplorer/projectexplorer.h>
88 #include <qt4projectmanager/qt4project.h>
89 #include <qt4projectmanager/qt4target.h>
90 #include <qtsupport/qtversionmanager.h>
91 #include <qt4projectmanager/qt4projectmanagerconstants.h>
92 #include <qmlprojectmanager/qmlprojectrunconfiguration.h>
98 namespace QmlDesigner {
100 class DesignDocumentControllerPrivate {
102 QWeakPointer<FormEditorView> formEditorView;
104 QWeakPointer<ItemLibraryView> itemLibraryView;
105 QWeakPointer<NavigatorView> navigator;
106 QWeakPointer<PropertyEditor> propertyEditorView;
107 QWeakPointer<StatesEditorView> statesEditorView;
108 QWeakPointer<QStackedWidget> stackedWidget;
109 QWeakPointer<NodeInstanceView> nodeInstanceView;
110 QWeakPointer<ComponentView> componentView;
112 QWeakPointer<QmlDesigner::Model> model;
113 QWeakPointer<QmlDesigner::Model> subComponentModel;
114 QWeakPointer<QmlDesigner::Model> masterModel;
115 QWeakPointer<QPlainTextEdit> textEdit;
116 QWeakPointer<RewriterView> rewriterView;
117 QmlDesigner::BaseTextEditModifier *textModifier;
118 QmlDesigner::ComponentTextModifier *componentTextModifier;
119 QWeakPointer<SubComponentManager> subComponentManager;
120 QWeakPointer<Internal::ViewLogger> viewLogger;
129 DesignDocumentController *DesignDocumentController::m_this = 0;
132 \class QmlDesigner::DesignDocumentController
134 DesignDocumentController acts as a facade to a model representing a qml document,
135 and the different views/widgets accessing it.
137 DesignDocumentController::DesignDocumentController(QObject *parent) :
139 d(new DesignDocumentControllerPrivate)
142 d->documentLoaded = false;
143 d->syncBlocked = false;
145 ProjectExplorer::ProjectExplorerPlugin *projectExplorer = ProjectExplorer::ProjectExplorerPlugin::instance();
146 connect(projectExplorer, SIGNAL(currentProjectChanged(ProjectExplorer::Project*)), this, SLOT(activeQtVersionChanged()));
147 activeQtVersionChanged();
150 DesignDocumentController::~DesignDocumentController()
153 delete d->model.data();
154 delete d->subComponentModel.data();
156 delete d->rewriterView.data();
158 if (d->componentTextModifier) //componentTextModifier might not be created
159 delete d->componentTextModifier;
164 Model *DesignDocumentController::model() const
166 return d->model.data();
169 Model *DesignDocumentController::masterModel() const
171 return d->masterModel.data();
175 void DesignDocumentController::detachNodeInstanceView()
177 if (d->nodeInstanceView)
178 model()->detachView(d->nodeInstanceView.data());
181 void DesignDocumentController::attachNodeInstanceView()
183 if (d->nodeInstanceView) {
184 model()->attachView(d->nodeInstanceView.data());
186 if (d->formEditorView) {
187 d->formEditorView->resetView();
191 void DesignDocumentController::changeToMasterModel()
193 d->model->detachView(d->rewriterView.data());
194 d->rewriterView->setTextModifier(d->textModifier);
195 d->model = d->masterModel;
196 d->model->attachView(d->rewriterView.data());
199 QWidget *DesignDocumentController::centralWidget() const
201 return qobject_cast<QWidget*>(parent());
204 QString DesignDocumentController::pathToQt() const
206 QtSupport::BaseQtVersion *activeQtVersion = QtSupport::QtVersionManager::instance()->version(d->qt_versionId);
207 if (activeQtVersion && (activeQtVersion->qtVersion().majorVersion > 3)
208 && (activeQtVersion->supportsTargetId(Qt4ProjectManager::Constants::QT_SIMULATOR_TARGET_ID)
209 || activeQtVersion->supportsTargetId(Qt4ProjectManager::Constants::DESKTOP_TARGET_ID)))
210 return activeQtVersion->versionInfo().value("QT_INSTALL_DATA");
215 Returns whether the model is automatically updated if the text editor changes.
217 bool DesignDocumentController::isModelSyncBlocked() const
219 return d->syncBlocked;
223 Switches whether the model (and therefore the views) are updated if the text editor
226 If the synchronization is enabled again, the model is automatically resynchronized
227 with the current state of the text editor.
229 void DesignDocumentController::blockModelSync(bool block)
231 if (d->syncBlocked == block)
234 d->syncBlocked = block;
236 if (d->textModifier) {
237 if (d->syncBlocked) {
238 detachNodeInstanceView();
239 d->textModifier->deactivateChangeSignals();
241 activeQtVersionChanged();
242 changeToMasterModel();
244 //We go back to base state (and back again) to avoid side effects from text editing.
245 if (d->statesEditorView && d->statesEditorView->model()) {
246 state = d->statesEditorView->currentState();
247 d->statesEditorView->setCurrentState(d->statesEditorView->baseState());
251 d->textModifier->reactivateChangeSignals();
253 if (state.isValid() && d->statesEditorView)
254 d->statesEditorView->setCurrentState(state);
255 attachNodeInstanceView();
256 if (d->propertyEditorView)
257 d->propertyEditorView->resetView();
258 if (d->formEditorView)
259 d->formEditorView->resetView();
265 Returns any errors that happened when parsing the latest qml file.
267 QList<RewriterView::Error> DesignDocumentController::qmlErrors() const
269 return d->rewriterView->errors();
272 void DesignDocumentController::setItemLibraryView(ItemLibraryView* itemLibraryView)
274 d->itemLibraryView = itemLibraryView;
277 void DesignDocumentController::setNavigator(NavigatorView* navigatorView)
279 d->navigator = navigatorView;
282 void DesignDocumentController::setPropertyEditorView(PropertyEditor *propertyEditor)
284 d->propertyEditorView = propertyEditor;
287 void DesignDocumentController::setStatesEditorView(StatesEditorView* statesEditorView)
289 d->statesEditorView = statesEditorView;
292 void DesignDocumentController::setFormEditorView(FormEditorView *formEditorView)
294 d->formEditorView = formEditorView;
297 void DesignDocumentController::setNodeInstanceView(NodeInstanceView *nodeInstanceView)
299 d->nodeInstanceView = nodeInstanceView;
302 void DesignDocumentController::setComponentView(ComponentView *componentView)
304 d->componentView = componentView;
305 connect(d->componentView->action(), SIGNAL(currentComponentChanged(ModelNode)), SLOT(changeCurrentModelTo(ModelNode)));
308 DesignDocumentController *DesignDocumentController::instance()
313 QString DesignDocumentController::displayName() const
315 if (fileName().isEmpty())
316 return tr("-New Form-");
321 QString DesignDocumentController::fileName() const
326 void DesignDocumentController::setFileName(const QString &fileName)
328 d->fileName = fileName;
330 if (QFileInfo(fileName).exists()) {
331 d->searchPath = QUrl::fromLocalFile(fileName);
333 d->searchPath = QUrl(fileName);
337 d->model->setFileUrl(d->searchPath);
339 if (d->itemLibraryView)
340 d->itemLibraryView->widget()->setResourcePath(QFileInfo(fileName).absolutePath());
341 emit displayNameChanged(displayName());
344 QList<RewriterView::Error> DesignDocumentController::loadMaster(QPlainTextEdit *edit)
350 connect(edit, SIGNAL(undoAvailable(bool)),
351 this, SIGNAL(undoAvailable(bool)));
352 connect(edit, SIGNAL(redoAvailable(bool)),
353 this, SIGNAL(redoAvailable(bool)));
354 connect(edit, SIGNAL(modificationChanged(bool)),
355 this, SIGNAL(dirtyStateChanged(bool)));
357 d->textModifier = new BaseTextEditModifier(dynamic_cast<TextEditor::BaseTextEditorWidget*>(d->textEdit.data()));
359 d->componentTextModifier = 0;
361 //d->masterModel = Model::create(d->textModifier, d->searchPath, errors);
363 d->masterModel = Model::create("QtQuick.Rectangle", 1, 0);
365 #if defined(VIEWLOGGER)
366 d->viewLogger = new Internal::ViewLogger(d->model.data());
367 d->masterModel->attachView(d->viewLogger.data());
370 d->masterModel->setFileUrl(d->searchPath);
372 d->subComponentModel = Model::create("QtQuick.Rectangle", 1, 0);
373 d->subComponentModel->setFileUrl(d->searchPath);
375 d->rewriterView = new RewriterView(RewriterView::Amend, d->masterModel.data());
376 d->rewriterView->setTextModifier( d->textModifier);
377 connect(d->rewriterView.data(), SIGNAL(errorsChanged(const QList<RewriterView::Error> &)),
378 this, SIGNAL(qmlErrorsChanged(const QList<RewriterView::Error> &)));
380 d->masterModel->attachView(d->rewriterView.data());
381 d->model = d->masterModel;
383 d->subComponentManager = new SubComponentManager(d->masterModel.data(), this);
384 d->subComponentManager->update(d->searchPath, d->model->imports());
388 d->masterModel->attachView(d->componentView.data());
390 return d->rewriterView->errors();
393 void DesignDocumentController::changeCurrentModelTo(const ModelNode &componentNode)
395 Q_ASSERT(d->masterModel);
396 QWeakPointer<Model> oldModel = d->model;
397 Q_ASSERT(oldModel.data());
399 if (d->model == d->subComponentModel) {
400 changeToMasterModel();
403 QString componentText = d->rewriterView->extractText(QList<ModelNode>() << componentNode).value(componentNode);
405 if (componentText.isEmpty())
408 bool explicitComponent = false;
409 if (componentText.contains("Component")) { //explicit component
410 explicitComponent = true;
413 if (!componentNode.isRootNode()) {
414 Q_ASSERT(d->model == d->masterModel);
415 Q_ASSERT(componentNode.isValid());
416 //change to subcomponent model
417 ModelNode rootModelNode = componentNode.view()->rootModelNode();
418 Q_ASSERT(rootModelNode.isValid());
419 if (d->componentTextModifier)
420 delete d->componentTextModifier;
423 int componentStartOffset;
424 int componentEndOffset;
426 int rootStartOffset = d->rewriterView->nodeOffset(rootModelNode);
428 if (explicitComponent) { //the component is explciit we have to find the first definition inside
429 componentStartOffset = d->rewriterView->firstDefinitionInsideOffset(componentNode);
430 componentEndOffset = componentStartOffset + d->rewriterView->firstDefinitionInsideLength(componentNode);
431 } else { //the component is implicit
432 componentStartOffset = d->rewriterView->nodeOffset(componentNode);
433 componentEndOffset = componentStartOffset + d->rewriterView->nodeLength(componentNode);
436 d->componentTextModifier = new ComponentTextModifier (d->textModifier, componentStartOffset, componentEndOffset, rootStartOffset);
439 d->model->detachView(d->rewriterView.data());
441 d->rewriterView->setTextModifier(d->componentTextModifier);
443 d->subComponentModel->attachView(d->rewriterView.data());
445 Q_ASSERT(d->rewriterView->rootModelNode().isValid());
447 d->model = d->subComponentModel;
450 Q_ASSERT(d->masterModel);
454 d->componentView->setComponentNode(componentNode);
457 void DesignDocumentController::goIntoComponent()
462 QList<ModelNode> selectedNodes;
463 if (d->formEditorView)
464 selectedNodes = d->formEditorView->selectedModelNodes();
466 if (selectedNodes.count() == 1)
467 ModelNodeAction::goIntoComponent(selectedNodes.first());
470 void DesignDocumentController::loadCurrentModel()
472 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
474 Q_ASSERT(d->masterModel);
476 d->model->setMasterModel(d->masterModel.data());
478 d->nodeInstanceView->setPathToQt(pathToQt());
479 d->model->attachView(d->nodeInstanceView.data());
480 d->model->attachView(d->navigator.data());
481 d->itemLibraryView->widget()->setResourcePath(QFileInfo(d->fileName).absolutePath());
483 d->model->attachView(d->formEditorView.data());
484 d->model->attachView(d->itemLibraryView.data());
486 if (!d->textEdit->parent()) // hack to prevent changing owner of external text edit
487 d->stackedWidget->addWidget(d->textEdit.data());
489 // Will call setCurrentState (formEditorView etc has to be constructed first)
490 d->model->attachView(d->statesEditorView.data());
492 d->model->attachView(d->propertyEditorView.data());
494 d->documentLoaded = true;
495 Q_ASSERT(d->masterModel);
496 QApplication::restoreOverrideCursor();
499 QList<RewriterView::Error> DesignDocumentController::loadMaster(const QByteArray &qml)
501 QPlainTextEdit *textEdit = new QPlainTextEdit;
502 textEdit->setReadOnly(true);
503 textEdit->setPlainText(QString(qml));
504 return loadMaster(textEdit);
507 void DesignDocumentController::saveAs(QWidget *parent)
509 QFileInfo oldFileInfo(d->fileName);
510 XUIFileDialog::runSaveFileDialog(oldFileInfo.path(), parent, this, SLOT(doRealSaveAs(QString)));
513 void DesignDocumentController::doRealSaveAs(const QString &fileName)
515 if (fileName.isNull())
518 QFileInfo fileInfo(fileName);
519 if (fileInfo.exists() && !fileInfo.isWritable()) {
520 QMessageBox msgBox(centralWidget());
521 msgBox.setIcon(QMessageBox::Warning);
522 msgBox.setText(tr("Cannot save to file \"%1\": permission denied.").arg(fileInfo.baseName()));
525 } else if (!fileInfo.exists() && !fileInfo.dir().exists()) {
526 QMessageBox msgBox(centralWidget());
527 msgBox.setIcon(QMessageBox::Warning);
528 msgBox.setText(tr("Parent folder \"%1\" for file \"%2\" does not exist.")
529 .arg(fileInfo.dir().dirName())
530 .arg(fileInfo.baseName()));
535 setFileName(fileName);
536 save(centralWidget());
539 bool DesignDocumentController::isDirty() const
542 return d->textEdit->document()->isModified();
547 bool DesignDocumentController::isUndoAvailable() const
551 return d->textEdit->document()->isUndoAvailable();
555 bool DesignDocumentController::isRedoAvailable() const
558 return d->textEdit->document()->isRedoAvailable();
562 void DesignDocumentController::close()
564 d->documentLoaded = false;
565 emit designDocumentClosed();
568 void DesignDocumentController::deleteSelected()
574 if (d->formEditorView) {
575 RewriterTransaction transaction(d->formEditorView.data());
576 QList<ModelNode> toDelete = d->formEditorView->selectedModelNodes();
577 foreach (ModelNode node, toDelete) {
578 if (node.isValid() && !node.isRootNode() && QmlObjectNode(node).isValid())
579 QmlObjectNode(node).destroy();
582 } catch (RewritingException &e) {
583 QMessageBox::warning(0, tr("Error"), e.description());
587 void DesignDocumentController::copySelected()
589 QScopedPointer<Model> model(Model::create("QtQuick.Rectangle", 1, 0, this->model()));
590 model->setFileUrl(d->model->fileUrl());
591 model->changeImports(d->model->imports(), QList<Import>());
595 DesignDocumentControllerView view;
597 d->model->attachView(&view);
599 if (view.selectedModelNodes().isEmpty())
602 QList<ModelNode> selectedNodes(view.selectedModelNodes());
604 foreach (const ModelNode &node, selectedNodes) {
605 foreach (const ModelNode &node2, selectedNodes) {
606 if (node.isAncestorOf(node2))
607 selectedNodes.removeAll(node2);
611 if (selectedNodes.count() == 1) {
612 ModelNode selectedNode(selectedNodes.first());
614 if (!selectedNode.isValid())
617 d->model->detachView(&view);
619 model->attachView(&view);
620 view.replaceModel(selectedNode);
622 Q_ASSERT(view.rootModelNode().isValid());
623 Q_ASSERT(view.rootModelNode().type() != "empty");
626 } else { //multi items selected
627 d->model->detachView(&view);
628 model->attachView(&view);
630 foreach (ModelNode node, view.rootModelNode().allDirectSubModelNodes()) {
633 view.changeRootNodeType("QtQuick.Rectangle", 1, 0);
634 view.rootModelNode().setId("designer__Selection");
636 foreach (const ModelNode &selectedNode, selectedNodes) {
637 ModelNode newNode(view.insertModel(selectedNode));
638 view.rootModelNode().nodeListProperty("data").reparentHere(newNode);
645 void DesignDocumentController::cutSelected()
651 static void scatterItem(ModelNode pastedNode, const ModelNode targetNode, int offset = -2000)
654 bool scatter = false;
655 foreach (const ModelNode &childNode, targetNode.allDirectSubModelNodes()) {
656 if ((childNode.variantProperty("x").value() == pastedNode.variantProperty("x").value()) &&
657 (childNode.variantProperty("y").value() == pastedNode.variantProperty("y").value()))
663 if (offset == -2000) {
664 double x = pastedNode.variantProperty("x").value().toDouble();
665 double y = pastedNode.variantProperty("y").value().toDouble();
666 double targetWidth = 20;
667 double targetHeight = 20;
668 x = x + double(qrand()) / RAND_MAX * targetWidth - targetWidth / 2;
669 y = y + double(qrand()) / RAND_MAX * targetHeight - targetHeight / 2;
670 pastedNode.variantProperty("x") = int(x);
671 pastedNode.variantProperty("y") = int(y);
673 double x = pastedNode.variantProperty("x").value().toDouble();
674 double y = pastedNode.variantProperty("y").value().toDouble();
677 pastedNode.variantProperty("x") = int(x);
678 pastedNode.variantProperty("y") = int(y);
682 void DesignDocumentController::paste()
684 QScopedPointer<Model> model(Model::create("empty", 1, 0, this->model()));
685 model->setFileUrl(d->model->fileUrl());
686 model->changeImports(d->model->imports(), QList<Import>());
693 DesignDocumentControllerView view;
694 model->attachView(&view);
696 view.fromClipboard();
698 ModelNode rootNode(view.rootModelNode());
700 if (rootNode.type() == "empty")
703 if (rootNode.id() == "designer__Selection") {
704 QList<ModelNode> selectedNodes = rootNode.allDirectSubModelNodes();
705 qDebug() << rootNode;
706 qDebug() << selectedNodes;
707 model->detachView(&view);
708 d->model->attachView(&view);
710 ModelNode targetNode;
712 if (!view.selectedModelNodes().isEmpty())
713 targetNode = view.selectedModelNodes().first();
715 //In case we copy and paste a selection we paste in the parent item
716 if ((view.selectedModelNodes().count() == selectedNodes.count()) && targetNode.isValid() && targetNode.parentProperty().isValid()) {
717 targetNode = targetNode.parentProperty().parentModelNode();
720 if (!targetNode.isValid())
721 targetNode = view.rootModelNode();
723 foreach (const ModelNode &node, selectedNodes) {
724 foreach (const ModelNode &node2, selectedNodes) {
725 if (node.isAncestorOf(node2))
726 selectedNodes.removeAll(node2);
730 QList<ModelNode> pastedNodeList;
733 RewriterTransaction transaction(d->formEditorView.data());
735 int offset = double(qrand()) / RAND_MAX * 20 - 10;
737 foreach (const ModelNode &node, selectedNodes) {
738 QString defaultProperty(targetNode.metaInfo().defaultPropertyName());
739 ModelNode pastedNode(view.insertModel(node));
740 pastedNodeList.append(pastedNode);
741 scatterItem(pastedNode, targetNode, offset);
742 targetNode.nodeListProperty(defaultProperty).reparentHere(pastedNode);
745 view.setSelectedModelNodes(pastedNodeList);
746 } catch (RewritingException &e) {
747 qWarning() << e.description(); //silent error
751 RewriterTransaction transaction(d->formEditorView.data());
753 model->detachView(&view);
754 d->model->attachView(&view);
755 ModelNode pastedNode(view.insertModel(rootNode));
756 ModelNode targetNode;
758 if (!view.selectedModelNodes().isEmpty())
759 targetNode = view.selectedModelNodes().first();
761 if (!targetNode.isValid())
762 targetNode = view.rootModelNode();
764 if (targetNode.parentProperty().isValid() &&
765 (pastedNode.simplifiedTypeName() == targetNode.simplifiedTypeName()) &&
766 (pastedNode.variantProperty("width").value() == targetNode.variantProperty("width").value()) &&
767 (pastedNode.variantProperty("height").value() == targetNode.variantProperty("height").value()))
769 targetNode = targetNode.parentProperty().parentModelNode();
771 QString defaultProperty(targetNode.metaInfo().defaultPropertyName());
773 scatterItem(pastedNode, targetNode);
774 if (targetNode.nodeListProperty(defaultProperty).isValid()) {
775 targetNode.nodeListProperty(defaultProperty).reparentHere(pastedNode);
778 transaction.commit();
779 NodeMetaInfo::clearCache();
781 view.setSelectedModelNodes(QList<ModelNode>() << pastedNode);
782 } catch (RewritingException &e) {
783 qWarning() << e.description(); //silent error
788 void DesignDocumentController::selectAll()
793 DesignDocumentControllerView view;
794 d->model->attachView(&view);
797 QList<ModelNode> allNodesExceptRootNode(view.allModelNodes());
798 allNodesExceptRootNode.removeOne(view.rootModelNode());
799 view.setSelectedModelNodes(allNodesExceptRootNode);
802 RewriterView *DesignDocumentController::rewriterView() const
804 return d->rewriterView.data();
807 void DesignDocumentController::undo()
809 if (d->rewriterView && !d->rewriterView->modificationGroupActive())
811 d->propertyEditorView->resetView();
814 void DesignDocumentController::redo()
816 if (d->rewriterView && !d->rewriterView->modificationGroupActive())
818 d->propertyEditorView->resetView();
821 static inline QtSupport::BaseQtVersion *getActiveQtVersion(DesignDocumentController *controller)
823 ProjectExplorer::ProjectExplorerPlugin *projectExplorer = ProjectExplorer::ProjectExplorerPlugin::instance();
824 ProjectExplorer::Project *currentProject = projectExplorer->currentProject();
829 controller->disconnect(controller, SLOT(activeQtVersionChanged()));
830 controller->connect(projectExplorer, SIGNAL(currentProjectChanged(ProjectExplorer::Project*)), controller, SLOT(activeQtVersionChanged()));
832 controller->connect(currentProject, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)), controller, SLOT(activeQtVersionChanged()));
835 ProjectExplorer::Target *target = currentProject->activeTarget();
840 ProjectExplorer::RunConfiguration *runConfiguration = target->activeRunConfiguration();
841 QmlProjectManager::QmlProjectRunConfiguration *qmlRunConfiguration = qobject_cast<QmlProjectManager::QmlProjectRunConfiguration* >(runConfiguration);
843 if (qmlRunConfiguration) {
844 controller->connect(target, SIGNAL(activeRunConfigurationChanged(ProjectExplorer::RunConfiguration*)), controller, SLOT(activeQtVersionChanged()));
845 return qmlRunConfiguration->qtVersion();
848 Qt4ProjectManager::Qt4BuildConfiguration *activeBuildConfiguration = qobject_cast<Qt4ProjectManager::Qt4BuildConfiguration *>(target->activeBuildConfiguration());
850 if (activeBuildConfiguration) {
851 controller->connect(target, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)), controller, SLOT(activeQtVersionChanged()));
852 return activeBuildConfiguration->qtVersion();
858 void DesignDocumentController::activeQtVersionChanged()
860 QtSupport::BaseQtVersion *newQtVersion = getActiveQtVersion(this);
862 if (!newQtVersion ) {
863 d->qt_versionId = -1;
867 if (d->qt_versionId == newQtVersion->uniqueId())
870 d->qt_versionId = newQtVersion->uniqueId();
872 if (d->nodeInstanceView)
873 d->nodeInstanceView->setPathToQt(pathToQt());
876 #ifdef ENABLE_TEXT_VIEW
877 void DesignDocumentController::showText()
879 d->stackedWidget->setCurrentWidget(d->textEdit.data());
881 #endif // ENABLE_TEXT_VIEW
883 #ifdef ENABLE_TEXT_VIEW
884 void DesignDocumentController::showForm()
886 d->stackedWidget->setCurrentWidget(d->formEditorView->widget());
888 #endif // ENABLE_TEXT_VIEW
890 bool DesignDocumentController::save(QWidget *parent)
892 // qDebug() << "Saving document to file \"" << d->fileName << "\"...";
894 if (d->fileName.isEmpty()) {
898 Utils::FileSaver saver(d->fileName, QIODevice::Text);
900 saver.write(d->textEdit->toPlainText().toLatin1());
901 if (!saver.finalize(parent ? parent : d->stackedWidget.data()))
904 d->textEdit->setPlainText(d->textEdit->toPlainText()); // clear undo/redo history
910 QString DesignDocumentController::contextHelpId() const
912 DesignDocumentControllerView view;
913 d->model->attachView(&view);
915 QList<ModelNode> nodes = view.selectedModelNodes();
917 if (!nodes.isEmpty()) {
918 helpId = nodes.first().type();
919 helpId.replace("QtQuick", "QML");
925 } // namespace QmlDesigner