forked from qt-creator/qt-creator
QmlDesigner: all views instanciated once and shared now
This commit is contained in:
@@ -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
|
||||
QWidget *DesignDocumentController::widget() const
|
||||
{
|
||||
return m_d->stackedWidget.data();
|
||||
return qobject_cast<QWidget*>(parent());
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
if (!m_d->documentLoaded)
|
||||
return false;
|
||||
|
||||
return m_d->previewWithDebugProcess;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
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)
|
||||
{
|
||||
emit previewVisibilityChanged(false);
|
||||
m_d->itemLibrary = itemLibrary;
|
||||
}
|
||||
|
||||
void DesignDocumentController::emitPreviewWithDebugVisibilityChanged()
|
||||
void DesignDocumentController::setNavigator(NavigatorView* navigatorView)
|
||||
{
|
||||
emit previewWithDebugVisibilityChanged(false);
|
||||
m_d->navigator = navigatorView;
|
||||
}
|
||||
|
||||
void DesignDocumentController::setAllPropertiesBox(AllPropertiesBox* allPropertiesBox)
|
||||
{
|
||||
m_d->allPropertiesBox = allPropertiesBox;
|
||||
}
|
||||
|
||||
void DesignDocumentController::setStatesEditorWidget(StatesEditorWidget* statesEditorWidget)
|
||||
{
|
||||
m_d->statesEditorWidget = statesEditorWidget;
|
||||
}
|
||||
|
||||
void DesignDocumentController::setFormEditorView(FormEditorView *formEditorView)
|
||||
{
|
||||
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
|
||||
{
|
||||
|
||||
if (m_d->textEdit)
|
||||
return m_d->textEdit->document()->isUndoAvailable();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DesignDocumentController::isRedoAvailable() const
|
||||
{
|
||||
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)
|
||||
bool DesignDocumentController::save(QWidget *parent)
|
||||
{
|
||||
Q_ASSERT(QDir(dirPath).exists());
|
||||
// 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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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.");
|
||||
|
||||
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,35 +77,31 @@ public:
|
||||
bool isDirty() const;
|
||||
bool isUndoAvailable() const;
|
||||
bool isRedoAvailable() const;
|
||||
QWidget *widget() const;
|
||||
|
||||
Model *model() 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;
|
||||
|
||||
bool isModelSyncBlocked() const;
|
||||
void blockModelSync(bool block);
|
||||
|
||||
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);
|
||||
|
||||
@@ -114,12 +115,6 @@ public slots:
|
||||
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
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include <model.h>
|
||||
#include <rewriterview.h>
|
||||
#include <formeditorwidget.h>
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/minisplitter.h>
|
||||
@@ -41,6 +42,8 @@
|
||||
#include <coreplugin/editormanager/ieditor.h>
|
||||
#include <coreplugin/modemanager.h>
|
||||
#include <coreplugin/editortoolbar.h>
|
||||
#include <coreplugin/inavigationwidgetfactory.h>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
#include <utils/parameteraction.h>
|
||||
#include <utils/qtcassert.h>
|
||||
@@ -57,6 +60,7 @@
|
||||
#include <QtGui/QMenu>
|
||||
#include <QtGui/QClipboard>
|
||||
#include <QtGui/QLabel>
|
||||
#include <QtGui/QProgressDialog>
|
||||
|
||||
using Core::MiniSplitter;
|
||||
using Core::IEditor;
|
||||
@@ -73,11 +77,11 @@ enum {
|
||||
namespace QmlDesigner {
|
||||
namespace Internal {
|
||||
|
||||
DocumentWarningWidget::DocumentWarningWidget(DocumentWidget *documentWidget, QWidget *parent) :
|
||||
DocumentWarningWidget::DocumentWarningWidget(DesignModeWidget *parent) :
|
||||
QFrame(parent),
|
||||
m_errorMessage(new QLabel("Placeholder", this)),
|
||||
m_goToError(new QLabel(this)),
|
||||
m_documentWidget(documentWidget)
|
||||
m_designModeWidget(parent)
|
||||
{
|
||||
setFrameStyle(QFrame::Panel | QFrame::Raised);
|
||||
setLineWidth(1);
|
||||
@@ -108,264 +112,20 @@ void DocumentWarningWidget::setError(const RewriterView::Error &error)
|
||||
|
||||
void DocumentWarningWidget::goToError()
|
||||
{
|
||||
m_documentWidget->textEditor()->gotoLine(m_error.line(), m_error.column());
|
||||
m_designModeWidget->textEditor()->gotoLine(m_error.line(), m_error.column());
|
||||
Core::EditorManager::instance()->ensureEditorManagerVisible();
|
||||
}
|
||||
|
||||
DocumentWidget::DocumentWidget(TextEditor::ITextEditor *textEditor, QPlainTextEdit *textEdit, QmlDesigner::DesignDocumentController *document, DesignModeWidget *mainWidget) :
|
||||
QWidget(),
|
||||
m_textEditor(textEditor),
|
||||
m_textBuffer(textEdit),
|
||||
m_document(document),
|
||||
m_mainWidget(mainWidget),
|
||||
m_mainSplitter(0),
|
||||
m_leftSideBar(0),
|
||||
m_rightSideBar(0),
|
||||
m_designToolBar(new QToolBar),
|
||||
m_fakeToolBar(Core::EditorManager::createToolBar(this)),
|
||||
m_isDisabled(false),
|
||||
m_warningWidget(0)
|
||||
{
|
||||
setup();
|
||||
}
|
||||
|
||||
DocumentWidget::~DocumentWidget()
|
||||
{
|
||||
// Make sure component widgets are deleted first in SideBarItem::~SideBarItem
|
||||
// before the DesignDocumentController runs (and deletes them again).
|
||||
m_document->deleteLater();
|
||||
}
|
||||
|
||||
QmlDesigner::DesignDocumentController *DocumentWidget::document() const
|
||||
{
|
||||
return m_document;
|
||||
}
|
||||
|
||||
TextEditor::ITextEditor *DocumentWidget::textEditor() const
|
||||
{
|
||||
return m_textEditor;
|
||||
}
|
||||
|
||||
void DocumentWidget::setAutoSynchronization(bool sync)
|
||||
{
|
||||
if (debug)
|
||||
qDebug() << Q_FUNC_INFO << sync;
|
||||
|
||||
document()->blockModelSync(!sync);
|
||||
|
||||
if (sync) {
|
||||
// text editor -> visual editor
|
||||
if (!document()->model()) {
|
||||
document()->loadMaster(m_textBuffer.data());
|
||||
}
|
||||
|
||||
QList<RewriterView::Error> errors = document()->qmlErrors();
|
||||
if (errors.isEmpty()) {
|
||||
// set selection to text cursor
|
||||
RewriterView *rewriter = document()->rewriterView();
|
||||
const int cursorPos = m_textBuffer->textCursor().position();
|
||||
ModelNode node = nodeForPosition(cursorPos);
|
||||
if (node.isValid()) {
|
||||
rewriter->setSelectedModelNodes(QList<ModelNode>() << node);
|
||||
}
|
||||
enable();
|
||||
} else {
|
||||
disable(errors);
|
||||
}
|
||||
|
||||
connect(document(), SIGNAL(qmlErrorsChanged(QList<RewriterView::Error>)),
|
||||
this, SLOT(updateErrorStatus(QList<RewriterView::Error>)));
|
||||
|
||||
} else {
|
||||
if (document()->model() && document()->qmlErrors().isEmpty()) {
|
||||
RewriterView *rewriter = document()->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_textBuffer->textCursor().position());
|
||||
if (currentSelectedNode != selectedNode) {
|
||||
int line, column;
|
||||
textEditor()->convertPosition(nodeOffset, &line, &column);
|
||||
textEditor()->gotoLine(line, column);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
disconnect(document(), SIGNAL(qmlErrorsChanged(QList<RewriterView::Error>)),
|
||||
this, SLOT(updateErrorStatus(QList<RewriterView::Error>)));
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentWidget::enable()
|
||||
{
|
||||
if (debug)
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
m_warningWidget->setVisible(false);
|
||||
m_document->documentWidget()->setEnabled(true);
|
||||
m_document->statesEditorWidget()->setEnabled(true);
|
||||
m_leftSideBar->setEnabled(true);
|
||||
m_rightSideBar->setEnabled(true);
|
||||
m_isDisabled = false;
|
||||
}
|
||||
|
||||
void DocumentWidget::disable(const QList<RewriterView::Error> &errors)
|
||||
{
|
||||
if (debug)
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
Q_ASSERT(!errors.isEmpty());
|
||||
m_warningWidget->setError(errors.first());
|
||||
m_warningWidget->setVisible(true);
|
||||
m_document->documentWidget()->setEnabled(false);
|
||||
m_document->statesEditorWidget()->setEnabled(false);
|
||||
m_leftSideBar->setEnabled(false);
|
||||
m_rightSideBar->setEnabled(false);
|
||||
m_isDisabled = true;
|
||||
}
|
||||
|
||||
void DocumentWidget::updateErrorStatus(const QList<RewriterView::Error> &errors)
|
||||
{
|
||||
if (debug)
|
||||
qDebug() << Q_FUNC_INFO << errors.count();
|
||||
|
||||
if (m_isDisabled && errors.isEmpty()) {
|
||||
enable();
|
||||
} else if (!errors.isEmpty()) {
|
||||
disable(errors);
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentWidget::readSettings()
|
||||
{
|
||||
QSettings *settings = Core::ICore::instance()->settings();
|
||||
|
||||
settings->beginGroup("Bauhaus");
|
||||
m_leftSideBar->readSettings(settings, QLatin1String("LeftSideBar"));
|
||||
m_rightSideBar->readSettings(settings, QLatin1String("RightSideBar"));
|
||||
if (settings->contains("MainSplitter")) {
|
||||
const QByteArray splitterState = settings->value("MainSplitter").toByteArray();
|
||||
m_mainSplitter->restoreState(splitterState);
|
||||
}
|
||||
settings->endGroup();
|
||||
}
|
||||
|
||||
void DocumentWidget::saveSettings()
|
||||
{
|
||||
QSettings *settings = Core::ICore::instance()->settings();
|
||||
|
||||
settings->beginGroup("Bauhaus");
|
||||
m_leftSideBar->saveSettings(settings, QLatin1String("LeftSideBar"));
|
||||
m_rightSideBar->saveSettings(settings, QLatin1String("RightSideBar"));
|
||||
settings->setValue("MainSplitter", m_mainSplitter->saveState());
|
||||
settings->endGroup();
|
||||
}
|
||||
|
||||
|
||||
void DocumentWidget::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
m_warningWidget->move(QPoint(event->size().width() / 2,
|
||||
event->size().height() / 2));
|
||||
QWidget::resizeEvent(event);
|
||||
}
|
||||
|
||||
void DocumentWidget::setup()
|
||||
{
|
||||
m_mainSplitter = new MiniSplitter(this);
|
||||
m_mainSplitter->setObjectName("mainSplitter");
|
||||
|
||||
// warning frame should be not in layout, but still child of the widget
|
||||
m_warningWidget = new DocumentWarningWidget(this, this);
|
||||
m_warningWidget->setVisible(false);
|
||||
|
||||
// Left area:
|
||||
Core::SideBarItem *navigatorItem = new Core::SideBarItem(m_document->navigator());
|
||||
Core::SideBarItem *libraryItem = new Core::SideBarItem(m_document->itemLibrary());
|
||||
Core::SideBarItem *propertiesItem = new Core::SideBarItem(m_document->allPropertiesBox());
|
||||
|
||||
QList<Core::SideBarItem*> leftSideBarItems, rightSideBarItems;
|
||||
leftSideBarItems << navigatorItem << libraryItem;
|
||||
rightSideBarItems << propertiesItem;
|
||||
|
||||
m_leftSideBar = new Core::SideBar(leftSideBarItems, QList<Core::SideBarItem*>() << navigatorItem << libraryItem);
|
||||
m_rightSideBar = new Core::SideBar(rightSideBarItems, QList<Core::SideBarItem*>() << propertiesItem);
|
||||
|
||||
m_designToolBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored);
|
||||
|
||||
m_fakeToolBar->setToolbarCreationFlags(Core::EditorToolBar::FlagsStandalone);
|
||||
m_fakeToolBar->addEditor(textEditor());
|
||||
m_fakeToolBar->addCenterToolBar(m_designToolBar);
|
||||
m_fakeToolBar->setNavigationVisible(false);
|
||||
|
||||
// right area:
|
||||
QWidget *centerWidget = new QWidget;
|
||||
{
|
||||
QVBoxLayout *rightLayout = new QVBoxLayout(centerWidget);
|
||||
rightLayout->setMargin(0);
|
||||
rightLayout->setSpacing(0);
|
||||
rightLayout->addWidget(m_fakeToolBar);
|
||||
rightLayout->addWidget(m_document->statesEditorWidget());
|
||||
rightLayout->addWidget(m_document->documentWidget());
|
||||
}
|
||||
|
||||
// m_mainSplitter area:
|
||||
m_mainSplitter->addWidget(m_leftSideBar);
|
||||
m_mainSplitter->addWidget(centerWidget);
|
||||
m_mainSplitter->addWidget(m_rightSideBar);
|
||||
|
||||
// Finishing touches:
|
||||
m_mainSplitter->setOpaqueResize(false);
|
||||
m_mainSplitter->setStretchFactor(1, 1);
|
||||
m_mainSplitter->setSizes(QList<int>() << 150 << 300 << 150);
|
||||
|
||||
QLayout *mainLayout = new QBoxLayout(QBoxLayout::RightToLeft, this);
|
||||
mainLayout->setMargin(0);
|
||||
mainLayout->setSpacing(0);
|
||||
mainLayout->addWidget(m_mainSplitter);
|
||||
}
|
||||
|
||||
bool DocumentWidget::isInNodeDefinition(int nodeOffset, int nodeLength, int cursorPos) const {
|
||||
return (nodeOffset <= cursorPos) && (nodeOffset + nodeLength > cursorPos);
|
||||
}
|
||||
|
||||
ModelNode DocumentWidget::nodeForPosition(int cursorPos) const
|
||||
{
|
||||
RewriterView *rewriter = m_document->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;
|
||||
}
|
||||
|
||||
// ---------- DesignModeWidget
|
||||
DesignModeWidget::DesignModeWidget(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
m_documentWidgetStack(new QStackedWidget),
|
||||
m_currentDocumentWidget(0),
|
||||
m_currentTextEdit(0),
|
||||
m_syncWithTextEdit(false)
|
||||
m_syncWithTextEdit(false),
|
||||
m_mainSplitter(0),
|
||||
m_leftSideBar(0),
|
||||
m_rightSideBar(0),
|
||||
m_setup(false),
|
||||
m_warningWidget(0)
|
||||
{
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
layout->setMargin(0);
|
||||
layout->addWidget(m_documentWidgetStack);
|
||||
|
||||
m_undoAction = new QAction(tr("&Undo"), this);
|
||||
connect(m_undoAction, SIGNAL(triggered()), this, SLOT(undo()));
|
||||
m_redoAction = new QAction(tr("&Redo"), this);
|
||||
@@ -380,11 +140,6 @@ DesignModeWidget::DesignModeWidget(QWidget *parent) :
|
||||
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()));
|
||||
|
||||
QLabel *defaultBackground = new QLabel(tr("Loading ..."));
|
||||
defaultBackground->setAlignment(Qt::AlignCenter);
|
||||
|
||||
m_documentWidgetStack->addWidget(defaultBackground);
|
||||
}
|
||||
|
||||
DesignModeWidget::~DesignModeWidget()
|
||||
@@ -393,6 +148,9 @@ DesignModeWidget::~DesignModeWidget()
|
||||
|
||||
void DesignModeWidget::showEditor(Core::IEditor *editor)
|
||||
{
|
||||
show();
|
||||
setup();
|
||||
|
||||
QString fileName;
|
||||
QPlainTextEdit *textEdit = 0;
|
||||
TextEditor::ITextEditor *textEditor = 0;
|
||||
@@ -401,49 +159,52 @@ void DesignModeWidget::showEditor(Core::IEditor *editor)
|
||||
fileName = editor->file()->fileName();
|
||||
textEdit = qobject_cast<QPlainTextEdit*>(editor->widget());
|
||||
textEditor = qobject_cast<TextEditor::ITextEditor*>(editor);
|
||||
m_fakeToolBar->addEditor(textEditor);
|
||||
}
|
||||
|
||||
if (debug)
|
||||
qDebug() << Q_FUNC_INFO << fileName;
|
||||
|
||||
if (textEdit)
|
||||
m_currentTextEdit = textEdit;
|
||||
DocumentWidget *documentWidget = 0;
|
||||
|
||||
if (textEditor)
|
||||
m_textEditor = textEditor;
|
||||
DesignDocumentController *document = 0;
|
||||
|
||||
if (textEdit && textEditor && fileName.endsWith(QLatin1String(".qml"))) {
|
||||
if (m_documentHash.contains(textEdit)) {
|
||||
documentWidget = m_documentHash.value(textEdit);
|
||||
document = m_documentHash.value(textEdit).data();
|
||||
} else {
|
||||
DesignDocumentController *newDocument = new DesignDocumentController(0);
|
||||
DesignDocumentController *newDocument = new DesignDocumentController(this);
|
||||
|
||||
newDocument->setAllPropertiesBox(m_allPropertiesBox.data());
|
||||
newDocument->setNavigator(m_navigator.data());
|
||||
newDocument->setStatesEditorWidget(m_statesEditorWidget.data());
|
||||
newDocument->setItemLibrary(m_itemLibrary.data());
|
||||
newDocument->setFormEditorView(m_formEditorView.data());
|
||||
|
||||
newDocument->setFileName(fileName);
|
||||
|
||||
documentWidget = new DocumentWidget(textEditor, textEdit, newDocument, this);
|
||||
connect(documentWidget->document(), SIGNAL(undoAvailable(bool)),
|
||||
this, SLOT(undoAvailable(bool)));
|
||||
connect(documentWidget->document(), SIGNAL(redoAvailable(bool)),
|
||||
this, SLOT(redoAvailable(bool)));
|
||||
// connect(documentWidget->document(), SIGNAL(deleteAvailable(bool)),
|
||||
// this, SLOT(deleteAvailable(bool)));
|
||||
document = newDocument;
|
||||
|
||||
m_documentHash.insert(textEdit, documentWidget);
|
||||
m_documentWidgetStack->addWidget(documentWidget);
|
||||
m_documentHash.insert(textEdit, document);
|
||||
}
|
||||
}
|
||||
|
||||
setCurrentDocumentWidget(documentWidget);
|
||||
setCurrentDocument(document);
|
||||
}
|
||||
|
||||
void DesignModeWidget::closeEditors(QList<Core::IEditor*> editors)
|
||||
{
|
||||
foreach (Core::IEditor* editor, editors) {
|
||||
if (QPlainTextEdit *textEdit = qobject_cast<QPlainTextEdit*>(editor->widget())) {
|
||||
if (m_currentTextEdit == textEdit) {
|
||||
setCurrentDocumentWidget(0);
|
||||
if (m_currentTextEdit.data() == textEdit) {
|
||||
setCurrentDocument(0);
|
||||
}
|
||||
if (m_documentHash.contains(textEdit)) {
|
||||
if (debug)
|
||||
qDebug() << Q_FUNC_INFO << editor->file()->fileName();
|
||||
DocumentWidget *document = m_documentHash.take(textEdit);
|
||||
m_documentWidgetStack->removeWidget(document);
|
||||
DesignDocumentController *document = m_documentHash.take(textEdit).data();
|
||||
delete document;
|
||||
}
|
||||
}
|
||||
@@ -485,53 +246,82 @@ QAction *DesignModeWidget::selectAllAction() const
|
||||
return m_selectAllAction;
|
||||
}
|
||||
|
||||
void DesignModeWidget::readSettings()
|
||||
{
|
||||
QSettings *settings = Core::ICore::instance()->settings();
|
||||
|
||||
settings->beginGroup("Bauhaus");
|
||||
m_leftSideBar->readSettings(settings, QLatin1String("LeftSideBar"));
|
||||
m_rightSideBar->readSettings(settings, QLatin1String("RightSideBar"));
|
||||
if (settings->contains("MainSplitter")) {
|
||||
const QByteArray splitterState = settings->value("MainSplitter").toByteArray();
|
||||
m_mainSplitter->restoreState(splitterState);
|
||||
}
|
||||
settings->endGroup();
|
||||
}
|
||||
|
||||
void DesignModeWidget::saveSettings()
|
||||
{
|
||||
QSettings *settings = Core::ICore::instance()->settings();
|
||||
|
||||
settings->beginGroup("Bauhaus");
|
||||
m_leftSideBar->saveSettings(settings, QLatin1String("LeftSideBar"));
|
||||
m_rightSideBar->saveSettings(settings, QLatin1String("RightSideBar"));
|
||||
settings->setValue("MainSplitter", m_mainSplitter->saveState());
|
||||
settings->endGroup();
|
||||
}
|
||||
|
||||
void DesignModeWidget::undo()
|
||||
{
|
||||
if (m_currentDocumentWidget)
|
||||
m_currentDocumentWidget->document()->undo();
|
||||
if (m_currentDesignDocumentController)
|
||||
m_currentDesignDocumentController->undo();
|
||||
}
|
||||
|
||||
void DesignModeWidget::redo()
|
||||
{
|
||||
if (m_currentDocumentWidget)
|
||||
m_currentDocumentWidget->document()->redo();
|
||||
if (m_currentDesignDocumentController)
|
||||
m_currentDesignDocumentController->redo();
|
||||
}
|
||||
|
||||
void DesignModeWidget::deleteSelected()
|
||||
{
|
||||
if (m_currentDocumentWidget)
|
||||
m_currentDocumentWidget->document()->deleteSelected();
|
||||
if (m_currentDesignDocumentController)
|
||||
m_currentDesignDocumentController->deleteSelected();
|
||||
}
|
||||
|
||||
void DesignModeWidget::cutSelected()
|
||||
{
|
||||
if (m_currentDocumentWidget)
|
||||
m_currentDocumentWidget->document()->cutSelected();
|
||||
if (m_currentDesignDocumentController)
|
||||
m_currentDesignDocumentController->cutSelected();
|
||||
}
|
||||
|
||||
void DesignModeWidget::copySelected()
|
||||
{
|
||||
if (m_currentDocumentWidget)
|
||||
m_currentDocumentWidget->document()->copySelected();
|
||||
if (m_currentDesignDocumentController)
|
||||
m_currentDesignDocumentController->copySelected();
|
||||
}
|
||||
|
||||
void DesignModeWidget::paste()
|
||||
{
|
||||
if (m_currentDocumentWidget)
|
||||
m_currentDocumentWidget->document()->paste();
|
||||
if (m_currentDesignDocumentController)
|
||||
m_currentDesignDocumentController->paste();
|
||||
}
|
||||
|
||||
void DesignModeWidget::selectAll()
|
||||
{
|
||||
if (m_currentDocumentWidget)
|
||||
m_currentDocumentWidget->document()->selectAll();
|
||||
if (m_currentDesignDocumentController)
|
||||
m_currentDesignDocumentController->selectAll();
|
||||
}
|
||||
|
||||
void DesignModeWidget::closeCurrentEditor()
|
||||
{
|
||||
}
|
||||
|
||||
void DesignModeWidget::undoAvailable(bool isAvailable)
|
||||
{
|
||||
DesignDocumentController *documentController = qobject_cast<DesignDocumentController*>(sender());
|
||||
if (m_currentDocumentWidget &&
|
||||
m_currentDocumentWidget->document() == documentController) {
|
||||
if (m_currentDesignDocumentController &&
|
||||
m_currentDesignDocumentController.data() == documentController) {
|
||||
m_undoAction->setEnabled(isAvailable);
|
||||
}
|
||||
}
|
||||
@@ -539,44 +329,333 @@ void DesignModeWidget::undoAvailable(bool isAvailable)
|
||||
void DesignModeWidget::redoAvailable(bool isAvailable)
|
||||
{
|
||||
DesignDocumentController *documentController = qobject_cast<DesignDocumentController*>(sender());
|
||||
if (m_currentDocumentWidget &&
|
||||
m_currentDocumentWidget->document() == documentController) {
|
||||
if (m_currentDesignDocumentController &&
|
||||
m_currentDesignDocumentController.data() == documentController) {
|
||||
m_redoAction->setEnabled(isAvailable);
|
||||
}
|
||||
}
|
||||
|
||||
void DesignModeWidget::setCurrentDocumentWidget(DocumentWidget *newDocumentWidget)
|
||||
|
||||
void DesignModeWidget::enable()
|
||||
{
|
||||
if (debug)
|
||||
qDebug() << Q_FUNC_INFO << newDocumentWidget;
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
m_warningWidget->setVisible(false);
|
||||
m_formEditorView->widget()->setEnabled(true);
|
||||
m_statesEditorWidget->setEnabled(true);
|
||||
m_leftSideBar->setEnabled(true);
|
||||
m_rightSideBar->setEnabled(true);
|
||||
m_isDisabled = false;
|
||||
}
|
||||
|
||||
if (m_currentDocumentWidget == newDocumentWidget)
|
||||
return;
|
||||
void DesignModeWidget::disable(const QList<RewriterView::Error> &errors)
|
||||
{
|
||||
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_statesEditorWidget->setEnabled(false);
|
||||
m_leftSideBar->setEnabled(false);
|
||||
m_rightSideBar->setEnabled(false);
|
||||
m_isDisabled = true;
|
||||
}
|
||||
|
||||
if (m_currentDocumentWidget) {
|
||||
m_currentDocumentWidget->setAutoSynchronization(false);
|
||||
m_currentDocumentWidget->saveSettings();
|
||||
void DesignModeWidget::updateErrorStatus(const QList<RewriterView::Error> &errors)
|
||||
{
|
||||
if (debug)
|
||||
qDebug() << Q_FUNC_INFO << errors.count();
|
||||
|
||||
if (m_isDisabled && errors.isEmpty()) {
|
||||
enable();
|
||||
} else if (!errors.isEmpty()) {
|
||||
disable(errors);
|
||||
}
|
||||
}
|
||||
|
||||
void DesignModeWidget::setAutoSynchronization(bool sync)
|
||||
{
|
||||
if (debug)
|
||||
qDebug() << Q_FUNC_INFO << sync;
|
||||
|
||||
m_currentDesignDocumentController->blockModelSync(!sync);
|
||||
|
||||
if (sync) {
|
||||
// text editor -> visual editor
|
||||
if (!m_currentDesignDocumentController->model()) {
|
||||
m_currentDesignDocumentController->loadMaster(m_currentTextEdit.data());
|
||||
} else {
|
||||
m_currentDesignDocumentController->loadCurrentModel();
|
||||
}
|
||||
|
||||
m_currentDocumentWidget = newDocumentWidget;
|
||||
|
||||
if (m_currentDocumentWidget) {
|
||||
m_currentDocumentWidget->setAutoSynchronization(true);
|
||||
m_documentWidgetStack->setCurrentWidget(m_currentDocumentWidget);
|
||||
m_currentDocumentWidget->readSettings();
|
||||
m_undoAction->setEnabled(m_currentDocumentWidget->document()->isUndoAvailable());
|
||||
m_redoAction->setEnabled(m_currentDocumentWidget->document()->isRedoAvailable());
|
||||
QList<RewriterView::Error> errors = m_currentDesignDocumentController->qmlErrors();
|
||||
if (errors.isEmpty()) {
|
||||
// set selection to text cursor
|
||||
RewriterView *rewriter = m_currentDesignDocumentController->rewriterView();
|
||||
const int cursorPos = m_currentTextEdit->textCursor().position();
|
||||
ModelNode node = nodeForPosition(cursorPos);
|
||||
if (node.isValid()) {
|
||||
rewriter->setSelectedModelNodes(QList<ModelNode>() << node);
|
||||
}
|
||||
enable();
|
||||
} else {
|
||||
m_documentWidgetStack->setCurrentIndex(0);
|
||||
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>)));
|
||||
}
|
||||
}
|
||||
|
||||
void DesignModeWidget::setCurrentDocument(DesignDocumentController *newDesignDocumentController)
|
||||
{
|
||||
if (debug)
|
||||
qDebug() << Q_FUNC_INFO << newDesignDocumentController;
|
||||
|
||||
if (m_currentDesignDocumentController.data() == newDesignDocumentController)
|
||||
return;
|
||||
if (m_currentDesignDocumentController) {
|
||||
setAutoSynchronization(false);
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
disconnect(currentDesignDocumentController(), SIGNAL(undoAvailable(bool)),
|
||||
this, SLOT(undoAvailable(bool)));
|
||||
disconnect(currentDesignDocumentController(), SIGNAL(redoAvailable(bool)),
|
||||
this, SLOT(redoAvailable(bool)));
|
||||
disconnect(currentDesignDocumentController(), SIGNAL(deleteAvailable(bool)),
|
||||
this, SLOT(deleteAvailable(bool)));
|
||||
|
||||
m_currentDesignDocumentController = newDesignDocumentController;
|
||||
|
||||
connect(currentDesignDocumentController(), SIGNAL(undoAvailable(bool)),
|
||||
this, SLOT(undoAvailable(bool)));
|
||||
connect(currentDesignDocumentController(), SIGNAL(redoAvailable(bool)),
|
||||
this, SLOT(redoAvailable(bool)));
|
||||
connect(currentDesignDocumentController(), SIGNAL(deleteAvailable(bool)),
|
||||
this, SLOT(deleteAvailable(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()
|
||||
{
|
||||
if (m_setup)
|
||||
return;
|
||||
m_setup = true;
|
||||
|
||||
QList<Core::INavigationWidgetFactory *> factories = ExtensionSystem::PluginManager::instance()->getObjects<Core::INavigationWidgetFactory>();
|
||||
|
||||
QWidget *openDocumentsWidget = 0;
|
||||
QWidget *projectsExplorer = 0;
|
||||
QWidget *fileSystemExplorer = 0;
|
||||
|
||||
|
||||
foreach(Core::INavigationWidgetFactory *factory, factories)
|
||||
{
|
||||
Core::NavigationView navigationView;
|
||||
navigationView.widget = 0;
|
||||
if (factory->displayName() == QLatin1String("Projects")) {
|
||||
navigationView = factory->createWidget();
|
||||
projectsExplorer = navigationView.widget;
|
||||
projectsExplorer->setWindowTitle(tr("Projects"));
|
||||
}
|
||||
if (factory->displayName() == QLatin1String("File System")) {
|
||||
navigationView = factory->createWidget();
|
||||
fileSystemExplorer = navigationView.widget;
|
||||
fileSystemExplorer->setWindowTitle(tr("File System"));
|
||||
}
|
||||
if (factory->displayName() == QLatin1String("Open Documents")) {
|
||||
navigationView = factory->createWidget();
|
||||
openDocumentsWidget = navigationView.widget;
|
||||
openDocumentsWidget->setWindowTitle(tr("Open Documents"));
|
||||
}
|
||||
|
||||
if (navigationView.widget)
|
||||
{
|
||||
QFile file(":/qmldesigner/stylesheet.css");
|
||||
file.open(QFile::ReadOnly);
|
||||
QFile file2(":/qmldesigner/scrollbar.css");
|
||||
file2.open(QFile::ReadOnly);
|
||||
|
||||
QString labelStyle = QLatin1String("QLabel { background-color: #707070; }");
|
||||
|
||||
QString styleSheet = file.readAll() + file2.readAll() + labelStyle;
|
||||
navigationView.widget->setStyleSheet(styleSheet);
|
||||
}
|
||||
}
|
||||
|
||||
m_navigator = new NavigatorView(this);
|
||||
|
||||
m_allPropertiesBox = new AllPropertiesBox(this);
|
||||
m_statesEditorWidget = new StatesEditorWidget(this);
|
||||
|
||||
m_formEditorView = new FormEditorView(this);
|
||||
|
||||
m_itemLibrary = new ItemLibrary(this);
|
||||
|
||||
m_designToolBar = new QToolBar;
|
||||
m_fakeToolBar = Core::EditorManager::createToolBar(this);
|
||||
|
||||
|
||||
m_mainSplitter = new MiniSplitter(this);
|
||||
m_mainSplitter->setObjectName("mainSplitter");
|
||||
|
||||
// warning frame should be not in layout, but still child of the widget
|
||||
m_warningWidget = new DocumentWarningWidget(this);
|
||||
m_warningWidget->setVisible(false);
|
||||
|
||||
// Left area:
|
||||
|
||||
Core::SideBarItem *navigatorItem = new Core::SideBarItem(m_navigator->widget());
|
||||
Core::SideBarItem *libraryItem = new Core::SideBarItem(m_itemLibrary.data());
|
||||
Core::SideBarItem *propertiesItem = new Core::SideBarItem(m_allPropertiesBox.data());
|
||||
|
||||
|
||||
QList<Core::SideBarItem*> leftSideBarItems, rightSideBarItems;
|
||||
leftSideBarItems << navigatorItem << libraryItem;
|
||||
rightSideBarItems << propertiesItem;
|
||||
|
||||
if (projectsExplorer) {
|
||||
Core::SideBarItem *projectExplorerItem = new Core::SideBarItem(projectsExplorer);
|
||||
rightSideBarItems << projectExplorerItem;
|
||||
}
|
||||
|
||||
if (fileSystemExplorer) {
|
||||
Core::SideBarItem *fileSystemExplorerItem = new Core::SideBarItem(fileSystemExplorer);
|
||||
rightSideBarItems << fileSystemExplorerItem;
|
||||
}
|
||||
|
||||
if (openDocumentsWidget) {
|
||||
Core::SideBarItem *openDocumentsItem = new Core::SideBarItem(openDocumentsWidget);
|
||||
rightSideBarItems << openDocumentsItem;
|
||||
}
|
||||
|
||||
m_leftSideBar = new Core::SideBar(leftSideBarItems, QList<Core::SideBarItem*>() << navigatorItem << libraryItem);
|
||||
m_rightSideBar = new Core::SideBar(rightSideBarItems, QList<Core::SideBarItem*>() << propertiesItem);
|
||||
|
||||
m_designToolBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored);
|
||||
|
||||
m_fakeToolBar->setToolbarCreationFlags(Core::EditorToolBar::FlagsStandalone);
|
||||
//m_fakeToolBar->addEditor(textEditor()); ### what does this mean?
|
||||
m_fakeToolBar->addCenterToolBar(m_designToolBar);
|
||||
m_fakeToolBar->setNavigationVisible(false);
|
||||
|
||||
connect(m_fakeToolBar, SIGNAL(closeClicked()), this, SLOT(closeCurrentEditor()));
|
||||
|
||||
// right area:
|
||||
QWidget *centerWidget = new QWidget;
|
||||
{
|
||||
QVBoxLayout *rightLayout = new QVBoxLayout(centerWidget);
|
||||
rightLayout->setMargin(0);
|
||||
rightLayout->setSpacing(0);
|
||||
rightLayout->addWidget(m_fakeToolBar);
|
||||
//### we now own these here
|
||||
rightLayout->addWidget(m_statesEditorWidget.data());
|
||||
rightLayout->addWidget(m_formEditorView->widget());
|
||||
}
|
||||
|
||||
// m_mainSplitter area:
|
||||
m_mainSplitter->addWidget(m_leftSideBar);
|
||||
m_mainSplitter->addWidget(centerWidget);
|
||||
m_mainSplitter->addWidget(m_rightSideBar);
|
||||
|
||||
// Finishing touches:
|
||||
m_mainSplitter->setOpaqueResize(false);
|
||||
m_mainSplitter->setStretchFactor(1, 1);
|
||||
m_mainSplitter->setSizes(QList<int>() << 150 << 300 << 150);
|
||||
|
||||
QLayout *mainLayout = new QBoxLayout(QBoxLayout::RightToLeft, this);
|
||||
mainLayout->setMargin(0);
|
||||
mainLayout->setSpacing(0);
|
||||
mainLayout->addWidget(m_mainSplitter);
|
||||
|
||||
m_warningWidget->setVisible(false);
|
||||
m_statesEditorWidget->setEnabled(true);
|
||||
m_leftSideBar->setEnabled(true);
|
||||
m_rightSideBar->setEnabled(true);
|
||||
|
||||
readSettings();
|
||||
|
||||
show();
|
||||
QApplication::processEvents();
|
||||
}
|
||||
|
||||
void DesignModeWidget::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
if (m_warningWidget)
|
||||
m_warningWidget->move(QPoint(event->size().width() / 2, event->size().height() / 2));
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
QString DesignModeWidget::contextHelpId() const
|
||||
{
|
||||
if (m_currentDocumentWidget)
|
||||
return m_currentDocumentWidget->document()->contextHelpId();
|
||||
if (m_currentDesignDocumentController)
|
||||
return m_currentDesignDocumentController->contextHelpId();
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
void showEditor(Core::IEditor *editor);
|
||||
void closeEditors(const QList<Core::IEditor*> editors);
|
||||
QString contextHelpId() const;
|
||||
@@ -158,6 +114,12 @@ public:
|
||||
QAction *pasteAction() const;
|
||||
QAction *selectAllAction() const;
|
||||
|
||||
void readSettings();
|
||||
void saveSettings();
|
||||
void setAutoSynchronization(bool sync);
|
||||
|
||||
TextEditor::ITextEditor *textEditor() const {return m_textEditor; }
|
||||
|
||||
private slots:
|
||||
void undo();
|
||||
void redo();
|
||||
@@ -166,17 +128,26 @@ private slots:
|
||||
void copySelected();
|
||||
void paste();
|
||||
void selectAll();
|
||||
void closeCurrentEditor();
|
||||
|
||||
void undoAvailable(bool isAvailable);
|
||||
void redoAvailable(bool isAvailable);
|
||||
|
||||
private:
|
||||
void setCurrentDocumentWidget(DocumentWidget *newDocumentWidget);
|
||||
void enable();
|
||||
void disable(const QList<RewriterView::Error> &errors);
|
||||
void updateErrorStatus(const QList<RewriterView::Error> &errors);
|
||||
|
||||
QStackedWidget *m_documentWidgetStack;
|
||||
QHash<QPlainTextEdit*,DocumentWidget*> m_documentHash;
|
||||
DocumentWidget *m_currentDocumentWidget;
|
||||
QPlainTextEdit *m_currentTextEdit;
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
private:
|
||||
DesignDocumentController *currentDesignDocumentController() const {return m_currentDesignDocumentController.data(); }
|
||||
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;
|
||||
@@ -186,7 +157,30 @@ private:
|
||||
QAction *m_pasteAction;
|
||||
QAction *m_selectAllAction;
|
||||
|
||||
QWeakPointer<ItemLibrary> m_itemLibrary;
|
||||
QWeakPointer<NavigatorView> m_navigator;
|
||||
QWeakPointer<AllPropertiesBox> m_allPropertiesBox;
|
||||
QWeakPointer<StatesEditorWidget> m_statesEditorWidget;
|
||||
QWeakPointer<FormEditorView> m_formEditorView;
|
||||
|
||||
bool m_syncWithTextEdit;
|
||||
|
||||
void setup();
|
||||
bool isInNodeDefinition(int nodeOffset, int nodeLength, int cursorPos) const;
|
||||
QmlDesigner::ModelNode nodeForPosition(int cursorPos) const;
|
||||
|
||||
TextEditor::ITextEditor *m_textEditor;
|
||||
|
||||
QSplitter *m_mainSplitter;
|
||||
Core::SideBar *m_leftSideBar;
|
||||
Core::SideBar *m_rightSideBar;
|
||||
|
||||
QToolBar *m_designToolBar;
|
||||
Core::EditorToolBar *m_fakeToolBar;
|
||||
|
||||
bool m_isDisabled;
|
||||
bool m_setup;
|
||||
DocumentWarningWidget *m_warningWidget;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
Reference in New Issue
Block a user