diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index 5c649e85cb5..5a744264c0a 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -62,13 +62,9 @@ #include #include -#include #include #include -#include -#include #include -#include #include 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::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 oldCodeModelSupport; - oldCodeModelSupport = m_uiCodeModelSupport; - m_uiCodeModelSupport.clear(); + QHash 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::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); - } - } + if (uiFile.endsWith(QLatin1String(".ui"))) + uiFileHash.insert(uiFile, uiHeaderFile(uiFile)); } - // Remove old - QMap::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::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; - } - } - - 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::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 38c8ebddb11..804eecc7564 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 list); void gatherFileNodes(ProjectExplorer::FolderNode *parent, QList &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 m_watchedFiles; QFuture m_codeModelFuture; - - QMap 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 d4a1088e422..2f4426902f4 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::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 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::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::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(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 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 "<path()<<" "<::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::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 5021ac809d9..1b51311d86f 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 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 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 m_uiFiles; // ui-file path, ui header path // Async stuff QFutureWatcher m_parseFutureWatcher; diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp index adb241026fd..d470c79ae3b 100644 --- a/src/plugins/qt4projectmanager/qt4project.cpp +++ b/src/plugins/qt4projectmanager/qt4project.cpp @@ -57,6 +57,7 @@ #include #include #include +#include #include #include @@ -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 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 uiData = pro->uiFiles(); + for (QHash::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 f0f7d2620ca..395fa9d4fbf 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 80432106b95..cf30ac99f8c 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 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 1a52c996777..75d0de2fb8e 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 964d969c19d..7a1683466ad 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 47d4fc04639..c5552b39b3a 100644 --- a/src/plugins/qtsupport/uicodemodelsupport.cpp +++ b/src/plugins/qtsupport/uicodemodelsupport.cpp @@ -31,9 +31,16 @@ #include "qtkitinformation.h" +#include +#include +#include #include +#include #include +#include +#include #include +#include #include #include @@ -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"< 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"<= 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 &range, const QString &uiFile) +{ + foreach (UiCodeModelSupport *support, range) { + if (support->uiFileName() == uiFile) + return support; + } + return 0; +} + +void UiCodeModelManager::update(ProjectExplorer::Project *project, QHash uiHeaders) +{ + CppTools::CppModelManagerInterface *mm = CppTools::CppModelManagerInterface::instance(); + + // Find support to add/update: + QList oldSupport = m_projectUiSupport.value(project); + QList newSupport; + QHash::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 >::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 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 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 76fa9476c16..293491b0713 100644 --- a/src/plugins/qtsupport/uicodemodelsupport.h +++ b/src/plugins/qtsupport/uicodemodelsupport.h @@ -35,14 +35,19 @@ #include #include +#include #include +#include +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 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 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 > m_projectUiSupport; + Core::IEditor *m_lastEditor; + bool m_dirty; + + static UiCodeModelManager *m_instance; + + friend class Internal::QtSupportPlugin; +}; + } // QtSupport #endif // UICODEMODELSUPPORT_H