diff options
author | Tobias Hunger <tobias.hunger@digia.com> | 2013-07-11 16:24:51 +0200 |
---|---|---|
committer | Tobias Hunger <tobias.hunger@digia.com> | 2013-08-01 14:23:00 +0200 |
commit | 78d3191363883db7023a5933a18b29c716b73d7d (patch) | |
tree | 1ba9cedae7b14c2676014bb947db186d25cd4e58 | |
parent | 0ea0c2f8769f06a22e34ec9dd55d89865a1697e8 (diff) |
UiCodeModel: Simplify usage
Change-Id: Id274db9ed3022364e7b65788f8313ae6cfa73326
Reviewed-by: Tobias Hunger <tobias.hunger@digia.com>
-rw-r--r-- | src/plugins/cmakeprojectmanager/cmakeproject.cpp | 129 | ||||
-rw-r--r-- | src/plugins/cmakeprojectmanager/cmakeproject.h | 10 | ||||
-rw-r--r-- | src/plugins/qt4projectmanager/qt4nodes.cpp | 84 | ||||
-rw-r--r-- | src/plugins/qt4projectmanager/qt4nodes.h | 10 | ||||
-rw-r--r-- | src/plugins/qt4projectmanager/qt4project.cpp | 16 | ||||
-rw-r--r-- | src/plugins/qt4projectmanager/qt4projectmanager.cpp | 73 | ||||
-rw-r--r-- | src/plugins/qt4projectmanager/qt4projectmanager.h | 10 | ||||
-rw-r--r-- | src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp | 4 | ||||
-rw-r--r-- | src/plugins/qtsupport/qtsupportplugin.cpp | 2 | ||||
-rw-r--r-- | src/plugins/qtsupport/uicodemodelsupport.cpp | 211 | ||||
-rw-r--r-- | src/plugins/qtsupport/uicodemodelsupport.h | 51 |
11 files changed, 269 insertions, 331 deletions
diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index 5c649e85cb..5a744264c0 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -62,13 +62,9 @@ #include <coreplugin/editormanager/editormanager.h> #include <coreplugin/variablemanager.h> -#include <QMap> #include <QDebug> #include <QDir> -#include <QDateTime> -#include <QProcess> #include <QFormLayout> -#include <QInputDialog> #include <QFileSystemWatcher> using namespace CMakeProjectManager; @@ -105,8 +101,7 @@ CMakeProject::CMakeProject(CMakeManager *manager, const QString &fileName) : m_manager(manager), m_activeTarget(0), m_fileName(fileName), - m_rootNode(new CMakeProjectNode(fileName)), - m_lastEditor(0) + m_rootNode(new CMakeProjectNode(fileName)) { setProjectContext(Core::Context(CMakeProjectManager::Constants::PROJECTCONTEXT)); setProjectLanguages(Core::Context(ProjectExplorer::Constants::LANG_CXX)); @@ -121,17 +116,6 @@ CMakeProject::CMakeProject(CMakeManager *manager, const QString &fileName) CMakeProject::~CMakeProject() { - // Remove CodeModel support - CppTools::CppModelManagerInterface *modelManager - = CppTools::CppModelManagerInterface::instance(); - QMap<QString, QtSupport::UiCodeModelSupport *>::const_iterator it, end; - it = m_uiCodeModelSupport.constBegin(); - end = m_uiCodeModelSupport.constEnd(); - for (; it!=end; ++it) { - modelManager->removeExtraEditorSupport(it.value()); - delete it.value(); - } - m_codeModelFuture.cancel(); delete m_rootNode; } @@ -632,15 +616,6 @@ bool CMakeProject::fromMap(const QVariantMap &map) makeStep->setBuildTarget(QLatin1String("all"), true); } - connect(Core::EditorManager::instance(), SIGNAL(editorAboutToClose(Core::IEditor*)), - this, SLOT(editorAboutToClose(Core::IEditor*))); - - connect(Core::EditorManager::instance(), SIGNAL(currentEditorChanged(Core::IEditor*)), - this, SLOT(editorChanged(Core::IEditor*))); - - connect(ProjectExplorer::ProjectExplorerPlugin::instance()->buildManager(), SIGNAL(buildStateChanged(ProjectExplorer::Project*)), - this, SLOT(buildStateChanged(ProjectExplorer::Project*))); - m_activeTarget = activeTarget(); if (m_activeTarget) connect(m_activeTarget, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)), @@ -768,109 +743,15 @@ void CMakeProject::updateRunConfigurations(Target *t) void CMakeProject::createUiCodeModelSupport() { -// qDebug()<<"creatUiCodeModelSupport()"; - CppTools::CppModelManagerInterface *modelManager - = CppTools::CppModelManagerInterface::instance(); - - // First move all to - QMap<QString, QtSupport::UiCodeModelSupport *> oldCodeModelSupport; - oldCodeModelSupport = m_uiCodeModelSupport; - m_uiCodeModelSupport.clear(); + QHash<QString, QString> uiFileHash; // Find all ui files foreach (const QString &uiFile, m_files) { - if (uiFile.endsWith(QLatin1String(".ui"))) { - // UI file, not convert to - QString uiHeaderFilePath = uiHeaderFile(uiFile); - QMap<QString, QtSupport::UiCodeModelSupport *>::iterator it - = oldCodeModelSupport.find(uiFile); - if (it != oldCodeModelSupport.end()) { - // qDebug()<<"updated old codemodelsupport"; - QtSupport::UiCodeModelSupport *cms = it.value(); - cms->setFileName(uiHeaderFilePath); - m_uiCodeModelSupport.insert(it.key(), cms); - oldCodeModelSupport.erase(it); - } else { - // qDebug()<<"adding new codemodelsupport"; - QtSupport::UiCodeModelSupport *cms = new QtSupport::UiCodeModelSupport(modelManager, this, uiFile, uiHeaderFilePath); - m_uiCodeModelSupport.insert(uiFile, cms); - modelManager->addExtraEditorSupport(cms); - } - } - } - - // Remove old - QMap<QString, QtSupport::UiCodeModelSupport *>::const_iterator it, end; - end = oldCodeModelSupport.constEnd(); - for (it = oldCodeModelSupport.constBegin(); it!=end; ++it) { - modelManager->removeExtraEditorSupport(it.value()); - delete it.value(); - } -} - -void CMakeProject::updateCodeModelSupportFromEditor(const QString &uiFileName, - const QString &contents) -{ - const QMap<QString, QtSupport::UiCodeModelSupport *>::const_iterator it = - m_uiCodeModelSupport.constFind(uiFileName); - if (it != m_uiCodeModelSupport.constEnd()) - it.value()->updateFromEditor(contents); -} - -void CMakeProject::editorChanged(Core::IEditor *editor) -{ - // Handle old editor - if (m_lastEditor && isFormWindowDocument(m_lastEditor->document())) { - disconnect(m_lastEditor->document(), SIGNAL(changed()), this, SLOT(uiDocumentContentsChanged())); - if (m_dirtyUic) { - const QString contents = formWindowEditorContents(m_lastEditor); - updateCodeModelSupportFromEditor(m_lastEditor->document()->filePath(), contents); - m_dirtyUic = false; - } + if (uiFile.endsWith(QLatin1String(".ui"))) + uiFileHash.insert(uiFile, uiHeaderFile(uiFile)); } - m_lastEditor = editor; - - // Handle new editor - if (editor && isFormWindowDocument(editor->document())) - connect(editor->document(), SIGNAL(changed()), this, SLOT(uiDocumentContentsChanged())); -} - -void CMakeProject::editorAboutToClose(Core::IEditor *editor) -{ - if (m_lastEditor == editor) { - // Oh no our editor is going to be closed - // get the content first - if (isFormWindowDocument(m_lastEditor->document())) { - disconnect(m_lastEditor->document(), SIGNAL(changed()), this, SLOT(uiDocumentContentsChanged())); - if (m_dirtyUic) { - const QString contents = formWindowEditorContents(m_lastEditor); - updateCodeModelSupportFromEditor(m_lastEditor->document()->filePath(), contents); - m_dirtyUic = false; - } - } - m_lastEditor = 0; - } -} - -void CMakeProject::uiDocumentContentsChanged() -{ - // cast sender, get filename - if (!m_dirtyUic && isFormWindowDocument(sender())) - m_dirtyUic = true; -} - -void CMakeProject::buildStateChanged(ProjectExplorer::Project *project) -{ - if (project == this) { - if (!ProjectExplorer::ProjectExplorerPlugin::instance()->buildManager()->isBuilding(this)) { - QMap<QString, QtSupport::UiCodeModelSupport *>::const_iterator it, end; - end = m_uiCodeModelSupport.constEnd(); - for (it = m_uiCodeModelSupport.constBegin(); it != end; ++it) { - it.value()->updateFromBuild(); - } - } - } + QtSupport::UiCodeModelManager::instance()->update(this, uiFileHash); } // CMakeFile diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h index 38c8ebddb1..804eecc756 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.h +++ b/src/plugins/cmakeprojectmanager/cmakeproject.h @@ -52,7 +52,6 @@ class QFileSystemWatcher; QT_END_NAMESPACE namespace ProjectExplorer { class Target; } -namespace QtSupport { class UiCodeModelSupport; } namespace CMakeProjectManager { namespace Internal { @@ -117,17 +116,12 @@ private slots: void activeTargetWasChanged(ProjectExplorer::Target *target); void changeActiveBuildConfiguration(ProjectExplorer::BuildConfiguration*); - void editorChanged(Core::IEditor *editor); - void editorAboutToClose(Core::IEditor *editor); - void uiDocumentContentsChanged(); - void buildStateChanged(ProjectExplorer::Project *project); void updateRunConfigurations(); private: void buildTree(CMakeProjectNode *rootNode, QList<ProjectExplorer::FileNode *> list); void gatherFileNodes(ProjectExplorer::FolderNode *parent, QList<ProjectExplorer::FileNode *> &list); ProjectExplorer::FolderNode *findOrCreateFolder(CMakeProjectNode *rootNode, QString directory); - void updateCodeModelSupportFromEditor(const QString &uiFileName, const QString &contents); void createUiCodeModelSupport(); QString uiHeaderFile(const QString &uiFile); void updateRunConfigurations(ProjectExplorer::Target *t); @@ -145,10 +139,6 @@ private: QFileSystemWatcher *m_watcher; QSet<QString> m_watchedFiles; QFuture<void> m_codeModelFuture; - - QMap<QString, QtSupport::UiCodeModelSupport *> m_uiCodeModelSupport; - Core::IEditor *m_lastEditor; - bool m_dirtyUic; }; class CMakeCbpParser : public QXmlStreamReader diff --git a/src/plugins/qt4projectmanager/qt4nodes.cpp b/src/plugins/qt4projectmanager/qt4nodes.cpp index d4a1088e42..2f4426902f 100644 --- a/src/plugins/qt4projectmanager/qt4nodes.cpp +++ b/src/plugins/qt4projectmanager/qt4nodes.cpp @@ -1452,23 +1452,12 @@ Qt4ProFileNode::Qt4ProFileNode(Qt4Project *project, if (parent) setParent(parent); - connect(ProjectExplorer::ProjectExplorerPlugin::instance()->buildManager(), SIGNAL(buildStateChanged(ProjectExplorer::Project*)), - this, SLOT(buildStateChanged(ProjectExplorer::Project*))); - connect(&m_parseFutureWatcher, SIGNAL(finished()), this, SLOT(applyAsyncEvaluate())); } Qt4ProFileNode::~Qt4ProFileNode() { - CppTools::CppModelManagerInterface *modelManager - = CppTools::CppModelManagerInterface::instance(); - QMap<QString, QtSupport::UiCodeModelSupport *>::const_iterator it, end; - end = m_uiCodeModelSupport.constEnd(); - for (it = m_uiCodeModelSupport.constBegin(); it != end; ++it) { - modelManager->removeExtraEditorSupport(it.value()); - delete it.value(); - } m_parseFutureWatcher.waitForFinished(); if (m_readerExact) { // Oh we need to clean up @@ -1486,13 +1475,6 @@ bool Qt4ProFileNode::isParent(Qt4ProFileNode *node) return false; } -void Qt4ProFileNode::buildStateChanged(ProjectExplorer::Project *project) -{ - if (project == m_project - && !ProjectExplorer::ProjectExplorerPlugin::instance()->buildManager()->isBuilding(m_project)) - updateCodeModelSupportFromBuild(); -} - bool Qt4ProFileNode::hasBuildTargets() const { return hasBuildTargets(projectType()); @@ -1525,9 +1507,9 @@ QString Qt4ProFileNode::singleVariableValue(const Qt4Variable var) const return values.isEmpty() ? QString() : values.first(); } -QStringList Qt4ProFileNode::uiFiles() const +QHash<QString, QString> Qt4ProFileNode::uiFiles() const { - return m_uiHeaderFiles; + return m_uiFiles; } void Qt4ProFileNode::emitProFileUpdatedRecursive() @@ -1982,7 +1964,7 @@ void Qt4ProFileNode::applyEvaluate(EvalResult evalResult, bool async) setParseInProgress(false); - createUiCodeModelSupport(); + updateUiFiles(); m_project->destroyProFileReader(m_readerExact); m_project->destroyProFileReader(m_readerCumulative); @@ -2244,26 +2226,6 @@ QString Qt4ProFileNode::buildDir(Qt4BuildConfiguration *bc) const return QDir::cleanPath(QDir(bc->buildDirectory()).absoluteFilePath(relativeDir)); } -void Qt4ProFileNode::updateCodeModelSupportFromBuild() -{ - QMap<QString, QtSupport::UiCodeModelSupport *>::const_iterator it, end; - end = m_uiCodeModelSupport.constEnd(); - for (it = m_uiCodeModelSupport.constBegin(); it != end; ++it) - it.value()->updateFromBuild(); -} - -void Qt4ProFileNode::updateCodeModelSupportFromEditor(const QString &uiFileName, - const QString &contents) -{ - const QMap<QString, QtSupport::UiCodeModelSupport *>::const_iterator it = - m_uiCodeModelSupport.constFind(uiFileName); - if (it != m_uiCodeModelSupport.constEnd()) - it.value()->updateFromEditor(contents); - foreach (ProjectExplorer::ProjectNode *pro, subProjectNodes()) - if (Qt4ProFileNode *qt4proFileNode = qobject_cast<Qt4ProFileNode *>(pro)) - qt4proFileNode->updateCodeModelSupportFromEditor(uiFileName, contents); -} - QString Qt4ProFileNode::uiDirectory() const { const Qt4VariablesHash::const_iterator it = m_varValues.constFind(UiDirVar); @@ -2281,18 +2243,9 @@ QString Qt4ProFileNode::uiHeaderFile(const QString &uiDir, const QString &formFi return QDir::cleanPath(uiHeaderFilePath); } -void Qt4ProFileNode::createUiCodeModelSupport() +void Qt4ProFileNode::updateUiFiles() { -// qDebug()<<"creatUiCodeModelSupport()"; - CppTools::CppModelManagerInterface *modelManager - = CppTools::CppModelManagerInterface::instance(); - - // First move all to - QMap<QString, QtSupport::UiCodeModelSupport *> oldCodeModelSupport; - oldCodeModelSupport = m_uiCodeModelSupport; - m_uiCodeModelSupport.clear(); - - m_uiHeaderFiles.clear(); + m_uiFiles.clear(); // Only those two project types can have ui files for us if (m_projectType == ApplicationTemplate || m_projectType == LibraryTemplate) { @@ -2303,30 +2256,7 @@ void Qt4ProFileNode::createUiCodeModelSupport() // Find the UiDir, there can only ever be one const QString uiDir = uiDirectory(); - foreach (const ProjectExplorer::FileNode *uiFile, uiFiles) { - const QString uiHeaderFilePath = uiHeaderFile(uiDir, uiFile->path()); - m_uiHeaderFiles << uiHeaderFilePath; -// qDebug()<<"code model support for "<<uiFile->path()<<" "<<uiHeaderFilePath; - QMap<QString, QtSupport::UiCodeModelSupport *>::iterator it = oldCodeModelSupport.find(uiFile->path()); - if (it != oldCodeModelSupport.end()) { -// qDebug()<<"updated old codemodelsupport"; - QtSupport::UiCodeModelSupport *cms = it.value(); - cms->setFileName(uiHeaderFilePath); - m_uiCodeModelSupport.insert(it.key(), cms); - oldCodeModelSupport.erase(it); - } else { -// qDebug()<<"adding new codemodelsupport"; - QtSupport::UiCodeModelSupport *cms = new QtSupport::UiCodeModelSupport(modelManager, m_project, uiFile->path(), uiHeaderFilePath); - m_uiCodeModelSupport.insert(uiFile->path(), cms); - modelManager->addExtraEditorSupport(cms); - } - } - } - // Remove old - QMap<QString, QtSupport::UiCodeModelSupport *>::const_iterator it, end; - end = oldCodeModelSupport.constEnd(); - for (it = oldCodeModelSupport.constBegin(); it!=end; ++it) { - modelManager->removeExtraEditorSupport(it.value()); - delete it.value(); + foreach (const ProjectExplorer::FileNode *uiFile, uiFiles) + m_uiFiles.insert(uiFile->path(), uiHeaderFile(uiDir, uiFile->path())); } } diff --git a/src/plugins/qt4projectmanager/qt4nodes.h b/src/plugins/qt4projectmanager/qt4nodes.h index 5021ac809d..1b51311d86 100644 --- a/src/plugins/qt4projectmanager/qt4nodes.h +++ b/src/plugins/qt4projectmanager/qt4nodes.h @@ -369,15 +369,12 @@ public: return !m_subProjectsNotToDeploy.contains(filePath); } - void updateCodeModelSupportFromBuild(); - void updateCodeModelSupportFromEditor(const QString &uiFileName, const QString &contents); - QString sourceDir() const; QString buildDir(Qt4BuildConfiguration *bc = 0) const; QString uiDirectory() const; static QString uiHeaderFile(const QString &uiDir, const QString &formFile); - QStringList uiFiles() const; + QHash<QString, QString> uiFiles() const; const Qt4ProFileNode *findProFileFor(const QString &string) const; TargetInformation targetInformation() const; @@ -409,7 +406,6 @@ public slots: void asyncUpdate(); private slots: - void buildStateChanged(ProjectExplorer::Project*); void applyAsyncEvaluate(); private: @@ -422,7 +418,7 @@ private: typedef QHash<Qt4Variable, QStringList> Qt4VariablesHash; - void createUiCodeModelSupport(); + void updateUiFiles(); QStringList fileListForVar(QtSupport::ProFileReader *readerExact, QtSupport::ProFileReader *readerCumulative, const QString &varName, const QString &projectDir, const QString &buildDir) const; @@ -450,7 +446,7 @@ private: InstallsList m_installsList; friend class Qt4NodeHierarchy; - QStringList m_uiHeaderFiles; + QHash<QString, QString> m_uiFiles; // ui-file path, ui header path // Async stuff QFutureWatcher<EvalResult> m_parseFutureWatcher; diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp index adb241026f..d470c79ae3 100644 --- a/src/plugins/qt4projectmanager/qt4project.cpp +++ b/src/plugins/qt4projectmanager/qt4project.cpp @@ -57,6 +57,7 @@ #include <proparser/qmakevfs.h> #include <qtsupport/profilereader.h> #include <qtsupport/qtkitinformation.h> +#include <qtsupport/uicodemodelsupport.h> #include <QDebug> #include <QDir> @@ -107,6 +108,7 @@ void updateBoilerPlateCodeFiles(const AbstractMobileApp *app, const QString &pro } } } + } // namespace namespace Qt4ProjectManager { @@ -532,6 +534,7 @@ void Qt4Project::updateCppCodeModel() qtVersionForPart = ProjectPart::Qt5; } + QHash<QString, QString> uiCodeModelData; QStringList allFiles; foreach (Qt4ProFileNode *pro, proFiles) { ProjectPart::Ptr part(new ProjectPart); @@ -579,10 +582,14 @@ void Qt4Project::updateCppCodeModel() allFiles << file; part->files << ProjectFile(file, ProjectFile::CXXHeader); } - foreach (const QString &file, pro->uiFiles()) { - allFiles << file; - part->files << ProjectFile(file, ProjectFile::CXXHeader); + + // Ui Files: + QHash<QString, QString> uiData = pro->uiFiles(); + for (QHash<QString, QString>::const_iterator i = uiData.constBegin(); i != uiData.constEnd(); ++i) { + allFiles << i.value(); + part->files << ProjectFile(i.value(), ProjectFile::CXXHeader); } + uiCodeModelData.unite(uiData); part->files.prepend(ProjectFile(CppTools::CppModelManagerInterface::configurationFileName(), ProjectFile::CXXSource)); @@ -602,6 +609,9 @@ void Qt4Project::updateCppCodeModel() setProjectLanguage(ProjectExplorer::Constants::LANG_CXX, !allFiles.isEmpty()); + // Also update Ui Code Model Support: + QtSupport::UiCodeModelManager::instance()->update(this, uiCodeModelData); + m_codeModelFuture = modelmanager->updateProjectInfo(pinfo); } diff --git a/src/plugins/qt4projectmanager/qt4projectmanager.cpp b/src/plugins/qt4projectmanager/qt4projectmanager.cpp index f0f7d2620c..395fa9d4fb 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanager.cpp +++ b/src/plugins/qt4projectmanager/qt4projectmanager.cpp @@ -70,27 +70,11 @@ static const char *qt4FileTypes[] = { "Qt4ResourceFiles" }; -// Test for form editor (loosely coupled) -static inline bool isFormWindowDocument(const QObject *o) -{ - return o && !qstrcmp(o->metaObject()->className(), "Designer::Internal::FormWindowFile"); -} - -// Return contents of form editor (loosely coupled) -static inline QString formWindowEditorContents(const QObject *editor) -{ - const QVariant contentV = editor->property("contents"); - QTC_ASSERT(contentV.isValid(), return QString()); - return contentV.toString(); -} - Qt4Manager::Qt4Manager(Qt4ProjectManagerPlugin *plugin) : m_plugin(plugin), m_contextNode(0), m_contextProject(0), - m_contextFile(0), - m_lastEditor(0), - m_dirty(false) + m_contextFile(0) { } @@ -114,61 +98,6 @@ void Qt4Manager::notifyChanged(const QString &name) pro->notifyChanged(name); } -void Qt4Manager::init() -{ - connect(Core::EditorManager::instance(), SIGNAL(editorAboutToClose(Core::IEditor*)), - this, SLOT(editorAboutToClose(Core::IEditor*))); - - connect(Core::EditorManager::instance(), SIGNAL(currentEditorChanged(Core::IEditor*)), - this, SLOT(editorChanged(Core::IEditor*))); -} - -void Qt4Manager::editorChanged(Core::IEditor *editor) -{ - // Handle old editor - if (m_lastEditor && isFormWindowDocument(m_lastEditor->document())) { - disconnect(m_lastEditor->document(), SIGNAL(changed()), this, SLOT(uiDocumentContentsChanged())); - - if (m_dirty) { - const QString contents = formWindowEditorContents(m_lastEditor); - foreach (Qt4Project *project, m_projects) - project->rootQt4ProjectNode()->updateCodeModelSupportFromEditor(m_lastEditor->document()->filePath(), contents); - m_dirty = false; - } - } - - m_lastEditor = editor; - - // Handle new editor - if (m_lastEditor && isFormWindowDocument(m_lastEditor->document())) - connect(m_lastEditor->document(), SIGNAL(changed()), this, SLOT(uiDocumentContentsChanged())); -} - -void Qt4Manager::editorAboutToClose(Core::IEditor *editor) -{ - if (m_lastEditor == editor) { - // Oh no our editor is going to be closed - // get the content first - if (isFormWindowDocument(m_lastEditor->document())) { - disconnect(m_lastEditor->document(), SIGNAL(changed()), this, SLOT(uiDocumentContentsChanged())); - if (m_dirty) { - const QString contents = formWindowEditorContents(m_lastEditor); - foreach (Qt4Project *project, m_projects) - project->rootQt4ProjectNode()->updateCodeModelSupportFromEditor(m_lastEditor->document()->filePath(), contents); - m_dirty = false; - } - } - m_lastEditor = 0; - } -} - -void Qt4Manager::uiDocumentContentsChanged() -{ - // cast sender, get filename - if (!m_dirty && isFormWindowDocument(sender())) - m_dirty = true; -} - QString Qt4Manager::mimeType() const { return QLatin1String(Qt4ProjectManager::Constants::PROFILE_MIMETYPE); diff --git a/src/plugins/qt4projectmanager/qt4projectmanager.h b/src/plugins/qt4projectmanager/qt4projectmanager.h index 80432106b9..cf30ac99f8 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanager.h +++ b/src/plugins/qt4projectmanager/qt4projectmanager.h @@ -68,8 +68,6 @@ public: Qt4Manager(Internal::Qt4ProjectManagerPlugin *plugin); ~Qt4Manager(); - void init(); - void registerProject(Qt4Project *project); void unregisterProject(Qt4Project *project); void notifyChanged(const QString &name); @@ -103,11 +101,6 @@ public slots: void buildFileContextMenu(); void buildFile(); -private slots: - void editorAboutToClose(Core::IEditor *editor); - void uiDocumentContentsChanged(); - void editorChanged(Core::IEditor*); - private: QList<Qt4Project *> m_projects; void handleSubDirContextMenu(Action action, bool isFileBuild); @@ -122,9 +115,6 @@ private: ProjectExplorer::Node *m_contextNode; ProjectExplorer::Project *m_contextProject; ProjectExplorer::FileNode *m_contextFile; - - Core::IEditor *m_lastEditor; - bool m_dirty; }; } // namespace Qt4ProjectManager diff --git a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp index 1a52c99677..75d0de2fb8 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp +++ b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp @@ -296,9 +296,7 @@ bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString * } void Qt4ProjectManagerPlugin::extensionsInitialized() -{ - m_qt4ProjectManager->init(); -} +{ } void Qt4ProjectManagerPlugin::startupProjectChanged() { diff --git a/src/plugins/qtsupport/qtsupportplugin.cpp b/src/plugins/qtsupport/qtsupportplugin.cpp index 964d969c19..7a1683466a 100644 --- a/src/plugins/qtsupport/qtsupportplugin.cpp +++ b/src/plugins/qtsupport/qtsupportplugin.cpp @@ -34,6 +34,7 @@ #include "qtkitinformation.h" #include "qtversionmanager.h" #include "qtfeatureprovider.h" +#include "uicodemodelsupport.h" #include "profilereader.h" @@ -66,6 +67,7 @@ bool QtSupportPlugin::initialize(const QStringList &arguments, QString *errorMes return false; QtVersionManager *mgr = new QtVersionManager; addAutoReleasedObject(mgr); + addAutoReleasedObject(new UiCodeModelManager); QtFeatureProvider *featureMgr = new QtFeatureProvider; addAutoReleasedObject(featureMgr); diff --git a/src/plugins/qtsupport/uicodemodelsupport.cpp b/src/plugins/qtsupport/uicodemodelsupport.cpp index 47d4fc0463..c5552b39b3 100644 --- a/src/plugins/qtsupport/uicodemodelsupport.cpp +++ b/src/plugins/qtsupport/uicodemodelsupport.cpp @@ -31,9 +31,16 @@ #include "qtkitinformation.h" +#include <coreplugin/editormanager/editormanager.h> +#include <coreplugin/editormanager/ieditor.h> +#include <cpptools/cppmodelmanagerinterface.h> #include <projectexplorer/buildconfiguration.h> +#include <projectexplorer/buildmanager.h> #include <projectexplorer/project.h> +#include <projectexplorer/projectexplorer.h> +#include <projectexplorer/session.h> #include <projectexplorer/target.h> +#include <utils/qtcassert.h> #include <QFile> #include <QFileInfo> @@ -42,20 +49,34 @@ enum { debug = 0 }; using namespace CPlusPlus; +// Test for form editor (loosely coupled) +static inline bool isFormWindowDocument(const QObject *o) +{ + return o && !qstrcmp(o->metaObject()->className(), "Designer::Internal::FormWindowFile"); +} + +// Return contents of form editor (loosely coupled) +static inline QString formWindowEditorContents(const QObject *editor) +{ + const QVariant contentV = editor->property("contents"); + QTC_ASSERT(contentV.isValid(), return QString()); + return contentV.toString(); +} + namespace QtSupport { UiCodeModelSupport::UiCodeModelSupport(CppTools::CppModelManagerInterface *modelmanager, ProjectExplorer::Project *project, - const QString &source, + const QString &uiFile, const QString &uiHeaderFile) : CppTools::AbstractEditorSupport(modelmanager), m_project(project), - m_sourceName(source), - m_fileName(uiHeaderFile), + m_uiFileName(uiFile), + m_headerFileName(uiHeaderFile), m_state(BARE) { if (debug) - qDebug()<<"ctor UiCodeModelSupport for"<<m_sourceName<<uiHeaderFile; + qDebug()<<"ctor UiCodeModelSupport for"<<m_uiFileName<<uiHeaderFile; connect(&m_process, SIGNAL(finished(int)), this, SLOT(finishProcess())); } @@ -63,21 +84,21 @@ UiCodeModelSupport::UiCodeModelSupport(CppTools::CppModelManagerInterface *model UiCodeModelSupport::~UiCodeModelSupport() { if (debug) - qDebug()<<"dtor ~UiCodeModelSupport for"<<m_sourceName; + qDebug()<<"dtor ~UiCodeModelSupport for"<<m_uiFileName; } void UiCodeModelSupport::init() const { if (m_state != BARE) return; - QDateTime sourceTime = QFileInfo(m_sourceName).lastModified(); - QFileInfo uiHeaderFileInfo(m_fileName); + QDateTime sourceTime = QFileInfo(m_uiFileName).lastModified(); + QFileInfo uiHeaderFileInfo(m_headerFileName); QDateTime uiHeaderTime = uiHeaderFileInfo.exists() ? uiHeaderFileInfo.lastModified() : QDateTime(); if (uiHeaderTime.isValid() && (uiHeaderTime > sourceTime)) { - QFile file(m_fileName); + QFile file(m_headerFileName); if (file.open(QFile::ReadOnly | QFile::Text)) { if (debug) - qDebug()<<"ui*h file is more recent then source file, using information from ui*h file"<<m_fileName; + qDebug()<<"ui*h file is more recent then source file, using information from ui*h file"<<m_headerFileName; QTextStream stream(&file); m_contents = stream.readAll().toUtf8(); m_cacheTime = uiHeaderTime; @@ -88,7 +109,7 @@ void UiCodeModelSupport::init() const if (debug) qDebug()<<"ui*h file not found, or not recent enough, trying to create it on the fly"; - QFile file(m_sourceName); + QFile file(m_uiFileName); if (file.open(QFile::ReadOnly | QFile::Text)) { QTextStream stream(&file); const QString contents = stream.readAll(); @@ -107,7 +128,7 @@ void UiCodeModelSupport::init() const } } else { if (debug) - qDebug()<<"Could open "<<m_sourceName<<"needed for the cpp model"; + qDebug()<<"Could open "<<m_uiFileName<<"needed for the cpp model"; m_contents = QByteArray(); m_state = FINISHED; } @@ -126,14 +147,19 @@ QByteArray UiCodeModelSupport::contents() const return m_contents; } +QString UiCodeModelSupport::uiFileName() const +{ + return m_uiFileName; +} + QString UiCodeModelSupport::fileName() const { - return m_fileName; + return m_headerFileName; } -void UiCodeModelSupport::setFileName(const QString &name) +void UiCodeModelSupport::setHeaderFileName(const QString &name) { - if (m_fileName == name && m_cacheTime.isValid()) + if (m_headerFileName == name && m_cacheTime.isValid()) return; if (m_state == RUNNING) @@ -142,7 +168,7 @@ void UiCodeModelSupport::setFileName(const QString &name) if (debug) qDebug() << "UiCodeModelSupport::setFileName"<<name; - m_fileName = name; + m_headerFileName = name; m_contents.clear(); m_cacheTime = QDateTime(); m_state = BARE; @@ -189,20 +215,20 @@ void UiCodeModelSupport::updateFromEditor(const QString &formEditorContents) void UiCodeModelSupport::updateFromBuild() { if (debug) - qDebug()<<"UiCodeModelSupport::updateFromBuild() for file"<<m_sourceName; + qDebug()<<"UiCodeModelSupport::updateFromBuild() for file"<<m_uiFileName; if (m_state == BARE) init(); if (m_state == RUNNING) finishProcess(); // This is mostly a fall back for the cases when uic couldn't be run // it pays special attention to the case where a ui_*h was newly created - QDateTime sourceTime = QFileInfo(m_sourceName).lastModified(); + QDateTime sourceTime = QFileInfo(m_uiFileName).lastModified(); if (m_cacheTime.isValid() && m_cacheTime >= sourceTime) { if (debug) qDebug()<<"Cache is still more recent then source"; return; } else { - QFileInfo fi(m_fileName); + QFileInfo fi(m_headerFileName); QDateTime uiHeaderTime = fi.exists() ? fi.lastModified() : QDateTime(); if (uiHeaderTime.isValid() && (uiHeaderTime > sourceTime)) { if (m_cacheTime >= uiHeaderTime) @@ -210,7 +236,7 @@ void UiCodeModelSupport::updateFromBuild() if (debug) qDebug()<<"found ui*h updating from it"; - QFile file(m_fileName); + QFile file(m_headerFileName); if (file.open(QFile::ReadOnly | QFile::Text)) { QTextStream stream(&file); m_contents = stream.readAll().toUtf8(); @@ -277,4 +303,151 @@ bool UiCodeModelSupport::finishProcess() const return true; } +UiCodeModelManager *UiCodeModelManager::m_instance = 0; + +UiCodeModelManager::UiCodeModelManager() : + m_lastEditor(0), + m_dirty(false) +{ + m_instance = this; + ProjectExplorer::BuildManager *bm + = ProjectExplorer::ProjectExplorerPlugin::instance()->buildManager(); + connect(bm, SIGNAL(buildStateChanged(ProjectExplorer::Project*)), + this, SLOT(buildStateHasChanged(ProjectExplorer::Project*))); + connect(ProjectExplorer::ProjectExplorerPlugin::instance()->session(), + SIGNAL(projectRemoved(ProjectExplorer::Project*)), + this, SLOT(projectWasRemoved(ProjectExplorer::Project*))); + + connect(Core::EditorManager::instance(), SIGNAL(editorAboutToClose(Core::IEditor*)), + this, SLOT(editorIsAboutToClose(Core::IEditor*))); + connect(Core::EditorManager::instance(), SIGNAL(currentEditorChanged(Core::IEditor*)), + this, SLOT(editorWasChanged(Core::IEditor*))); +} + +UiCodeModelManager *UiCodeModelManager::instance() +{ + return m_instance; +} + +UiCodeModelManager::~UiCodeModelManager() +{ + m_instance = 0; +} + +static UiCodeModelSupport *findUiFile(const QList<UiCodeModelSupport *> &range, const QString &uiFile) +{ + foreach (UiCodeModelSupport *support, range) { + if (support->uiFileName() == uiFile) + return support; + } + return 0; +} + +void UiCodeModelManager::update(ProjectExplorer::Project *project, QHash<QString, QString> uiHeaders) +{ + CppTools::CppModelManagerInterface *mm = CppTools::CppModelManagerInterface::instance(); + + // Find support to add/update: + QList<UiCodeModelSupport *> oldSupport = m_projectUiSupport.value(project); + QList<UiCodeModelSupport *> newSupport; + QHash<QString, QString>::const_iterator it; + for (it = uiHeaders.constBegin(); it != uiHeaders.constEnd(); ++it) { + if (UiCodeModelSupport *support = findUiFile(oldSupport, it.key())) { + support->setHeaderFileName(it.value()); + oldSupport.removeOne(support); + newSupport.append(support); + } else { + UiCodeModelSupport *cms = new UiCodeModelSupport(mm, project, it.key(), it.value()); + newSupport.append(cms); + mm->addEditorSupport(cms); + } + } + + // Remove old: + foreach (UiCodeModelSupport *support, oldSupport) { + mm->removeEditorSupport(support); + delete support; + } + + // Update state: + m_projectUiSupport.insert(project, newSupport); +} + +void UiCodeModelManager::updateContents(const QString &uiFileName, const QString &contents) +{ + QHash<ProjectExplorer::Project *, QList<UiCodeModelSupport *> >::iterator i; + for (i = m_projectUiSupport.begin(); i != m_projectUiSupport.end(); ++i) { + foreach (UiCodeModelSupport *support, i.value()) { + if (support->uiFileName() == uiFileName) + support->updateFromEditor(contents); + } + } +} + +void UiCodeModelManager::buildStateHasChanged(ProjectExplorer::Project *project) +{ + if (ProjectExplorer::ProjectExplorerPlugin::instance()->buildManager()->isBuilding(project)) + return; + + QList<UiCodeModelSupport *> projectSupport = m_projectUiSupport.value(project); + foreach (UiCodeModelSupport *const i, projectSupport) + i->updateFromBuild(); +} + +void UiCodeModelManager::projectWasRemoved(ProjectExplorer::Project *project) +{ + CppTools::CppModelManagerInterface *mm = CppTools::CppModelManagerInterface::instance(); + + QList<UiCodeModelSupport *> projectSupport = m_projectUiSupport.value(project); + foreach (UiCodeModelSupport *const i, projectSupport) { + mm->removeEditorSupport(i); + delete i; + } + + m_projectUiSupport.remove(project); +} + +void UiCodeModelManager::editorIsAboutToClose(Core::IEditor *editor) +{ + if (m_lastEditor == editor) { + // Oh no our editor is going to be closed + // get the content first + if (isFormWindowDocument(m_lastEditor->document())) { + disconnect(m_lastEditor->document(), SIGNAL(changed()), this, SLOT(uiDocumentContentsHasChanged())); + if (m_dirty) { + updateContents(m_lastEditor->document()->filePath(), + formWindowEditorContents(m_lastEditor)); + m_dirty = false; + } + } + m_lastEditor = 0; + } +} + +void UiCodeModelManager::editorWasChanged(Core::IEditor *editor) +{ + // Handle old editor + if (m_lastEditor && isFormWindowDocument(m_lastEditor->document())) { + disconnect(m_lastEditor->document(), SIGNAL(changed()), this, SLOT(uiDocumentContentsHasChanged())); + + if (m_dirty) { + updateContents(m_lastEditor->document()->filePath(), + formWindowEditorContents(m_lastEditor)); + m_dirty = false; + } + } + + m_lastEditor = editor; + + // Handle new editor + if (m_lastEditor && isFormWindowDocument(m_lastEditor->document())) + connect(m_lastEditor->document(), SIGNAL(changed()), this, SLOT(uiDocumentContentsHasChanged())); +} + +void UiCodeModelManager::uiDocumentContentsHasChanged() +{ + QTC_ASSERT(isFormWindowDocument(sender()), return); + m_dirty = true; +} + } // namespace QtSupport diff --git a/src/plugins/qtsupport/uicodemodelsupport.h b/src/plugins/qtsupport/uicodemodelsupport.h index 76fa9476c1..293491b071 100644 --- a/src/plugins/qtsupport/uicodemodelsupport.h +++ b/src/plugins/qtsupport/uicodemodelsupport.h @@ -35,14 +35,19 @@ #include <cpptools/abstracteditorsupport.h> #include <QDateTime> +#include <QHash> #include <QProcess> +#include <QSet> +namespace Core { class IEditor; } namespace CPlusPlus { class CppModelManagerInterface; } namespace ProjectExplorer { class Project; } namespace QtSupport { -class QTSUPPORT_EXPORT UiCodeModelSupport : public CppTools::AbstractEditorSupport +namespace Internal { class QtSupportPlugin; } + +class UiCodeModelSupport : public CppTools::AbstractEditorSupport { Q_OBJECT @@ -53,10 +58,11 @@ public: const QString &uiHeaderFile); ~UiCodeModelSupport(); - void setFileName(const QString &name); - void setSourceName(const QString &name); + void setHeaderFileName(const QString &name); QByteArray contents() const; - QString fileName() const; + QString uiFileName() const; // The .ui-file + QString fileName() const; // The header file + QString headerFileName() const { return fileName(); } void updateFromEditor(const QString &formEditorContents); void updateFromBuild(); @@ -74,14 +80,47 @@ private: void init() const; bool runUic(const QString &ui) const; mutable QProcess m_process; - QString m_sourceName; - QString m_fileName; + QString m_uiFileName; + QString m_headerFileName; mutable State m_state; mutable QByteArray m_contents; mutable QDateTime m_cacheTime; static QList<UiCodeModelSupport *> m_waitingForStart; }; +class QTSUPPORT_EXPORT UiCodeModelManager : public QObject +{ + Q_OBJECT + +public: + static UiCodeModelManager *instance(); + ~UiCodeModelManager(); + + // This needs to be called by the project *before* the C++ code model is updated! + void update(ProjectExplorer::Project *project, + QHash<QString, QString> uiHeaders); + +private slots: + void buildStateHasChanged(ProjectExplorer::Project *project); + void projectWasRemoved(ProjectExplorer::Project *project); + void editorIsAboutToClose(Core::IEditor *editor); + void editorWasChanged(Core::IEditor *editor); + void uiDocumentContentsHasChanged(); + +private: + UiCodeModelManager(); + + void updateContents(const QString &uiFileName, const QString &contents); + + QHash<ProjectExplorer::Project *, QList<UiCodeModelSupport *> > m_projectUiSupport; + Core::IEditor *m_lastEditor; + bool m_dirty; + + static UiCodeModelManager *m_instance; + + friend class Internal::QtSupportPlugin; +}; + } // QtSupport #endif // UICODEMODELSUPPORT_H |