diff --git a/src/plugins/designer/designer.pro b/src/plugins/designer/designer.pro index d60541416476ba8d3f575b9837c07bb043f54bca..9a28eb14b0d19ae8876f8c69bc6a0f18238a7fb2 100644 --- a/src/plugins/designer/designer.pro +++ b/src/plugins/designer/designer.pro @@ -39,7 +39,8 @@ HEADERS += formeditorplugin.h \ designerxmleditor.h \ designercontext.h \ faketoolbar.h \ - formeditorstack.h + formeditorstack.h \ + editordata.h SOURCES += formeditorplugin.cpp \ formeditorfactory.cpp \ diff --git a/src/plugins/designer/designercontext.cpp b/src/plugins/designer/designercontext.cpp index 5a5a7b6bee0eee3c283fdb44a4e0472c23561e84..7e28f1df6899df82679a2fb30011dce7472c56cb 100644 --- a/src/plugins/designer/designercontext.cpp +++ b/src/plugins/designer/designercontext.cpp @@ -36,6 +36,7 @@ #include <QtGui/QWidget> #include <QtCore/QDebug> +#include <QtCore/QSettings> enum { debug = 0 }; diff --git a/src/plugins/designer/designerxmleditor.cpp b/src/plugins/designer/designerxmleditor.cpp index 96e52f1bcaba5433f23a9985ddec0e5a7b593ea6..e6982bc917d4d0b858da1b876c025cc2689e6dc6 100644 --- a/src/plugins/designer/designerxmleditor.cpp +++ b/src/plugins/designer/designerxmleditor.cpp @@ -29,64 +29,157 @@ #include "designerxmleditor.h" #include "designerconstants.h" +#include "qt_private/formwindowbase_p.h" + #include <coreplugin/editormanager/editormanager.h> #include <coreplugin/icore.h> #include <coreplugin/modemanager.h> #include <coreplugin/imode.h> #include <coreplugin/coreconstants.h> #include <coreplugin/uniqueidmanager.h> -#include <QDebug> +#include <texteditor/basetextdocument.h> + +#include <utils/qtcassert.h> + +#include <QtDesigner/QDesignerFormWindowInterface> + +#include <QtCore/QDebug> +#include <QtCore/QFileInfo> +#include <QtCore/QFile> namespace Designer { -namespace Internal { -DesignerXmlEditor::DesignerXmlEditor(QWidget *parent) : TextEditor::PlainTextEditor(parent) + +DesignerXmlEditorEditable::DesignerXmlEditorEditable(Internal::DesignerXmlEditor *editor, + QDesignerFormWindowInterface *form, + QObject *parent) : + Core::IEditor(parent), + m_textEditable(editor), + m_file(form) { - setReadOnly(true); - connect(Core::ICore::instance()->editorManager(), SIGNAL(currentEditorChanged(Core::IEditor*)), - SLOT(updateEditorInfoBar(Core::IEditor*))); + Core::UniqueIDManager *uidm = Core::UniqueIDManager::instance(); + m_context << uidm->uniqueIdentifier(QLatin1String(Designer::Constants::K_DESIGNER_XML_EDITOR_ID)); + m_context << uidm->uniqueIdentifier(QLatin1String(Designer::Constants::C_DESIGNER_XML_EDITOR)); + connect(form, SIGNAL(changed()), this, SIGNAL(changed())); + // Revert to saved/load externally modified files + connect(&m_file, SIGNAL(reload(QString)), this, SLOT(slotOpen(QString))); } -DesignerXmlEditor::~DesignerXmlEditor() +bool DesignerXmlEditorEditable::createNew(const QString &contents) { + if (Designer::Constants::Internal::debug) + qDebug() << "DesignerXmlEditorEditable::createNew" << contents.size(); + + syncXmlEditor(QString()); + + QDesignerFormWindowInterface *form = m_file.formWindow(); + QTC_ASSERT(form, return false); + + if (contents.isEmpty()) + return false; + form->setContents(contents); + if (form->mainContainer() == 0) + return false; + + syncXmlEditor(contents); + m_file.setFileName(QString()); + return true; } -bool DesignerXmlEditor::open(const QString &fileName) +void DesignerXmlEditorEditable::slotOpen(const QString &fileName) { - bool res = TextEditor::PlainTextEditor::open(fileName); - QPlainTextEdit::setReadOnly(true); - return res; + open(fileName); } -void DesignerXmlEditor::updateEditorInfoBar(Core::IEditor *editor) +bool DesignerXmlEditorEditable::open(const QString &fileName) { - if (editor == editableInterface()) { - Core::EditorManager::instance()->showEditorInfoBar(Constants::INFO_READ_ONLY, - tr("This file can only be edited in Design Mode."), - "Open Designer", this, SLOT(designerOpened())); + if (Designer::Constants::Internal::debug) + qDebug() << "DesignerXmlEditorEditable::open" << fileName; + + QDesignerFormWindowInterface *form = m_file.formWindow(); + QTC_ASSERT(form, return false); + + if (fileName.isEmpty()) { + setDisplayName(tr("untitled")); + return true; } - if (!editor) - Core::EditorManager::instance()->hideEditorInfoBar(Constants::INFO_READ_ONLY); + + const QFileInfo fi(fileName); + const QString absfileName = fi.absoluteFilePath(); + + QFile file(absfileName); + if (!file.open(QIODevice::ReadOnly|QIODevice::Text)) + return false; + + form->setFileName(absfileName); + + const QString contents = QString::fromUtf8(file.readAll()); + form->setContents(contents); + file.close(); + if (!form->mainContainer()) + return false; + form->setDirty(false); + syncXmlEditor(contents); + + setDisplayName(fi.fileName()); + m_file.setFileName(absfileName); + + emit changed(); + + return true; } -void DesignerXmlEditor::designerOpened() +void DesignerXmlEditorEditable::syncXmlEditor() { - Core::ICore::instance()->modeManager()->activateMode(Core::Constants::MODE_DESIGN); + if (Designer::Constants::Internal::debug) + qDebug() << "DesignerXmlEditorEditable::syncXmlEditor" << m_file.fileName(); + syncXmlEditor(contents()); } -} // namespace Internal +void DesignerXmlEditorEditable::syncXmlEditor(const QString &contents) +{ + m_textEditable.editor()->setPlainText(contents); + m_textEditable.editor()->setReadOnly(true); +} + +Core::IFile *DesignerXmlEditorEditable::file() +{ + return &m_file; +} QString DesignerXmlEditorEditable::id() const { return QLatin1String(Designer::Constants::K_DESIGNER_XML_EDITOR_ID); } -DesignerXmlEditorEditable::DesignerXmlEditorEditable(Internal::DesignerXmlEditor *editor) - : TextEditor::PlainTextEditorEditable(editor) +QString DesignerXmlEditorEditable::displayName() const { - Core::UniqueIDManager *uidm = Core::UniqueIDManager::instance(); - m_context << uidm->uniqueIdentifier(Designer::Constants::K_DESIGNER_XML_EDITOR_ID); - m_context << uidm->uniqueIdentifier(Designer::Constants::C_DESIGNER_XML_EDITOR); + return m_textEditable.displayName(); +} + +void DesignerXmlEditorEditable::setDisplayName(const QString &title) +{ + m_textEditable.setDisplayName(title); +} + +bool DesignerXmlEditorEditable::duplicateSupported() const +{ + return false; +} + +Core::IEditor *DesignerXmlEditorEditable::duplicate(QWidget *) +{ + return 0; +} + +QByteArray DesignerXmlEditorEditable::saveState() const +{ + return m_textEditable.saveState(); +} + +bool DesignerXmlEditorEditable::restoreState(const QByteArray &state) +{ + return m_textEditable.restoreState(state); } QList<int> DesignerXmlEditorEditable::context() const @@ -94,17 +187,78 @@ QList<int> DesignerXmlEditorEditable::context() const return m_context; } -Core::IEditor *DesignerXmlEditorEditable::duplicate(QWidget *parent) +QWidget *DesignerXmlEditorEditable::widget() +{ + return m_textEditable.widget(); +} + +bool DesignerXmlEditorEditable::isTemporary() const +{ + return false; +} + +QWidget *DesignerXmlEditorEditable::toolBar() { - Q_UNUSED(parent); return 0; } +QString DesignerXmlEditorEditable::contents() const +{ + const qdesigner_internal::FormWindowBase *fw = qobject_cast<const qdesigner_internal::FormWindowBase *>(m_file.formWindow()); + QTC_ASSERT(fw, return QString()); + return fw->fileContents(); // No warnings about spacers here +} + +TextEditor::BaseTextDocument *DesignerXmlEditorEditable::textDocument() +{ + return qobject_cast<TextEditor::BaseTextDocument*>(m_textEditable.file()); +} + +TextEditor::PlainTextEditorEditable *DesignerXmlEditorEditable::textEditable() +{ + return &m_textEditable; +} + namespace Internal { + +DesignerXmlEditor::DesignerXmlEditor(QDesignerFormWindowInterface *form, + QWidget *parent) : + TextEditor::PlainTextEditor(parent), + m_editable(new DesignerXmlEditorEditable(this, form)) +{ + setReadOnly(true); + connect(Core::EditorManager::instance(), SIGNAL(currentEditorChanged(Core::IEditor*)), + SLOT(updateEditorInfoBar(Core::IEditor*))); +} + TextEditor::BaseTextEditorEditable *DesignerXmlEditor::createEditableInterface() { - return new DesignerXmlEditorEditable(this); + if (Designer::Constants::Internal::debug) + qDebug() << "DesignerXmlEditor::createEditableInterface()"; + return m_editable->textEditable(); } + +void DesignerXmlEditor::updateEditorInfoBar(Core::IEditor *editor) +{ + if (editor == m_editable) { + Core::EditorManager::instance()->showEditorInfoBar(Constants::INFO_READ_ONLY, + tr("This file can only be edited in Design Mode."), + "Open Designer", this, SLOT(designerModeClicked())); + } + if (!editor) + Core::EditorManager::instance()->hideEditorInfoBar(Constants::INFO_READ_ONLY); +} + +void DesignerXmlEditor::designerModeClicked() +{ + Core::ICore::instance()->modeManager()->activateMode(QLatin1String(Core::Constants::MODE_DESIGN)); +} + +DesignerXmlEditorEditable *DesignerXmlEditor::designerEditable() const +{ + return m_editable; +} + } } // namespace Designer diff --git a/src/plugins/designer/designerxmleditor.h b/src/plugins/designer/designerxmleditor.h index ce0b2abb897416022fd73c93791b8288f0b5f396..d5f32ceedc9a2725f5c2c67669a74c2dc68e02f6 100644 --- a/src/plugins/designer/designerxmleditor.h +++ b/src/plugins/designer/designerxmleditor.h @@ -31,58 +31,106 @@ #define DESIGNERXMLEDITOR_H #include "designer_export.h" +#include "formwindowfile.h" + #include <texteditor/plaintexteditor.h> -#include <texteditor/basetexteditor.h> namespace Core { - class IEditor; class IMode; } +namespace TextEditor { + class BaseTextDocument; +} + namespace Designer { namespace Internal { class DesignerXmlEditor; } -class DESIGNER_EXPORT DesignerXmlEditorEditable : public TextEditor::PlainTextEditorEditable +// The actual Core::IEditor belonging to Qt Designer. It internally embeds +// a TextEditor::PlainTextEditorEditable which is used to make the +// Read-only edit mode XML text editor work and delegates some functionality +// to it. However, the isDirty() handling is delegated to the FormWindowFile, +// which is the Core::IFile used for it. +class DESIGNER_EXPORT DesignerXmlEditorEditable : public Core::IEditor { Q_OBJECT public: - explicit DesignerXmlEditorEditable(Internal::DesignerXmlEditor *editor); - QList<int> context() const; + explicit DesignerXmlEditorEditable(Internal::DesignerXmlEditor *editor, + QDesignerFormWindowInterface *form, + QObject *parent = 0); - bool duplicateSupported() const { return false; } - Core::IEditor *duplicate(QWidget *parent); + // IEditor + virtual bool createNew(const QString &contents = QString()); + virtual bool open(const QString &fileName = QString()); + virtual Core::IFile *file(); virtual QString id() const; + virtual QString displayName() const; + virtual void setDisplayName(const QString &title); + + virtual bool duplicateSupported() const; + virtual IEditor *duplicate(QWidget *parent); + + virtual QByteArray saveState() const; + virtual bool restoreState(const QByteArray &state); + + virtual bool isTemporary() const; + + virtual QWidget *toolBar(); + + // IContext + virtual QList<int> context() const; + virtual QWidget *widget(); + + // For uic code model support + QString contents() const; + + TextEditor::BaseTextDocument *textDocument(); + TextEditor::PlainTextEditorEditable *textEditable(); + +public slots: + void syncXmlEditor(); + +private slots: + void slotOpen(const QString &fileName); private: + void syncXmlEditor(const QString &contents); + + TextEditor::PlainTextEditorEditable m_textEditable; + Internal::FormWindowFile m_file; QList<int> m_context; }; -/** - * A stub-like, read-only text editor which displays UI files as text. Could be used as a +/* A stub-like, read-only text editor which displays UI files as text. Could be used as a * read/write editor too, but due to lack of XML editor, highlighting and other such * functionality, editing is disabled. - */ + * Provides an informational title bar containing a button triggering a + * switch to design mode. + * Internally manages DesignerXmlEditorEditable and uses the plain text + * editable embedded in it. */ namespace Internal { class DesignerXmlEditor : public TextEditor::PlainTextEditor { Q_OBJECT public: - explicit DesignerXmlEditor(QWidget *parent = 0); - virtual ~DesignerXmlEditor(); - bool open(const QString &fileName = QString()); + explicit DesignerXmlEditor(QDesignerFormWindowInterface *form, + QWidget *parent = 0); + + DesignerXmlEditorEditable *designerEditable() const; private slots: - void designerOpened(); + void designerModeClicked(); void updateEditorInfoBar(Core::IEditor *editor); protected: virtual TextEditor::BaseTextEditorEditable *createEditableInterface(); private: + DesignerXmlEditorEditable *m_editable; }; } // Internal diff --git a/src/plugins/designer/editordata.h b/src/plugins/designer/editordata.h new file mode 100644 index 0000000000000000000000000000000000000000..661c8e202499dd5561ca61cc76135eaa25f0b36b --- /dev/null +++ b/src/plugins/designer/editordata.h @@ -0,0 +1,49 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef EDITORDATA_H +#define EDITORDATA_H + +namespace Designer { + class FormWindowEditor; + class DesignerXmlEditorEditable; + +namespace Internal { + +// Associates XML and its form editor +struct EditorData { + EditorData() : xmlEditor(0), formEditor(0) {} + DesignerXmlEditorEditable *xmlEditor; + Designer::FormWindowEditor *formEditor; +}; + +} // namespace Internal +} // namespace Designer + +#endif // EDITORDATA_H diff --git a/src/plugins/designer/editorwidget.cpp b/src/plugins/designer/editorwidget.cpp index 4459b263078a8ba140ec52a5bc4c3c67127e42d0..7e7ea571b5749c69b4a60d56cd43ad5ef9cf8934 100644 --- a/src/plugins/designer/editorwidget.cpp +++ b/src/plugins/designer/editorwidget.cpp @@ -92,9 +92,9 @@ QDockWidget* const* EditorWidget::designerDockWidgets() const return m_designerDockWidgets; } -Designer::FormWindowEditor *EditorWidget::createFormWindowEditor(DesignerXmlEditorEditable *xmlEditor) +void EditorWidget::add(const EditorData &d) { - return m_stack->createFormWindowEditor(xmlEditor); + m_stack->add(d); } bool EditorWidget::removeFormWindowEditor(Core::IEditor *xmlEditor) diff --git a/src/plugins/designer/editorwidget.h b/src/plugins/designer/editorwidget.h index 42c8e52a3ebcc6c2acbb0c4c910b733c9a992658..cf8041d23599e93f9ed86e6f5f0f4ce42d2be80b 100644 --- a/src/plugins/designer/editorwidget.h +++ b/src/plugins/designer/editorwidget.h @@ -34,9 +34,6 @@ #include <utils/fancymainwindow.h> -#include <QtCore/QHash> -#include <QtCore/QVariant> - QT_BEGIN_NAMESPACE class QDesignerFormWindowInterface; QT_END_NAMESPACE @@ -49,10 +46,11 @@ class FormWindowEditor; class DesignerXmlEditorEditable; namespace Internal { +struct EditorData; class FormEditorStack; class FormEditorW; -/* Form editor splitter used as editor window. Contains the shared designer - * windows. */ + +// Design mode main view. class EditorWidget : public Utils::FancyMainWindow { Q_OBJECT @@ -63,7 +61,7 @@ public: QDockWidget* const* designerDockWidgets() const; // Form editor stack API - Designer::FormWindowEditor *createFormWindowEditor(DesignerXmlEditorEditable *xmlEditor); + void add(const EditorData &d); bool removeFormWindowEditor(Core::IEditor *xmlEditor); bool setVisibleEditor(Core::IEditor *xmlEditor); Designer::FormWindowEditor *formWindowEditorForXmlEditor(const Core::IEditor *xmlEditor) const; diff --git a/src/plugins/designer/formeditorfactory.cpp b/src/plugins/designer/formeditorfactory.cpp index 39cd429fb1f78a3bb09fd58e68576540b6be186c..5891741698f9a92d323203390ecf92912610619f 100644 --- a/src/plugins/designer/formeditorfactory.cpp +++ b/src/plugins/designer/formeditorfactory.cpp @@ -30,32 +30,34 @@ #include "formeditorfactory.h" #include "formeditorw.h" #include "formwindoweditor.h" +#include "editordata.h" #include "designerconstants.h" #include "designerxmleditor.h" #include <coreplugin/icore.h> #include <coreplugin/fileiconprovider.h> #include <coreplugin/editormanager/editormanager.h> -#include <texteditor/texteditorsettings.h> #include <QtCore/QFileInfo> #include <QtCore/QDebug> -using namespace Designer::Internal; using namespace Designer::Constants; +namespace Designer { +namespace Internal { + FormEditorFactory::FormEditorFactory() : Core::IEditorFactory(Core::ICore::instance()), m_mimeTypes(QLatin1String(FORM_MIMETYPE)) { Core::FileIconProvider *iconProvider = Core::FileIconProvider::instance(); - iconProvider->registerIconOverlayForSuffix(QIcon(":/formeditor/images/qt_ui.png"), - QLatin1String("ui")); + iconProvider->registerIconOverlayForSuffix(QIcon(QLatin1String(":/formeditor/images/qt_ui.png")), + QLatin1String("ui")); } QString FormEditorFactory::id() const { - return QLatin1String(DESIGNER_XML_EDITOR_ID); //FORMEDITOR_ID); + return QLatin1String(DESIGNER_XML_EDITOR_ID); } QString FormEditorFactory::displayName() const @@ -71,12 +73,16 @@ Core::IFile *FormEditorFactory::open(const QString &fileName) Core::IEditor *FormEditorFactory::createEditor(QWidget *parent) { - DesignerXmlEditor *xmlEditor = new DesignerXmlEditor(parent); - TextEditor::TextEditorSettings::instance()->initializeEditor(xmlEditor); - return xmlEditor->editableInterface(); + const EditorData data = FormEditorW::instance()->createEditor(parent); + return data.xmlEditor; } QStringList FormEditorFactory::mimeTypes() const { return m_mimeTypes; } + +} // namespace Internal +} // namespace Designer + + diff --git a/src/plugins/designer/formeditorfactory.h b/src/plugins/designer/formeditorfactory.h index 1d8a8584aac84da377570c6b0d3bfa631b755b0a..75c0db8778ceb32c8973e55fcde9763c33749fb8 100644 --- a/src/plugins/designer/formeditorfactory.h +++ b/src/plugins/designer/formeditorfactory.h @@ -45,7 +45,6 @@ namespace Internal { class FormEditorFactory : public Core::IEditorFactory { Q_OBJECT - public: FormEditorFactory(); diff --git a/src/plugins/designer/formeditorstack.cpp b/src/plugins/designer/formeditorstack.cpp index 6d7198445b1e5a5480205259d10922de56cd5046..202c5fadaa8c9a1965c8b045df76457e7c93895a 100644 --- a/src/plugins/designer/formeditorstack.cpp +++ b/src/plugins/designer/formeditorstack.cpp @@ -33,28 +33,21 @@ #include "formeditorw.h" #include "designerconstants.h" -#include <texteditor/basetextdocument.h> - -#include <coreplugin/editormanager/editormanager.h> -#include <coreplugin/icore.h> +#include <coreplugin/coreconstants.h> +#include <coreplugin/modemanager.h> +#include <coreplugin/imode.h> #include <utils/qtcassert.h> #include <QDesignerFormWindowInterface> #include <QDesignerFormWindowManagerInterface> #include <QDesignerFormEditorInterface> -#include "qt_private/formwindowbase_p.h" #include <QtCore/QDebug> namespace Designer { namespace Internal { -FormEditorStack::FormXmlData::FormXmlData() : - xmlEditor(0), formEditor(0) -{ -} - FormEditorStack::FormEditorStack(QWidget *parent) : QStackedWidget(parent), m_designerCore(0) @@ -62,28 +55,24 @@ FormEditorStack::FormEditorStack(QWidget *parent) : setObjectName(QLatin1String("FormEditorStack")); } -Designer::FormWindowEditor *FormEditorStack::createFormWindowEditor(DesignerXmlEditorEditable *xmlEditor) +void FormEditorStack::add(const EditorData &data) { - FormEditorW *few = FormEditorW::instance(); if (m_designerCore == 0) { // Initialize first time here - m_designerCore = few->designerEditor(); + m_designerCore = data.formEditor->formWindow()->core(); connect(m_designerCore->formWindowManager(), SIGNAL(activeFormWindowChanged(QDesignerFormWindowInterface*)), this, SLOT(updateFormWindowSelectionHandles())); + connect(Core::ModeManager::instance(), SIGNAL(currentModeAboutToChange(Core::IMode*)), + this, SLOT(modeAboutToChange(Core::IMode*))); } - FormXmlData data; - data.formEditor = few->createFormWindowEditor(this); - data.formEditor->setFile(xmlEditor->file()); - data.xmlEditor = xmlEditor; - addWidget(data.formEditor); - m_formEditors.append(data); - setFormEditorData(data.formEditor, xmlEditor->contents()); + if (Designer::Constants::Internal::debug) + qDebug() << "FormEditorStack::add" << data.xmlEditor << data.formEditor; + + m_formEditors.append(data); + addWidget(data.formEditor); - TextEditor::BaseTextDocument *document = qobject_cast<TextEditor::BaseTextDocument*>(xmlEditor->file()); - connect(document, SIGNAL(reloaded()), SLOT(reloadDocument())); if (Designer::Constants::Internal::debug) - qDebug() << "FormEditorStack::createFormWindowEditor" << data.formEditor; - return data.formEditor; + qDebug() << "FormEditorStack::add" << data.formEditor; } int FormEditorStack::indexOf(const QDesignerFormWindowInterface *fw) const @@ -125,7 +114,6 @@ bool FormEditorStack::removeFormWindowEditor(Core::IEditor *xmlEditor) const int i = indexOf(xmlEditor); if (i == -1) // Fail silently as this is invoked for all editors. return false; - disconnect(m_formEditors[i].formEditor->formWindow(), SIGNAL(changed()), this, SLOT(formChanged())); removeWidget(m_formEditors[i].formEditor->widget()); delete m_formEditors[i].formEditor; m_formEditors.removeAt(i); @@ -150,7 +138,7 @@ void FormEditorStack::updateFormWindowSelectionHandles() if (Designer::Constants::Internal::debug) qDebug() << "updateFormWindowSelectionHandles"; QDesignerFormWindowInterface *activeFormWindow = m_designerCore->formWindowManager()->activeFormWindow(); - foreach(const FormXmlData &fdm, m_formEditors) { + foreach(const EditorData &fdm, m_formEditors) { const bool active = activeFormWindow == fdm.formEditor->formWindow(); fdm.formEditor->updateFormWindowSelectionHandles(active); } @@ -162,39 +150,15 @@ Designer::FormWindowEditor *FormEditorStack::formWindowEditorForXmlEditor(const return i != -1 ? m_formEditors.at(i).formEditor : static_cast<Designer::FormWindowEditor *>(0); } -void FormEditorStack::reloadDocument() +void FormEditorStack::modeAboutToChange(Core::IMode *m) { - if (Designer::Constants::Internal::debug) - qDebug() << "FormEditorStack::reloadDocument()"; - const int index = currentIndex(); - if (index >= 0) - setFormEditorData(m_formEditors[index].formEditor, m_formEditors[index].xmlEditor->contents()); -} + if (Designer::Constants::Internal::debug && m) + qDebug() << "FormEditorStack::modeAboutToChange" << m->id(); -void FormEditorStack::setFormEditorData(Designer::FormWindowEditor *formEditor, const QString &contents) -{ - if (Designer::Constants::Internal::debug) - qDebug() << "FormEditorStack::setFormEditorData()"; - disconnect(formEditor->formWindow(), SIGNAL(changed()), this, SLOT(formChanged())); - formEditor->createNew(contents); - connect(formEditor->formWindow(), SIGNAL(changed()), SLOT(formChanged())); -} - -void FormEditorStack::formChanged() -{ - const int index = currentIndex(); - if (index < 0) - return; - if (Core::IEditor *currentEditor = Core::EditorManager::instance()->currentEditor()) { - if (m_formEditors[index].xmlEditor == currentEditor) { - FormXmlData &xmlData = m_formEditors[index]; - TextEditor::BaseTextDocument *doc = qobject_cast<TextEditor::BaseTextDocument*>(xmlData.xmlEditor->file()); - QTC_ASSERT(doc, return); - if (doc) // Save quietly (without spacer's warning). - if (const qdesigner_internal::FormWindowBase *fwb = qobject_cast<const qdesigner_internal::FormWindowBase *>(xmlData.formEditor->formWindow())) - doc->document()->setPlainText(fwb->fileContents()); - } - } + // Sync the editor when leaving design mode + if (m && m->id() == QLatin1String(Core::Constants::MODE_DESIGN)) + foreach(const EditorData &data, m_formEditors) + data.xmlEditor->syncXmlEditor(); } } // Internal diff --git a/src/plugins/designer/formeditorstack.h b/src/plugins/designer/formeditorstack.h index 994a892c6c0894f84c0cc5e818caa3df1528158c..94513924e524ba7633993a555fc86a7bea2507c7 100644 --- a/src/plugins/designer/formeditorstack.h +++ b/src/plugins/designer/formeditorstack.h @@ -30,6 +30,8 @@ #ifndef FORMEDITORSTACK_H #define FORMEDITORSTACK_H +#include "editordata.h" + #include <QtGui/QStackedWidget> #include <QtCore/QList> #include <QtCore/QString> @@ -41,6 +43,7 @@ QT_END_NAMESPACE namespace Core { class IEditor; + class IMode; } namespace Designer { @@ -49,11 +52,11 @@ class DesignerXmlEditorEditable; namespace Internal { -/** - * A wrapper for Qt Designer form editors, so that they can be used in Design mode. - * FormEditorW owns an instance of this class, and creates new form editors when - * needed. - */ +/* FormEditorStack: Maintains a stack of Qt Designer form windows embedded + * into a scrollarea and their associated XML editors. + * Takes care of updating the XML editor once design mode is left. + * Also updates the maincontainer resize handles when the active form + * window changes. */ class FormEditorStack : public QStackedWidget { Q_OBJECT @@ -61,29 +64,23 @@ class FormEditorStack : public QStackedWidget public: explicit FormEditorStack(QWidget *parent = 0); - Designer::FormWindowEditor *createFormWindowEditor(DesignerXmlEditorEditable *xmlEditor); + void add(const EditorData &d); bool removeFormWindowEditor(Core::IEditor *xmlEditor); + bool setVisibleEditor(Core::IEditor *xmlEditor); Designer::FormWindowEditor *formWindowEditorForXmlEditor(const Core::IEditor *xmlEditor) const; Designer::FormWindowEditor *formWindowEditorForFormWindow(const QDesignerFormWindowInterface *fw) const; FormWindowEditor *activeFormWindow() const; private slots: - void formChanged(); - void reloadDocument(); void updateFormWindowSelectionHandles(); + void modeAboutToChange(Core::IMode *); private: inline int indexOf(const QDesignerFormWindowInterface *) const; inline int indexOf(const Core::IEditor *xmlEditor) const; - void setFormEditorData(Designer::FormWindowEditor *formEditor, const QString &contents); - struct FormXmlData { - FormXmlData(); - DesignerXmlEditorEditable *xmlEditor; - Designer::FormWindowEditor *formEditor; - }; - QList<FormXmlData> m_formEditors; + QList<EditorData> m_formEditors; QDesignerFormEditorInterface *m_designerCore; }; diff --git a/src/plugins/designer/formeditorw.cpp b/src/plugins/designer/formeditorw.cpp index 98c2ea295bbc438356e261a9a7e9a280705cbf65..320be347a6338305d8d8a2be11d668c8af25f3b6 100644 --- a/src/plugins/designer/formeditorw.cpp +++ b/src/plugins/designer/formeditorw.cpp @@ -34,12 +34,12 @@ #include "settingsmanager.h" #include "settingspage.h" #include "editorwidget.h" +#include "editordata.h" #include "qtcreatorintegration.h" #include "designerxmleditor.h" #include "designercontext.h" #include "editorwidget.h" -#include <texteditor/basetextdocument.h> #include <coreplugin/modemanager.h> #include <coreplugin/designmode.h> #include <coreplugin/coreconstants.h> @@ -47,6 +47,7 @@ #include <coreplugin/uniqueidmanager.h> #include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/editormanager/editormanager.h> +#include <texteditor/texteditorsettings.h> #include <extensionsystem/pluginmanager.h> #include <utils/qtcassert.h> @@ -213,7 +214,7 @@ FormEditorW::~FormEditorW() m_self = 0; } -// Add an action to toggle the view state of a dock window +// Add an actioon to toggle the view state of a dock window void FormEditorW::addDockViewAction(Core::ActionManager *am, int index, const QList<int> &context, const QString &title, const QString &id) @@ -651,13 +652,27 @@ void FormEditorW::addToolAction(QAction *a, c1->addAction(command); } -FormWindowEditor *FormEditorW::createFormWindowEditor(QWidget* parentWidget) +EditorData FormEditorW::createEditor(QWidget *parent) { + if (Designer::Constants::Internal::debug) + qDebug() << "FormEditorW::createEditor"; + // Create and associate form and text editor. + EditorData data; m_fwm->closeAllPreviews(); - QDesignerFormWindowInterface *form = m_fwm->createFormWindow(0); + qdesigner_internal::FormWindowBase *form = qobject_cast<qdesigner_internal::FormWindowBase *>(m_fwm->createFormWindow(0)); + QTC_ASSERT(form, return data); connect(form, SIGNAL(toolChanged(int)), this, SLOT(toolChanged(int))); + form->setDesignerGrid(qdesigner_internal::FormWindowBase::defaultDesignerGrid()); qdesigner_internal::FormWindowBase::setupDefaultAction(form); - return new FormWindowEditor(form, parentWidget); + data.formEditor = new FormWindowEditor(form); + DesignerXmlEditor *xmlEditor = new DesignerXmlEditor(form, parent); + TextEditor::TextEditorSettings::instance()->initializeEditor(xmlEditor); + data.xmlEditor = xmlEditor->designerEditable(); + data.formEditor->setFile(data.xmlEditor->file()); + connect(data.formEditor, SIGNAL(formWindowSizeChanged(int,int)), + xmlEditor, SIGNAL(changed())); + m_editorWidget->add(data); + return data; } void FormEditorW::updateShortcut(QObject *command) @@ -681,11 +696,8 @@ void FormEditorW::currentEditorChanged(Core::IEditor *editor) QTC_ASSERT(xmlEditor, return); ensureInitStage(FullyInitialized); FormWindowEditor *fw = m_editorWidget->formWindowEditorForXmlEditor(xmlEditor); - if (fw) { - m_editorWidget->setVisibleEditor(xmlEditor); - } else { - fw = m_editorWidget->createFormWindowEditor(xmlEditor); - } + QTC_ASSERT(fw, return) + m_editorWidget->setVisibleEditor(xmlEditor); m_fwm->setActiveFormWindow(fw->formWindow()); m_actionGroupEditMode->setVisible(true); m_modeActionSeparator->setVisible(true); diff --git a/src/plugins/designer/formeditorw.h b/src/plugins/designer/formeditorw.h index 51893429e5be0a4a6af8a6c15ea9428e46096cb3..48617ab62fc5e0ff065dd9486c791b595f9b09bf 100644 --- a/src/plugins/designer/formeditorw.h +++ b/src/plugins/designer/formeditorw.h @@ -31,7 +31,6 @@ #define FORMEDITORW_H #include <QtCore/QObject> -#include <QtCore/QPointer> #include <QtCore/QStringList> #include <QtCore/QMap> @@ -45,9 +44,6 @@ class QDesignerFormWindowInterface; class QAction; class QActionGroup; -class QFocusEvent; - -class QWidget; class QSignalMapper; class QSettings; class QToolBar; @@ -64,7 +60,6 @@ class ActionContainer; class ICore; class IEditor; class Command; -class IMode; class DesignMode; } @@ -73,6 +68,7 @@ class FormWindowEditor; namespace Internal { +struct EditorData; class EditorWidget; class SettingsPage; class DesignerContext; @@ -113,11 +109,11 @@ public: // Deletes an existing instance if there is one. static void deleteInstance(); + EditorData createEditor(QWidget *parent); + inline QDesignerFormEditorInterface *designerEditor() const { return m_formeditor; } inline QWidget * const*designerSubWindows() const { return m_designerSubWindows; } - FormWindowEditor *createFormWindowEditor(QWidget* parentWidget); - FormWindowEditor *activeFormWindow() const; private slots: diff --git a/src/plugins/designer/formwindoweditor.cpp b/src/plugins/designer/formwindoweditor.cpp index bc43089985bf70296775dfeea39c512d64ae956e..df6f9a2b21964337368eb8722c2669eefa7bbf07 100644 --- a/src/plugins/designer/formwindoweditor.cpp +++ b/src/plugins/designer/formwindoweditor.cpp @@ -96,26 +96,12 @@ FormWindowEditor::FormWindowEditor(QDesignerFormWindowInterface *form, m_sessionNode(0), m_sessionWatcher(0) { - connect(formWindow(), SIGNAL(selectionChanged()), this, SIGNAL(changed())); connect(this, SIGNAL(formWindowSizeChanged(int,int)), this, SLOT(slotFormSizeChanged(int,int))); - connect(formWindow(), SIGNAL(changed()), this, SIGNAL(changed())); - } void FormWindowEditor::setFile(Core::IFile *file) { - if (m_file) { - disconnect(m_file, SIGNAL(changed()), this, SIGNAL(changed())); - disconnect(m_file, SIGNAL(changed()), this, SLOT(updateResources())); - } - - m_file = file; - formWindow()->setFileName(file->fileName()); - - if (m_file) { - connect(m_file, SIGNAL(changed()), this, SIGNAL(changed())); - connect(m_file, SIGNAL(changed()), this, SLOT(updateResources())); - } + m_file = file; } FormWindowEditor::~FormWindowEditor() @@ -127,26 +113,6 @@ FormWindowEditor::~FormWindowEditor() } } -bool FormWindowEditor::createNew(const QString &contents) -{ - if (Designer::Constants::Internal::debug) - qDebug() << Q_FUNC_INFO << contents.size() << "chars"; - - if (!formWindow()) - return false; - - formWindow()->setContents(contents); - if (!formWindow()->mainContainer()) - return false; - - if (qdesigner_internal::FormWindowBase *fw = qobject_cast<qdesigner_internal::FormWindowBase *>(formWindow())) - fw->setDesignerGrid(qdesigner_internal::FormWindowBase::defaultDesignerGrid()); - - initializeResources(); - - return true; -} - void FormWindowEditor::initializeResources(const QString & /* fileName */) { ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance(); @@ -167,11 +133,6 @@ void FormWindowEditor::initializeResources(const QString & /* fileName */) } updateResources(); - - QDesignerFormWindowManagerInterface *fwm = FormEditorW::instance()->designerEditor()->formWindowManager(); - fwm->setActiveFormWindow(formWindow()); - - emit changed(); } void FormWindowEditor::updateResources() @@ -202,13 +163,6 @@ Core::IFile *FormWindowEditor::file() const return m_file; } -QString FormWindowEditor::contents() const -{ - if (!formWindow()) - return QString(); - return formWindow()->contents(); -} - void FormWindowEditor::slotFormSizeChanged(int w, int h) { if (Designer::Constants::Internal::debug) @@ -217,5 +171,4 @@ void FormWindowEditor::slotFormSizeChanged(int w, int h) formWindow()->setDirty(true); static const QString geometry = QLatin1String("geometry"); FormEditorW::instance()->designerEditor()->propertyEditor()->setPropertyValue(geometry, QRect(0,0,w,h) ); - emit changed(); } diff --git a/src/plugins/designer/formwindoweditor.h b/src/plugins/designer/formwindoweditor.h index aeb59ef594fe7e803fee29b2e5bb7ba7fb465279..20cccbe09c3952fcb31d0a83241d6e31b20a07c3 100644 --- a/src/plugins/designer/formwindoweditor.h +++ b/src/plugins/designer/formwindoweditor.h @@ -30,7 +30,6 @@ #ifndef FORMWINDOWEDITOR_H #define FORMWINDOWEDITOR_H -#include "designer_export.h" #include "widgethost.h" #include <QtCore/QStringList> @@ -58,15 +57,10 @@ public: QWidget *parent = 0); ~FormWindowEditor(); - // IEditor - bool createNew(const QString &contents); void setFile(Core::IFile *file); QString contents() const; Core::IFile *file() const; -signals: - void changed(); - private slots: void updateResources(); void slotFormSizeChanged(int w, int h); @@ -74,8 +68,6 @@ private slots: private: void initializeResources(const QString &fileName = QString()); - QWidget *m_containerWidget; - QString m_displayName; QPointer<Core::IFile> m_file; QStringList m_originalUiQrcPaths; ProjectExplorer::SessionNode *m_sessionNode; diff --git a/src/plugins/designer/formwindowfile.cpp b/src/plugins/designer/formwindowfile.cpp index 15bac0bbd09b7882534435a13d4c964c10e5a7c7..2cd65a1848be57339d2bbd5d70ff0babd8040ea2 100644 --- a/src/plugins/designer/formwindowfile.cpp +++ b/src/plugins/designer/formwindowfile.cpp @@ -31,8 +31,8 @@ #include "designerconstants.h" #include <coreplugin/icore.h> -#include <coreplugin/editormanager/editormanager.h> #include <utils/reloadpromptutils.h> +#include <utils/qtcassert.h> #include <QtDesigner/QDesignerFormWindowInterface> #include <QtDesigner/QDesignerFormEditorInterface> @@ -42,17 +42,15 @@ #include <QtCore/QFile> #include <QtCore/QFileInfo> -#include <QtCore/QDir> #include <QtCore/QByteArray> #include <QtCore/QDebug> -using namespace Designer::Internal; -using namespace Designer::Constants; -using namespace SharedTools; +namespace Designer { +namespace Internal { FormWindowFile::FormWindowFile(QDesignerFormWindowInterface *form, QObject *parent) : Core::IFile(parent), - m_mimeType(QLatin1String(FORM_MIMETYPE)), + m_mimeType(QLatin1String(Designer::Constants::FORM_MIMETYPE)), m_formWindow(form) { } @@ -64,6 +62,8 @@ bool FormWindowFile::save(const QString &name /*= QString()*/) if (Designer::Constants::Internal::debug) qDebug() << Q_FUNC_INFO << name << "->" << actualName; + QTC_ASSERT(m_formWindow, return false); + if (actualName.isEmpty()) return false; @@ -94,9 +94,9 @@ QString FormWindowFile::fileName() const bool FormWindowFile::isModified() const { - if (Designer::Constants::Internal::debug) + if (Designer::Constants::Internal::debug > 1) qDebug() << Q_FUNC_INFO << m_formWindow->isDirty(); - return m_formWindow->isDirty(); + return m_formWindow && m_formWindow->isDirty(); } bool FormWindowFile::isReadOnly() const @@ -204,3 +204,11 @@ void FormWindowFile::setFileName(const QString &fname) { m_fileName = fname; } + +QDesignerFormWindowInterface *FormWindowFile::formWindow() const +{ + return m_formWindow; +} + +} // namespace Internal +} // namespace Designer diff --git a/src/plugins/designer/formwindowfile.h b/src/plugins/designer/formwindowfile.h index 873bdb98bcd2f4777885a11fc396be5f5b753484..e04d74a2a2e00df4b03918ae51a9da12f3aff084 100644 --- a/src/plugins/designer/formwindowfile.h +++ b/src/plugins/designer/formwindowfile.h @@ -32,8 +32,7 @@ #include <coreplugin/ifile.h> -#include "widgethost.h" -#include "designerconstants.h" +#include <QtCore/QPointer> QT_BEGIN_NAMESPACE class QDesignerFormWindowInterface; @@ -65,9 +64,12 @@ public: // Internal void setSuggestedFileName(const QString &fileName); + bool writeFile(const QString &fileName, QString &errorString) const; bool writeFile(QFile &file, QString &errorString) const; + QDesignerFormWindowInterface *formWindow() const; + signals: // Internal void reload(const QString &); @@ -78,10 +80,12 @@ public slots: private: const QString m_mimeType; + QString m_fileName; QString m_suggestedName; - - QDesignerFormWindowInterface *m_formWindow; + // Might actually go out of scope before the IEditor due + // to deleting the WidgetHost which owns it. + QPointer<QDesignerFormWindowInterface> m_formWindow; }; } // namespace Internal