From 0a2df32654ba0402457621613b5bcf74ca0e72d7 Mon Sep 17 00:00:00 2001 From: dt <qtc-committer@nokia.com> Date: Thu, 26 Mar 2009 17:36:58 +0100 Subject: [PATCH] Pop up a dialog if the CMakeCache.txt changes. Rerun cmake and reparse the file. Add new files to the tree, remove old ones from th tree. Add/removing targets should also work. --- .../cmakeprojectmanager/cmakeproject.cpp | 197 ++++++++++++++---- .../cmakeprojectmanager/cmakeproject.h | 18 +- .../filewatcher.cpp} | 8 +- .../filewatcher.h} | 16 +- .../projectexplorer/projectexplorer.pro | 6 +- src/plugins/qt4projectmanager/qt4nodes.cpp | 4 +- src/plugins/qt4projectmanager/qt4nodes.h | 9 +- .../qt4projectmanager/qt4projectmanager.pro | 6 +- 8 files changed, 186 insertions(+), 78 deletions(-) rename src/plugins/{qt4projectmanager/directorywatcher.cpp => projectexplorer/filewatcher.cpp} (94%) rename src/plugins/{qt4projectmanager/directorywatcher.h => projectexplorer/filewatcher.h} (89%) diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index e97d2b7f007..45df839ff0f 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -67,9 +67,13 @@ CMakeProject::CMakeProject(CMakeManager *manager, const QString &fileName) : m_manager(manager), m_fileName(fileName), m_rootNode(new CMakeProjectNode(m_fileName)), - m_toolChain(0) + m_toolChain(0), + m_insideFileChanged(false) { m_file = new CMakeFile(this, fileName); + m_watcher = new ProjectExplorer::FileWatcher(this); + connect(m_watcher, SIGNAL(fileChanged(QString)), this, SLOT(fileChanged(QString))); + m_watcher->addFile(fileName); } CMakeProject::~CMakeProject() @@ -78,53 +82,94 @@ CMakeProject::~CMakeProject() delete m_toolChain; } -// TODO also call this method if the CMakeLists.txt file changed, which is also called if the CMakeList.txt is updated -// TODO make this function work even if it is reparsing +void CMakeProject::fileChanged(const QString &fileName) +{ + if (m_insideFileChanged== true) + return; + m_insideFileChanged = true; + if (fileName == m_fileName) { + // Oh we have changed... + + // Pop up a dialog asking the user to rerun cmake + QFileInfo sourceFileInfo(m_fileName); + QStringList needToCreate; + QStringList needToUpdate; + foreach(const QString &buildConfiguration, buildConfigurations()) { + QString buildDirectory = value(buildConfiguration, "buildDirectory").toString(); + QString cbpFile = CMakeManager::findCbpFile(QDir(buildDirectory)); + QFileInfo cbpFileFi(cbpFile); + if (!cbpFileFi.exists()) + needToCreate << buildDirectory; + else if (cbpFileFi.lastModified() < sourceFileInfo.lastModified()) + needToUpdate << buildDirectory; + } + if (!needToCreate.isEmpty() || !needToUpdate.isEmpty()) { + CMakeOpenProjectWizard copw(m_manager, sourceFileInfo.absolutePath(), needToCreate, needToUpdate); + copw.exec(); + } + // reparse + parseCMakeLists(); + } + m_insideFileChanged = false; +} + +void CMakeProject::updateToolChain(const QString &compiler) +{ + //qDebug()<<"CodeBlocks Compilername"<<compiler + ProjectExplorer::ToolChain *newToolChain = 0; + if (compiler == "gcc") { + newToolChain = ProjectExplorer::ToolChain::createGccToolChain("gcc"); + } else if (compiler == "msvc8") { + // TODO hmm + //newToolChain = ProjectExplorer::ToolChain::createMSVCToolChain("//TODO"); + Q_ASSERT(false); + } else { + // TODO hmm? + qDebug()<<"Not implemented yet!!! Qt Creator doesn't know which toolchain to use for"<<compiler; + } + + if (ProjectExplorer::ToolChain::equals(newToolChain, m_toolChain)) { + delete newToolChain; + newToolChain = 0; + } else { + delete m_toolChain; + m_toolChain = newToolChain; + } +} + void CMakeProject::parseCMakeLists() { + // Find cbp file QString sourceDirectory = QFileInfo(m_fileName).absolutePath(); QString cbpFile = CMakeManager::findCbpFile(buildDirectory(activeBuildConfiguration())); + + // setFolderName m_rootNode->setFolderName(QFileInfo(cbpFile).completeBaseName()); CMakeCbpParser cbpparser; - qDebug()<<"Parsing file "<<cbpFile; - if (cbpparser.parseCbpFile(cbpFile)) { - qDebug()<<"CodeBlocks Compilername"<<cbpparser.compilerName(); - ProjectExplorer::ToolChain *newToolChain = 0; - if (cbpparser.compilerName() == "gcc") { - newToolChain = ProjectExplorer::ToolChain::createGccToolChain("gcc"); - } else if (cbpparser.compilerName() == "msvc8") { - // TODO hmm - //newToolChain = ProjectExplorer::ToolChain::createMSVCToolChain("//TODO"); - Q_ASSERT(false); - } else { - // TODO hmm? - qDebug()<<"Not implemented yet!!! Qt Creator doesn't know which toolchain to use for"<<cbpparser.compilerName(); - } - - if (ProjectExplorer::ToolChain::equals(newToolChain, m_toolChain)) { - delete newToolChain; - newToolChain = 0; - } else { - delete m_toolChain; - m_toolChain = newToolChain; - } + // Parsing + //qDebug()<<"Parsing file "<<cbpFile; + if (cbpparser.parseCbpFile(cbpFile)) { + // ToolChain + updateToolChain(cbpparser.compilerName()); m_projectName = cbpparser.projectName(); m_rootNode->setFolderName(cbpparser.projectName()); - qDebug()<<"Building Tree"; - // TODO do a intelligent updating of the tree + //qDebug()<<"Building Tree"; + QList<ProjectExplorer::FileNode *> fileList = cbpparser.fileList(); // Manually add the CMakeLists.txt file fileList.append(new ProjectExplorer::FileNode(sourceDirectory + "/CMakeLists.txt", ProjectExplorer::ProjectFileType, false)); - buildTree(m_rootNode, fileList); m_files.clear(); foreach (ProjectExplorer::FileNode *fn, fileList) m_files.append(fn->path()); m_files.sort(); - qDebug()<<"Adding Targets"; + buildTree(m_rootNode, fileList); + + + //qDebug()<<"Adding Targets"; m_targets = cbpparser.targets(); // qDebug()<<"Printing targets"; // foreach(CMakeTarget ct, m_targets) { @@ -134,7 +179,7 @@ void CMakeProject::parseCMakeLists() // qDebug()<<""; // } - qDebug()<<"Updating CodeModel"; + //qDebug()<<"Updating CodeModel"; QStringList allIncludePaths; QStringList allFrameworkPaths; @@ -158,7 +203,7 @@ void CMakeProject::parseCMakeLists() } // Create run configurations for m_targets - qDebug()<<"Create run configurations of m_targets"; + //qDebug()<<"Create run configurations of m_targets"; QMap<QString, QSharedPointer<CMakeRunConfiguration> > existingRunConfigurations; foreach(QSharedPointer<ProjectExplorer::RunConfiguration> cmakeRunConfiguration, runConfigurations()) { if (QSharedPointer<CMakeRunConfiguration> rc = cmakeRunConfiguration.dynamicCast<CMakeRunConfiguration>()) { @@ -177,16 +222,16 @@ void CMakeProject::parseCMakeLists() if (it != existingRunConfigurations.end()) { // Already exists, so override the settings... QSharedPointer<CMakeRunConfiguration> rc = it.value(); - qDebug()<<"Updating Run Configuration with title"<<ct.title; - qDebug()<<" Executable new:"<<ct.executable<< "old:"<<rc->executable(); - qDebug()<<" WD new:"<<ct.workingDirectory<<"old:"<<rc->workingDirectory(); + //qDebug()<<"Updating Run Configuration with title"<<ct.title; + //qDebug()<<" Executable new:"<<ct.executable<< "old:"<<rc->executable(); + //qDebug()<<" WD new:"<<ct.workingDirectory<<"old:"<<rc->workingDirectory(); rc->setExecutable(ct.executable); rc->setWorkingDirectory(ct.workingDirectory); existingRunConfigurations.erase(it); } else { // Does not exist yet - qDebug()<<"Adding new run configuration with title"<<ct.title; - qDebug()<<" Executable:"<<ct.executable<<"WD:"<<ct.workingDirectory; + //qDebug()<<"Adding new run configuration with title"<<ct.title; + //qDebug()<<" Executable:"<<ct.executable<<"WD:"<<ct.workingDirectory; QSharedPointer<ProjectExplorer::RunConfiguration> rc(new CMakeRunConfiguration(this, ct.executable, ct.workingDirectory, ct.title)); addRunConfiguration(rc); // The first one gets the honour of beeing the active one @@ -200,11 +245,11 @@ void CMakeProject::parseCMakeLists() existingRunConfigurations.constBegin(); for( ; it != existingRunConfigurations.constEnd(); ++it) { QSharedPointer<CMakeRunConfiguration> rc = it.value(); - qDebug()<<"Removing old RunConfiguration with title:"<<rc->title(); - qDebug()<<" Executable:"<<rc->executable()<<rc->workingDirectory(); + //qDebug()<<"Removing old RunConfiguration with title:"<<rc->title(); + //qDebug()<<" Executable:"<<rc->executable()<<rc->workingDirectory(); removeRunConfiguration(rc); } - qDebug()<<"\n"; + //qDebug()<<"\n"; } else { // TODO report error qDebug()<<"Parsing failed"; @@ -238,17 +283,79 @@ QStringList CMakeProject::targets() const return results; } -void CMakeProject::buildTree(CMakeProjectNode *rootNode, QList<ProjectExplorer::FileNode *> list) +void CMakeProject::gatherFileNodes(ProjectExplorer::FolderNode *parent, QList<ProjectExplorer::FileNode *> &list) +{ + foreach(ProjectExplorer::FolderNode *folder, parent->subFolderNodes()) + gatherFileNodes(folder, list); + foreach(ProjectExplorer::FileNode *file, parent->fileNodes()) + list.append(file); +} + +void CMakeProject::buildTree(CMakeProjectNode *rootNode, QList<ProjectExplorer::FileNode *> newList) { - //m_rootNode->addFileNodes(fileList, m_rootNode); - qSort(list.begin(), list.end(), ProjectExplorer::ProjectNode::sortNodesByPath); - foreach (ProjectExplorer::FileNode *fn, list) { + // Gather old list + QList<ProjectExplorer::FileNode *> oldList; + gatherFileNodes(rootNode, oldList); + qSort(oldList.begin(), oldList.end(), ProjectExplorer::ProjectNode::sortNodesByPath); + qSort(newList.begin(), newList.end(), ProjectExplorer::ProjectNode::sortNodesByPath); + + // generate added and deleted list + QList<ProjectExplorer::FileNode *>::const_iterator oldIt = oldList.constBegin(); + QList<ProjectExplorer::FileNode *>::const_iterator oldEnd = oldList.constEnd(); + QList<ProjectExplorer::FileNode *>::const_iterator newIt = newList.constBegin(); + QList<ProjectExplorer::FileNode *>::const_iterator newEnd = newList.constEnd(); + + QList<ProjectExplorer::FileNode *> added; + QList<ProjectExplorer::FileNode *> deleted; + + + while(oldIt != oldEnd && newIt != newEnd) { + if ( (*oldIt)->path() == (*newIt)->path()) { + delete *newIt; + ++oldIt; + ++newIt; + } else if ((*oldIt)->path() < (*newIt)->path()) { + deleted.append(*oldIt); + ++oldIt; + } else { + added.append(*newIt); + ++newIt; + } + } + + while (oldIt != oldEnd) { + deleted.append(*oldIt); + ++oldIt; + } + + while (newIt != newEnd) { + added.append(*newIt); + ++newIt; + } + + // add added nodes + foreach (ProjectExplorer::FileNode *fn, added) { +// qDebug()<<"added"<<fn->path(); // Get relative path to rootNode QString parentDir = QFileInfo(fn->path()).absolutePath(); ProjectExplorer::FolderNode *folder = findOrCreateFolder(rootNode, parentDir); rootNode->addFileNodes(QList<ProjectExplorer::FileNode *>()<< fn, folder); } - //m_rootNode->addFileNodes(list, rootNode); + + // remove old file nodes and check wheter folder nodes can be removed + foreach (ProjectExplorer::FileNode *fn, deleted) { + ProjectExplorer::FolderNode *parent = fn->parentFolderNode(); +// qDebug()<<"removed"<<fn->path(); + rootNode->removeFileNodes(QList<ProjectExplorer::FileNode *>() << fn, parent); + // Check for empty parent + while (parent->subFolderNodes().isEmpty() && parent->fileNodes().isEmpty()) { + ProjectExplorer::FolderNode *grandparent = parent->parentFolderNode(); + rootNode->removeFolderNodes(QList<ProjectExplorer::FolderNode *>() << parent, grandparent); + parent = grandparent; + if (parent == rootNode) + break; + } + } } ProjectExplorer::FolderNode *CMakeProject::findOrCreateFolder(CMakeProjectNode *rootNode, QString directory) @@ -346,13 +453,11 @@ ProjectExplorer::ProjectNode *CMakeProject::rootProjectNode() const QStringList CMakeProject::files(FilesMode fileMode) const { Q_UNUSED(fileMode); - // TODO return m_files; } void CMakeProject::saveSettingsImpl(ProjectExplorer::PersistentSettingsWriter &writer) { - // TODO Project::saveSettingsImpl(writer); } diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h index 02a1995306f..74b1a2f0eec 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.h +++ b/src/plugins/cmakeprojectmanager/cmakeproject.h @@ -38,6 +38,7 @@ #include <projectexplorer/projectnodes.h> #include <projectexplorer/buildstep.h> #include <projectexplorer/toolchain.h> +#include <projectexplorer/filewatcher.h> #include <coreplugin/ifile.h> #include <utils/pathchooser.h> @@ -101,13 +102,21 @@ public: QStringList targets() const; QString buildParser(const QString &buildConfiguration) const; +protected: + virtual void saveSettingsImpl(ProjectExplorer::PersistentSettingsWriter &writer); + virtual void restoreSettingsImpl(ProjectExplorer::PersistentSettingsReader &reader); + +private slots: + void fileChanged(const QString &fileName); + private: void parseCMakeLists(); + void updateToolChain(const QString &compiler); void buildTree(CMakeProjectNode *rootNode, QList<ProjectExplorer::FileNode *> list); + void gatherFileNodes(ProjectExplorer::FolderNode *parent, QList<ProjectExplorer::FileNode *> &list); ProjectExplorer::FolderNode *findOrCreateFolder(CMakeProjectNode *rootNode, QString directory); - CMakeManager *m_manager; QString m_fileName; CMakeFile *m_file; @@ -118,11 +127,8 @@ private: QStringList m_files; QList<CMakeTarget> m_targets; ProjectExplorer::ToolChain *m_toolChain; - -protected: - virtual void saveSettingsImpl(ProjectExplorer::PersistentSettingsWriter &writer); - virtual void restoreSettingsImpl(ProjectExplorer::PersistentSettingsReader &reader); - + ProjectExplorer::FileWatcher *m_watcher; + bool m_insideFileChanged; }; class CMakeCbpParser : public QXmlStreamReader diff --git a/src/plugins/qt4projectmanager/directorywatcher.cpp b/src/plugins/projectexplorer/filewatcher.cpp similarity index 94% rename from src/plugins/qt4projectmanager/directorywatcher.cpp rename to src/plugins/projectexplorer/filewatcher.cpp index 7fc56381605..fc6c5309a0e 100644 --- a/src/plugins/qt4projectmanager/directorywatcher.cpp +++ b/src/plugins/projectexplorer/filewatcher.cpp @@ -27,7 +27,7 @@ ** **************************************************************************/ -#include "directorywatcher.h" +#include "filewatcher.h" #include <QtCore/QDebug> #include <QtCore/QDir> @@ -37,8 +37,7 @@ enum { debugWatcher = 0 }; -namespace Qt4ProjectManager { -namespace Internal { +using namespace ProjectExplorer; int FileWatcher::m_objectCount = 0; QHash<QString,int> FileWatcher::m_fileCount; @@ -92,6 +91,3 @@ void FileWatcher::removeFile(const QString &file) if (m_fileCount[file] == 0) m_watcher->removePath(file); } - -} // namespace Internal -} // namespace Qt4ProjectManager diff --git a/src/plugins/qt4projectmanager/directorywatcher.h b/src/plugins/projectexplorer/filewatcher.h similarity index 89% rename from src/plugins/qt4projectmanager/directorywatcher.h rename to src/plugins/projectexplorer/filewatcher.h index 8c5029df51e..24a2e4f74e7 100644 --- a/src/plugins/qt4projectmanager/directorywatcher.h +++ b/src/plugins/projectexplorer/filewatcher.h @@ -27,8 +27,10 @@ ** **************************************************************************/ -#ifndef DIRECTORYWATCHER_H -#define DIRECTORYWATCHER_H +#ifndef FILEWATCHER_H +#define FILEWATCHER_H + +#include "projectexplorer_export.h" #include <QtCore/QDateTime> #include <QtCore/QHash> @@ -40,10 +42,9 @@ class QTimer; class QFileSystemWatcher; QT_END_NAMESPACE -namespace Qt4ProjectManager { -namespace Internal { +namespace ProjectExplorer { -class FileWatcher : public QObject +class PROJECTEXPLORER_EXPORT FileWatcher : public QObject { Q_DISABLE_COPY(FileWatcher) Q_OBJECT @@ -68,7 +69,6 @@ private: QStringList m_files; }; -} // namespace Internal -} // namespace Qt4ProjectManager +} // namespace ProjectExplorer -#endif // DIRECTORYWATCHER_H +#endif // FILEWATCHER_H diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro index 460dd658718..5df19ebb034 100644 --- a/src/plugins/projectexplorer/projectexplorer.pro +++ b/src/plugins/projectexplorer/projectexplorer.pro @@ -57,7 +57,8 @@ HEADERS += projectexplorer.h \ cesdkhandler.h\ buildparserfactory.h\ gccparser.h\ - msvcparser.h + msvcparser.h\ + filewatcher.h SOURCES += projectexplorer.cpp \ projectwindow.cpp \ buildmanager.cpp \ @@ -103,7 +104,8 @@ SOURCES += projectexplorer.cpp \ cesdkhandler.cpp\ buildparserfactory.cpp \ gccparser.cpp\ - msvcparser.cpp + msvcparser.cpp\ + filewatcher.cpp FORMS += dependenciespanel.ui \ buildsettingspropertiespage.ui \ processstep.ui \ diff --git a/src/plugins/qt4projectmanager/qt4nodes.cpp b/src/plugins/qt4projectmanager/qt4nodes.cpp index 686e6d42cb6..b85efa2821a 100644 --- a/src/plugins/qt4projectmanager/qt4nodes.cpp +++ b/src/plugins/qt4projectmanager/qt4nodes.cpp @@ -29,7 +29,6 @@ #include "proeditormodel.h" -#include "directorywatcher.h" #include "profilereader.h" #include "prowriter.h" #include "qt4nodes.h" @@ -37,6 +36,7 @@ #include "qt4projectmanager.h" #include <projectexplorer/nodesvisitor.h> +#include <projectexplorer/filewatcher.h> #include <coreplugin/editormanager/editormanager.h> #include <coreplugin/fileiconprovider.h> @@ -88,7 +88,7 @@ Qt4PriFileNode::Qt4PriFileNode(Qt4Project *project, Qt4ProFileNode* qt4ProFileNo m_qt4ProFileNode(qt4ProFileNode), m_projectFilePath(QDir::fromNativeSeparators(filePath)), m_projectDir(QFileInfo(filePath).absolutePath()), - m_fileWatcher(new FileWatcher(this)) + m_fileWatcher(new ProjectExplorer::FileWatcher(this)) { Q_ASSERT(project); setFolderName(QFileInfo(filePath).completeBaseName()); diff --git a/src/plugins/qt4projectmanager/qt4nodes.h b/src/plugins/qt4projectmanager/qt4nodes.h index e94b08e67ae..4e95ac4b8a6 100644 --- a/src/plugins/qt4projectmanager/qt4nodes.h +++ b/src/plugins/qt4projectmanager/qt4nodes.h @@ -48,6 +48,10 @@ namespace Core { class ICore; } +namespace ProjectExplorer { +class FileWatcher; +} + namespace Qt4ProjectManager { // Import base classes into namespace @@ -71,10 +75,7 @@ class Qt4Project; namespace Internal { using ProjectExplorer::FileType; - class ProFileReader; -class DirectoryWatcher; -class FileWatcher; // Type of projects enum Qt4ProjectType { @@ -158,7 +159,7 @@ private: // TODO we might be better off using an IFile* and the FileManager for // watching changes to the .pro and .pri files on disk - FileWatcher *m_fileWatcher; + ProjectExplorer::FileWatcher *m_fileWatcher; // managed by Qt4ProFileNode friend class Qt4ProFileNode; diff --git a/src/plugins/qt4projectmanager/qt4projectmanager.pro b/src/plugins/qt4projectmanager/qt4projectmanager.pro index 98e95274706..eaf782e4c20 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanager.pro +++ b/src/plugins/qt4projectmanager/qt4projectmanager.pro @@ -34,8 +34,7 @@ HEADERS = qt4projectmanagerplugin.h \ speinfo.h \ qt4buildconfigwidget.h \ qt4buildenvironmentwidget.h \ - projectloadwizard.h \ - directorywatcher.h + projectloadwizard.h SOURCES = qt4projectmanagerplugin.cpp \ qt4projectmanager.cpp \ qtversionmanager.cpp \ @@ -65,8 +64,7 @@ SOURCES = qt4projectmanagerplugin.cpp \ speinfo.cpp \ qt4buildconfigwidget.cpp \ qt4buildenvironmentwidget.cpp \ - projectloadwizard.cpp \ - directorywatcher.cpp + projectloadwizard.cpp FORMS = qtversionmanager.ui \ envvariablespage.ui \ enveditdialog.ui \ -- GitLab