Commit 7bb8f29c authored by Thomas Hartmann's avatar Thomas Hartmann
Browse files

QmlDesigner: all views instanciated once and shared now

parent 84598b45
......@@ -97,13 +97,11 @@ public:
QWeakPointer<SubComponentManager> subComponentManager;
QWeakPointer<Internal::ViewLogger> viewLogger;
QWeakPointer<QProcess> previewProcess;
QWeakPointer<QProcess> previewWithDebugProcess;
QString fileName;
QUrl searchPath;
bool documentLoaded;
bool syncBlocked;
QWeakPointer<ComponentAction> componentAction;
};
......@@ -117,39 +115,20 @@ DesignDocumentController::DesignDocumentController(QObject *parent) :
QObject(parent),
m_d(new DesignDocumentControllerPrivate)
{
m_d->itemLibrary = new ItemLibrary;
m_d->navigator = new NavigatorView(this);
m_d->allPropertiesBox = new AllPropertiesBox;
m_d->statesEditorWidget = new StatesEditorWidget;
m_d->stackedWidget = new QStackedWidget;
m_d->documentLoaded = false;
m_d->syncBlocked = false;
}
DesignDocumentController::~DesignDocumentController()
{
delete m_d->formEditorView.data();
// deleting the widgets should be safe because these are QWeakPointer's
delete m_d->itemLibrary.data();
delete m_d->allPropertiesBox.data();
delete m_d->statesEditorWidget.data();
delete m_d->stackedWidget.data();
{
delete m_d->model.data();
delete m_d->subComponentModel.data();
delete m_d->rewriterView.data();
// m_d->textEdit is child of stackedWidget or owned by external widget
delete m_d->textModifier;
if (m_d->componentTextModifier) //componentTextModifier might not be created
delete m_d->componentTextModifier;
delete m_d->previewProcess.data();
delete m_d->previewWithDebugProcess.data();
delete m_d;
}
......@@ -163,76 +142,11 @@ Model *DesignDocumentController::masterModel() const
return m_d->masterModel.data();
}
QWidget *DesignDocumentController::documentWidget() const
{
return m_d->stackedWidget.data();
}
void DesignDocumentController::togglePreview(bool visible)
{
if (!m_d->documentLoaded)
return;
if (visible) {
Q_ASSERT(!m_d->previewProcess);
QString directory;
if (!m_d->fileName.isEmpty()) {
directory = QFileInfo(m_d->fileName).absoluteDir().path();
} else {
directory = QDir::tempPath();
}
m_d->previewProcess = createPreviewProcess(directory);
connect(m_d->previewProcess.data(), SIGNAL(finished(int, QProcess::ExitStatus)),
this, SLOT(emitPreviewVisibilityChanged()));
} else {
Q_ASSERT(m_d->previewProcess);
delete m_d->previewProcess.data();
}
}
void DesignDocumentController::toggleWithDebugPreview(bool visible)
{
if (!m_d->documentLoaded)
return;
if (visible) {
Q_ASSERT(!m_d->previewWithDebugProcess);
QString directory;
if (!m_d->fileName.isEmpty()) {
directory = QFileInfo(m_d->fileName).absoluteDir().path();
} else {
directory = QDir::tempPath();
}
m_d->previewWithDebugProcess = createPreviewWithDebugProcess(directory);
connect(m_d->previewWithDebugProcess.data(), SIGNAL(finished(int, QProcess::ExitStatus)),
this, SLOT(emitPreviewWithDebugVisibilityChanged()));
} else {
Q_ASSERT(m_d->previewWithDebugProcess);
delete m_d->previewWithDebugProcess.data();
}
}
bool DesignDocumentController::previewVisible() const
{
if (!m_d->documentLoaded)
return false;
return m_d->previewProcess;
}
bool DesignDocumentController::previewWithDebugVisible() const
QWidget *DesignDocumentController::widget() const
{
if (!m_d->documentLoaded)
return false;
return m_d->previewWithDebugProcess;
return qobject_cast<QWidget*>(parent());
}
/*!
Returns whether the model is automatically updated if the text editor changes.
*/
......@@ -272,14 +186,29 @@ QList<RewriterView::Error> DesignDocumentController::qmlErrors() const
return m_d->rewriterView->errors();
}
void DesignDocumentController::emitPreviewVisibilityChanged()
void DesignDocumentController::setItemLibrary(ItemLibrary* itemLibrary)
{
m_d->itemLibrary = itemLibrary;
}
void DesignDocumentController::setNavigator(NavigatorView* navigatorView)
{
m_d->navigator = navigatorView;
}
void DesignDocumentController::setAllPropertiesBox(AllPropertiesBox* allPropertiesBox)
{
m_d->allPropertiesBox = allPropertiesBox;
}
void DesignDocumentController::setStatesEditorWidget(StatesEditorWidget* statesEditorWidget)
{
emit previewVisibilityChanged(false);
m_d->statesEditorWidget = statesEditorWidget;
}
void DesignDocumentController::emitPreviewWithDebugVisibilityChanged()
void DesignDocumentController::setFormEditorView(FormEditorView *formEditorView)
{
emit previewWithDebugVisibilityChanged(false);
m_d->formEditorView = formEditorView;
}
QString DesignDocumentController::displayName() const
......@@ -411,21 +340,21 @@ void DesignDocumentController::loadCurrentModel()
Q_ASSERT(m_d->model);
m_d->model->setMasterModel(m_d->masterModel.data());
m_d->allPropertiesBox->setModel(m_d->model.data());
m_d->model->attachView(m_d->navigator.data());
m_d->itemLibrary->setMetaInfo(m_d->model->metaInfo());
if (m_d->formEditorView.isNull()) {
m_d->formEditorView = new FormEditorView(this);
m_d->stackedWidget->addWidget(m_d->formEditorView->widget());
ComponentAction *componentAction = new ComponentAction(m_d->formEditorView->widget());
componentAction->setModel(m_d->model.data());
// TODO: Enable again
//m_d->formEditorView->widget()->lowerToolBox()->addAction(componentAction);
connect(componentAction, SIGNAL(currentComponentChanged(ModelNode)), SLOT(changeCurrentModelTo(ModelNode))); //TODO component action
connect(m_d->itemLibrary.data(), SIGNAL(itemActivated(const QString&)), m_d->formEditorView.data(), SLOT(activateItemCreator(const QString&)));
if (!m_d->componentAction) {
m_d->componentAction = new ComponentAction(m_d->formEditorView->widget());
m_d->componentAction->setModel(m_d->model.data());
connect(m_d->componentAction.data(), SIGNAL(currentComponentChanged(ModelNode)), SLOT(changeCurrentModelTo(ModelNode)));
m_d->formEditorView->widget()->lowerToolBox()->addAction(m_d->componentAction.data());
}
foreach (QAction *action , m_d->formEditorView->widget()->lowerToolBox()->actions())
if (qobject_cast<ComponentAction*>(action))
action->setVisible(false);
m_d->componentAction->setVisible(true);
connect(m_d->itemLibrary.data(), SIGNAL(itemActivated(const QString&)), m_d->formEditorView.data(), SLOT(activateItemCreator(const QString&)));
m_d->model->attachView(m_d->formEditorView.data());
......@@ -436,6 +365,8 @@ void DesignDocumentController::loadCurrentModel()
// Will call setCurrentState (formEditorView etc has to be constructed first)
m_d->statesEditorWidget->setup(m_d->model.data());
m_d->allPropertiesBox->setModel(m_d->model.data());
m_d->documentLoaded = true;
Q_ASSERT(m_d->masterModel);
}
......@@ -461,13 +392,13 @@ void DesignDocumentController::doRealSaveAs(const QString &fileName)
QFileInfo fileInfo(fileName);
if (fileInfo.exists() && !fileInfo.isWritable()) {
QMessageBox msgBox(documentWidget());
QMessageBox msgBox(widget());
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(documentWidget());
QMessageBox msgBox(widget());
msgBox.setIcon(QMessageBox::Warning);
msgBox.setText(tr("Parent folder \"%1\" for file \"%2\" does not exist.")
.arg(fileInfo.dir().dirName())
......@@ -477,28 +408,7 @@ void DesignDocumentController::doRealSaveAs(const QString &fileName)
}
setFileName(fileName);
save(documentWidget());
}
bool DesignDocumentController::save(QWidget *parent)
{
// qDebug() << "Saving document to file \"" << m_d->fileName << "\"...";
//
if (m_d->fileName.isEmpty()) {
saveAs(parent);
return true;
}
QFile file(m_d->fileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
showError(tr("Cannot write file: \"%1\".").arg(m_d->fileName), parent);
return false;
}
QString errorMessage;
bool result = save(&file, &errorMessage);
if (!result)
showError(errorMessage, parent);
return result;
save(widget());
}
bool DesignDocumentController::isDirty() const
......@@ -511,17 +421,21 @@ bool DesignDocumentController::isDirty() const
bool DesignDocumentController::isUndoAvailable() const
{
return m_d->textEdit->document()->isUndoAvailable();
if (m_d->textEdit)
return m_d->textEdit->document()->isUndoAvailable();
return false;
}
bool DesignDocumentController::isRedoAvailable() const
{
return m_d->textEdit->document()->isRedoAvailable();
if (m_d->textEdit)
return m_d->textEdit->document()->isRedoAvailable();
return false;
}
void DesignDocumentController::close()
{
documentWidget()->close();
m_d->documentLoaded = false;
emit designDocumentClosed();
}
......@@ -752,26 +666,6 @@ void DesignDocumentController::showError(const QString &message, QWidget *parent
msgBox.exec();
}
QWidget *DesignDocumentController::itemLibrary() const
{
return m_d->itemLibrary.data();
}
QWidget *DesignDocumentController::navigator() const
{
return m_d->navigator->widget();
}
QWidget *DesignDocumentController::allPropertiesBox() const
{
return m_d->allPropertiesBox.data();
}
QWidget *DesignDocumentController::statesEditorWidget() const
{
return m_d->statesEditorWidget.data();
}
RewriterView *DesignDocumentController::rewriterView() const
{
return m_d->rewriterView.data();
......@@ -803,79 +697,26 @@ void DesignDocumentController::showForm()
}
#endif // ENABLE_TEXT_VIEW
QProcess *DesignDocumentController::createPreviewProcess(const QString &dirPath)
{
Q_ASSERT(QDir(dirPath).exists());
QProcess *previewProcess = new QProcess(this);
previewProcess->setWorkingDirectory(dirPath);
QTemporaryFile *temporaryFile = new QTemporaryFile(QDir(dirPath).absoluteFilePath("bauhaus_tmp"));
temporaryFile->setParent(previewProcess);
temporaryFile->open();
m_d->textModifier->save(temporaryFile);
QStringList qmlViewerArgumentList;
// qmlViewerArgumentList.append("-L");
// qmlViewerArgumentList.append(dirPath);
previewProcess->setWorkingDirectory(dirPath);
qmlViewerArgumentList.append(temporaryFile->fileName());
temporaryFile->close();
previewProcess->start(QString("%1/qml").arg(QCoreApplication::applicationDirPath()), qmlViewerArgumentList);
if (!previewProcess->waitForStarted())
previewProcess->start("qml", qmlViewerArgumentList);
if (!previewProcess->waitForStarted())
QMessageBox::warning(documentWidget(), "qml runtime not found", "qml runtime should be in the PATH or in the same directory like the bauhaus binary.");
return previewProcess;
}
QProcess *DesignDocumentController::createPreviewWithDebugProcess(const QString &dirPath)
bool DesignDocumentController::save(QWidget *parent)
{
Q_ASSERT(QDir(dirPath).exists());
QProcess *previewProcess = new QProcess(this);
previewProcess->setWorkingDirectory(dirPath);
QProcess *debugger = new QProcess(previewProcess);
QTemporaryFile *temporaryFile = new QTemporaryFile(QDir(dirPath).absoluteFilePath("bauhaus_tmp"));
temporaryFile->setParent(previewProcess);
temporaryFile->open();
m_d->textModifier->save(temporaryFile);
QStringList environmentList = QProcess::systemEnvironment();
environmentList.append("QML_DEBUG_SERVER_PORT=3768");
previewProcess->setEnvironment(environmentList);
QStringList qmlViewerArgumentList;
// qmlViewerArgumentList.append("-L");
// qmlViewerArgumentList.append(libraryPath);
qmlViewerArgumentList.append(temporaryFile->fileName());
temporaryFile->close();
debugger->setWorkingDirectory(dirPath);
debugger->start(QString("%1/qmldebugger").arg(QCoreApplication::applicationDirPath()));
if (!debugger->waitForStarted())
debugger->start("qmldebugger", qmlViewerArgumentList);
if (!debugger->waitForStarted())
QMessageBox::warning(documentWidget(), "qmldebugger not found", "qmldebugger should in the PATH or in the same directory like the bauhaus binary.");
previewProcess->setWorkingDirectory(dirPath);
previewProcess->start(QString("%1/qml").arg(QCoreApplication::applicationDirPath()), qmlViewerArgumentList);
if (!previewProcess->waitForStarted())
previewProcess->start("qml", qmlViewerArgumentList);
if (!previewProcess->waitForStarted())
QMessageBox::warning(documentWidget(), "qml runtime not found", "qml runtime should in the PATH or in the same directory like the bauhaus binary.");
// qDebug() << "Saving document to file \"" << m_d->fileName << "\"...";
//
if (m_d->fileName.isEmpty()) {
saveAs(parent);
return true;
}
QFile file(m_d->fileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
showError(tr("Cannot write file: \"%1\".").arg(m_d->fileName), parent);
return false;
}
return previewProcess;
QString errorMessage;
bool result = save(&file, &errorMessage);
if (!result)
showError(errorMessage, parent);
return result;
save(widget());
}
bool DesignDocumentController::save(QIODevice *device, QString * /*errorMessage*/)
......@@ -884,12 +725,11 @@ bool DesignDocumentController::save(QIODevice *device, QString * /*errorMessage*
QByteArray data = m_d->textEdit->toPlainText().toLatin1();
device->write(data);
m_d->textEdit->setPlainText(data); // clear undo/redo history
return true;
} else {
return false;
}
return false;
}
QString DesignDocumentController::contextHelpId() const
{
DesignDocumentControllerView view;
......
......@@ -51,6 +51,11 @@ class ModelNode;
class TextModifier;
class QmlObjectNode;
class RewriterView;
class ItemLibrary;
class NavigatorView;
class AllPropertiesBox;
class StatesEditorWidget;
class FormEditorView;
class DesignDocumentController: public QObject
{
......@@ -72,20 +77,12 @@ public:
bool isDirty() const;
bool isUndoAvailable() const;
bool isRedoAvailable() const;
QWidget *widget() const;
Model *model() const;
Model *masterModel() const;
Model *masterModel() const;
QWidget *documentWidget() const;
QWidget *itemLibrary() const;
QWidget *navigator() const;
QWidget *allPropertiesBox() const;
QWidget *statesEditorWidget() const;
RewriterView *rewriterView() const;
bool previewVisible() const;
bool previewWithDebugVisible() const;
RewriterView *rewriterView() const;
bool isModelSyncBlocked() const;
void blockModelSync(bool block);
......@@ -93,14 +90,18 @@ public:
QString contextHelpId() const;
QList<RewriterView::Error> qmlErrors() const;
void setItemLibrary(ItemLibrary* itemLibrary);
void setNavigator(NavigatorView* navigatorView);
void setAllPropertiesBox(AllPropertiesBox* allPropertiesBox);
void setStatesEditorWidget(StatesEditorWidget* statesEditorWidget);
void setFormEditorView(FormEditorView *formEditorView);
signals:
void displayNameChanged(const QString &newFileName);
void dirtyStateChanged(bool newState);
void undoAvailable(bool isAvailable);
void redoAvailable(bool isAvailable);
void previewVisibilityChanged(bool visible);
void previewWithDebugVisibilityChanged(bool visible);
void designDocumentClosed();
void qmlErrorsChanged(const QList<RewriterView::Error> &errors);
......@@ -108,18 +109,12 @@ signals:
public slots:
bool save(QWidget *parent = 0);
void saveAs(QWidget *parent = 0);
void saveAs(QWidget *parent = 0);
void deleteSelected();
void copySelected();
void cutSelected();
void paste();
void selectAll();
void togglePreview(bool visible);
void toggleWithDebugPreview(bool visible);
void emitPreviewVisibilityChanged();
void emitPreviewWithDebugVisibilityChanged();
void undo();
void redo();
......@@ -134,11 +129,8 @@ private slots:
void changeCurrentModelTo(const ModelNode &node);
private:
QProcess *createPreviewProcess(const QString &dirPath);
QProcess *createPreviewWithDebugProcess(const QString &dirPath);
bool save(QIODevice *device, QString *errorMessage);
class DesignDocumentControllerPrivate *m_d;
bool save(QIODevice *device, QString *errorMessage);
};
} // namespace QmlDesigner
......
......@@ -40,8 +40,10 @@
#include <designdocumentcontroller.h>
#include <itemlibrary.h>
#include <navigatorwidget.h>
#include <navigatorview.h>
#include <stateseditorwidget.h>
#include <modelnode.h>
#include <formeditorview.h>
#include <QWeakPointer>
......@@ -78,7 +80,7 @@ class DocumentWarningWidget : public QFrame
Q_OBJECT
Q_DISABLE_COPY(DocumentWarningWidget)
public:
explicit DocumentWarningWidget(DocumentWidget *documentWidget, QWidget *parent = 0);
explicit DocumentWarningWidget(DesignModeWidget *parent = 0);
void setError(const RewriterView::Error &error);
......@@ -88,52 +90,8 @@ private slots:
private:
QLabel *m_errorMessage;
QLabel *m_goToError;
DocumentWidget *m_documentWidget;
RewriterView::Error m_error;
};
class DocumentWidget : public QWidget
{
Q_OBJECT
Q_DISABLE_COPY(DocumentWidget)
public:
explicit DocumentWidget(TextEditor::ITextEditor *textEditor, QPlainTextEdit *textEdit, QmlDesigner::DesignDocumentController *document, DesignModeWidget *mainWidget);
~DocumentWidget();
QmlDesigner::DesignDocumentController *document() const;
TextEditor::ITextEditor *textEditor() const;
void setAutoSynchronization(bool sync);
void readSettings();
void saveSettings();
protected:
void resizeEvent(QResizeEvent *event);
private slots:
void enable();
void disable(const QList<RewriterView::Error> &errors);
void updateErrorStatus(const QList<RewriterView::Error> &errors);
private:
void setup();
bool isInNodeDefinition(int nodeOffset, int nodeLength, int cursorPos) const;
QmlDesigner::ModelNode nodeForPosition(int cursorPos) const;
TextEditor::ITextEditor *m_textEditor;
QWeakPointer<QPlainTextEdit> m_textBuffer;
QmlDesigner::DesignDocumentController *m_document;
DesignModeWidget *m_mainWidget;
QSplitter *m_mainSplitter;
Core::SideBar *m_leftSideBar;
Core::SideBar *m_rightSideBar;
QToolBar *m_designToolBar;
Core::EditorToolBar *m_fakeToolBar;
bool m_isDisabled;
DocumentWarningWidget *m_warningWidget;
DesignModeWidget *m_designModeWidget;
};
class DesignModeWidget : public QWidget
......@@ -144,8 +102,6 @@ public:
explicit DesignModeWidget(QWidget *parent = 0);
~DesignModeWidget();
// void syncWithTextEdit(bool sync);