From 20801bee306cbf6c6790cd0af4a7e389a811aa79 Mon Sep 17 00:00:00 2001 From: Kai Koehne <kai.koehne@nokia.com> Date: Tue, 19 Jan 2010 13:53:48 +0100 Subject: [PATCH] Update project tree if .qmlproject file / included directories change --- .../fileformat/filefilteritems.cpp | 36 +++++++++++++--- .../fileformat/filefilteritems.h | 9 +++- .../fileformat/qmlprojectitem.cpp | 5 ++- .../fileformat/qmlprojectitem.h | 4 +- src/plugins/qmlprojectmanager/qmlproject.cpp | 42 ++++++++++++++----- src/plugins/qmlprojectmanager/qmlproject.h | 18 ++++++-- 6 files changed, 90 insertions(+), 24 deletions(-) diff --git a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp index d80f3de97ec..7ccee302ce7 100644 --- a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp +++ b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp @@ -7,6 +7,8 @@ FileFilterBaseItem::FileFilterBaseItem(QObject *parent) : QmlProjectContentItem(parent), m_recursive(false) { + connect(&m_fsWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(updateFileList())); + connect(&m_fsWatcher, SIGNAL(fileChanged(QString)), this, SLOT(updateFileList())); } QString FileFilterBaseItem::directory() const @@ -82,24 +84,48 @@ QString FileFilterBaseItem::absoluteDir() const void FileFilterBaseItem::updateFileList() { - const QString dir = absoluteDir(); - if (dir.isEmpty()) + const QString projectDir = absoluteDir(); + if (projectDir.isEmpty()) return; - const QSet<QString> newFiles = filesInSubTree(QDir(m_defaultDir), QDir(dir)); + QSet<QString> dirsToBeWatched; + const QSet<QString> newFiles = filesInSubTree(QDir(m_defaultDir), QDir(projectDir), &dirsToBeWatched); + if (newFiles != m_files) { + // update watched files + foreach (const QString &file, m_files - newFiles) { + m_fsWatcher.removePath(QDir(projectDir).absoluteFilePath(file)); + } + foreach (const QString &file, newFiles - m_files) { + m_fsWatcher.addPath(QDir(projectDir).absoluteFilePath(file)); + } + m_files = newFiles; + emit filesChanged(); } + + // update watched directories + QSet<QString> watchedDirectories = m_fsWatcher.directories().toSet(); + foreach (const QString &dir, watchedDirectories - dirsToBeWatched) { + m_fsWatcher.removePath(QDir(projectDir).absoluteFilePath(dir)); + } + foreach (const QString &dir, dirsToBeWatched - watchedDirectories) { + m_fsWatcher.addPath(QDir(projectDir).absoluteFilePath(dir)); + } } -QSet<QString> FileFilterBaseItem::filesInSubTree(const QDir &rootDir, const QDir &dir) +QSet<QString> FileFilterBaseItem::filesInSubTree(const QDir &rootDir, const QDir &dir, QSet<QString> *parsedDirs) { QSet<QString> fileSet; + if (parsedDirs) + parsedDirs->insert(dir.absolutePath()); + foreach (const QFileInfo &file, dir.entryInfoList(QDir::Files)) { - if (m_regex.exactMatch(file.fileName())) + if (m_regex.exactMatch(file.fileName())) { fileSet.insert(rootDir.relativeFilePath(file.absoluteFilePath())); + } } if (m_recursive) { diff --git a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.h b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.h index 5857495be14..d3abe526b25 100644 --- a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.h +++ b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.h @@ -5,6 +5,7 @@ #include <QObject> #include <QSet> #include <qml.h> +#include <QFileSystemWatcher> #include "qmlprojectitem.h" @@ -40,11 +41,13 @@ signals: void filterChanged(); void filesChanged(); +private slots: + void updateFileList(); + private: QString absoluteDir() const; - void updateFileList(); - QSet<QString> filesInSubTree(const QDir &rootDir, const QDir &dir); + QSet<QString> filesInSubTree(const QDir &rootDir, const QDir &dir, QSet<QString> *parsedDirs = 0); QString m_rootDir; QString m_defaultDir; @@ -53,6 +56,8 @@ private: QRegExp m_regex; bool m_recursive; + QFileSystemWatcher m_fsWatcher; + QSet<QString> m_files; friend class ProjectItem; diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp index 4bc66ecbd49..1308c1bbe5b 100644 --- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp +++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.cpp @@ -56,6 +56,7 @@ QString QmlProjectItem::sourceDirectory() const return d->sourceDirectory; } +// kind of initialization void QmlProjectItem::setSourceDirectory(const QString &directoryPath) { Q_D(QmlProjectItem); @@ -68,8 +69,10 @@ void QmlProjectItem::setSourceDirectory(const QString &directoryPath) for (int i = 0; i < d->content.size(); ++i) { QmlProjectContentItem *contentElement = d->content.at(i); FileFilterBaseItem *fileFilter = qobject_cast<FileFilterBaseItem*>(contentElement); - if (fileFilter) + if (fileFilter) { fileFilter->setDefaultDirectory(directoryPath); + connect(fileFilter, SIGNAL(filesChanged()), this, SIGNAL(qmlFilesChanged())); + } } emit sourceDirectoryChanged(); diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h index ce7a6b54670..47a1353bfab 100644 --- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h +++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectitem.h @@ -1,7 +1,7 @@ #ifndef PROJECTITEM_H #define PROJECTITEM_H -#include <QObject> +#include <QtCore/QObject> #include <qml.h> namespace QmlProjectManager { @@ -38,11 +38,11 @@ public: QStringList qmlFiles() const; signals: + void qmlFilesChanged(); void sourceDirectoryChanged(); protected: QmlProjectItemPrivate *d_ptr; - }; } // namespace QmlProjectManager diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp index 04458845c9e..8b1c28f289e 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.cpp +++ b/src/plugins/qmlprojectmanager/qmlproject.cpp @@ -76,7 +76,8 @@ enum { QmlProject::QmlProject(Manager *manager, const QString &fileName) : m_manager(manager), m_fileName(fileName), - m_modelManager(ExtensionSystem::PluginManager::instance()->getObject<QmlJSEditor::QmlModelManagerInterface>()) + m_modelManager(ExtensionSystem::PluginManager::instance()->getObject<QmlJSEditor::QmlModelManagerInterface>()), + m_fileWatcher(new ProjectExplorer::FileWatcher(this)) { QFileInfo fileInfo(m_fileName); m_projectName = fileInfo.completeBaseName(); @@ -84,6 +85,10 @@ QmlProject::QmlProject(Manager *manager, const QString &fileName) m_file = new QmlProjectFile(this, fileName); m_rootNode = new QmlProjectNode(this, m_file); + m_fileWatcher->addFile(fileName), + connect(m_fileWatcher, SIGNAL(fileChanged(QString)), + this, SLOT(refreshProjectFile())); + m_manager->registerProject(this); } @@ -129,16 +134,23 @@ static QStringList readLines(const QString &absoluteFileName) void QmlProject::parseProject(RefreshOptions options) { if (options & Files) { + if (options & ProjectFile) + delete m_projectItem.data(); if (!m_projectItem) { - QmlComponent *component = new QmlComponent(&m_engine, m_fileName, this); - if (component->isReady() - && qobject_cast<QmlProjectItem*>(component->create())) { - m_projectItem = qobject_cast<QmlProjectItem*>(component->create()); - } else { - qWarning() << m_fileName << "is not valid qml file, falling back to old format ..."; - m_files = convertToAbsoluteFiles(readLines(filesFileName())); - m_files.removeDuplicates(); - m_modelManager->updateSourceFiles(m_files); + QFile file(m_fileName); + if (file.open(QFile::ReadOnly)) { + QmlComponent *component = new QmlComponent(&m_engine, this); + component->setData(file.readAll(), QUrl::fromLocalFile(m_fileName)); + if (component->isReady() + && qobject_cast<QmlProjectItem*>(component->create())) { + m_projectItem = qobject_cast<QmlProjectItem*>(component->create()); + connect(m_projectItem.data(), SIGNAL(qmlFilesChanged()), this, SLOT(refreshFiles())); + } else { + qWarning() << m_fileName << "is not valid qml file, falling back to old format ..."; + m_files = convertToAbsoluteFiles(readLines(filesFileName())); + m_files.removeDuplicates(); + m_modelManager->updateSourceFiles(m_files); + } } } if (m_projectItem) { @@ -191,6 +203,16 @@ QStringList QmlProject::files() const return files; } +void QmlProject::refreshProjectFile() +{ + refresh(QmlProject::ProjectFile | Files); +} + +void QmlProject::refreshFiles() +{ + refresh(Files); +} + QString QmlProject::displayName() const { return m_projectName; diff --git a/src/plugins/qmlprojectmanager/qmlproject.h b/src/plugins/qmlprojectmanager/qmlproject.h index ec695092d83..96d836f0841 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.h +++ b/src/plugins/qmlprojectmanager/qmlproject.h @@ -39,6 +39,7 @@ #include <projectexplorer/projectnodes.h> #include <projectexplorer/buildstep.h> #include <projectexplorer/applicationrunconfiguration.h> +#include <projectexplorer/filewatcher.h> #include <coreplugin/ifile.h> #include <QtCore/QDir> @@ -170,17 +171,23 @@ public: virtual Internal::QmlProjectNode *rootProjectNode() const; virtual QStringList files(FilesMode fileMode) const; - enum RefreshOptions { - Files = 0x01, - Configuration = 0x02, - Everything = Files | Configuration + enum RefreshOption { + ProjectFile = 0x01, + Files = 0x02, + Configuration = 0x04, + Everything = ProjectFile | Files | Configuration }; + Q_DECLARE_FLAGS(RefreshOptions,RefreshOption) void refresh(RefreshOptions options); QDir projectDir() const; QStringList files() const; +private slots: + void refreshProjectFile(); + void refreshFiles(); + protected: virtual void saveSettingsImpl(ProjectExplorer::PersistentSettingsWriter &writer); virtual bool restoreSettingsImpl(ProjectExplorer::PersistentSettingsReader &reader); @@ -202,6 +209,7 @@ private: // qml based, new format QmlEngine m_engine; QWeakPointer<QmlProjectItem> m_projectItem; + ProjectExplorer::FileWatcher *m_fileWatcher; Internal::QmlProjectNode *m_rootNode; }; @@ -243,4 +251,6 @@ private: } // namespace QmlProjectManager +Q_DECLARE_OPERATORS_FOR_FLAGS(QmlProjectManager::QmlProject::RefreshOptions) + #endif // QMLPROJECT_H -- GitLab