diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp index 344830e90bca998fc2492d9f4f101b58c02e0b16..9ef22349f1460c5f4f2e73bd95edb7228fea81c6 100644 --- a/src/plugins/qmljseditor/qmljseditor.cpp +++ b/src/plugins/qmljseditor/qmljseditor.cpp @@ -651,6 +651,7 @@ QmlJSTextEditor::QmlJSTextEditor(QWidget *parent) : m_semanticHighlighter->setModelManager(m_modelManager); connect(m_modelManager, SIGNAL(documentUpdated(QmlJS::Document::Ptr)), this, SLOT(onDocumentUpdated(QmlJS::Document::Ptr))); + connect(this->document(), SIGNAL(modificationChanged(bool)), this, SLOT(modificationChanged(bool))); } connect(m_semanticHighlighter, SIGNAL(changed(QmlJSEditor::Internal::SemanticInfo)), @@ -775,6 +776,12 @@ void QmlJSTextEditor::onDocumentUpdated(QmlJS::Document::Ptr doc) } } +void QmlJSTextEditor::modificationChanged(bool changed) +{ + if (!changed && m_modelManager) + m_modelManager->fileChangedOnDisk(file()->fileName()); +} + void QmlJSTextEditor::jumpToMethod(int index) { if (index > 0 && index <= m_semanticInfo.declarations.size()) { // indexes are 1-based diff --git a/src/plugins/qmljseditor/qmljseditor.h b/src/plugins/qmljseditor/qmljseditor.h index 6bfb3b4722c9b534f0207ba7f9ad80550c72caa3..1fb222e51b5a03bc648e9e5a801eb60ba07955f8 100644 --- a/src/plugins/qmljseditor/qmljseditor.h +++ b/src/plugins/qmljseditor/qmljseditor.h @@ -218,6 +218,7 @@ public slots: private slots: void onDocumentUpdated(QmlJS::Document::Ptr doc); + void modificationChanged(bool); void updateDocument(); void updateDocumentNow(); diff --git a/src/plugins/qmljseditor/qmljsmodelmanager.cpp b/src/plugins/qmljseditor/qmljsmodelmanager.cpp index 0788dc4a99700bcbb12351c1c0f3896734d6e813..8c60de1a38b2415e2f2f4ffd782fda15341c2149 100644 --- a/src/plugins/qmljseditor/qmljsmodelmanager.cpp +++ b/src/plugins/qmljseditor/qmljsmodelmanager.cpp @@ -112,7 +112,7 @@ QFuture<void> ModelManager::refreshSourceFiles(const QStringList &sourceFiles) QFuture<void> result = QtConcurrent::run(&ModelManager::parse, workingCopy, sourceFiles, - this); + this, false); if (m_synchronizer.futures().size() > 10) { QList<QFuture<void> > futures = m_synchronizer.futures(); @@ -154,6 +154,16 @@ QMap<QString, ModelManager::WorkingCopy> ModelManager::buildWorkingCopyList() return workingCopy; } +void ModelManager::fileChangedOnDisk(const QString &path) +{ + QtConcurrent::run(&ModelManager::parse, + buildWorkingCopyList(), QStringList() << path, + this, true); +} + +void ModelManager::emitDocumentChangedOnDisk(Document::Ptr doc) +{ emit documentChangedOnDisk(doc); } + void ModelManager::emitDocumentUpdated(Document::Ptr doc) { emit documentUpdated(doc); } @@ -279,7 +289,8 @@ static void findNewLibraryImports(const Document::Ptr &doc, const Snapshot &snap void ModelManager::parse(QFutureInterface<void> &future, QMap<QString, WorkingCopy> workingCopy, QStringList files, - ModelManager *modelManager) + ModelManager *modelManager, + bool emitDocChangedOnDisk) { Core::MimeDatabase *db = Core::ICore::instance()->mimeDatabase(); Core::MimeType jsSourceTy = db->findByType(QLatin1String("application/javascript")); @@ -344,6 +355,8 @@ void ModelManager::parse(QFutureInterface<void> &future, } modelManager->emitDocumentUpdated(doc); + if (emitDocChangedOnDisk) + modelManager->emitDocumentChangedOnDisk(doc); } future.setProgressValue(progressRange); diff --git a/src/plugins/qmljseditor/qmljsmodelmanager.h b/src/plugins/qmljseditor/qmljsmodelmanager.h index d83d6547c2c3b2f299b5febf531483c27d623171..f43f7c6129157db22a4b95a83c3a99f22ad4f797 100644 --- a/src/plugins/qmljseditor/qmljsmodelmanager.h +++ b/src/plugins/qmljseditor/qmljsmodelmanager.h @@ -55,18 +55,20 @@ public: virtual QmlJS::Snapshot snapshot() const; virtual void updateSourceFiles(const QStringList &files); + virtual void fileChangedOnDisk(const QString &path); void emitDocumentUpdated(QmlJS::Document::Ptr doc); void emitLibraryInfoUpdated(const QString &path, const QmlJS::LibraryInfo &info); + void emitDocumentChangedOnDisk(QmlJS::Document::Ptr doc); virtual void setProjectImportPaths(const QStringList &importPaths); virtual QStringList importPaths() const; Q_SIGNALS: void projectPathChanged(const QString &projectPath); - void aboutToRemoveFiles(const QStringList &files); void libraryInfoUpdated(const QString &path, const QmlJS::LibraryInfo &info); + private Q_SLOTS: // this should be executed in the GUI thread. void onDocumentUpdated(QmlJS::Document::Ptr doc); @@ -86,7 +88,8 @@ protected: static void parse(QFutureInterface<void> &future, QMap<QString, WorkingCopy> workingCopy, QStringList files, - ModelManager *modelManager); + ModelManager *modelManager, + bool emitDocChangedOnDisk); void loadQmlTypeDescriptions(); diff --git a/src/plugins/qmljseditor/qmljsmodelmanagerinterface.h b/src/plugins/qmljseditor/qmljsmodelmanagerinterface.h index 280828c0e753b869b965b67df4ae126b42cc2838..706e574f87470cda426e60c8a0e1de449816d40c 100644 --- a/src/plugins/qmljseditor/qmljsmodelmanagerinterface.h +++ b/src/plugins/qmljseditor/qmljsmodelmanagerinterface.h @@ -54,12 +54,15 @@ public: virtual QmlJS::Snapshot snapshot() const = 0; virtual void updateSourceFiles(const QStringList &files) = 0; + virtual void fileChangedOnDisk(const QString &path) = 0; virtual void setProjectImportPaths(const QStringList &importPaths) = 0; virtual QStringList importPaths() const = 0; signals: void documentUpdated(QmlJS::Document::Ptr doc); + void documentChangedOnDisk(QmlJS::Document::Ptr doc); + void aboutToRemoveFiles(const QStringList &files); }; } // namespace QmlJSEditor diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp index 1b495017ce8f9ddc4759c74996a7e1d923f62992..548c4026886ff6d14092c6b678a15dbd1f755e4b 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.cpp +++ b/src/plugins/qmlprojectmanager/qmlproject.cpp @@ -121,14 +121,20 @@ void QmlProject::parseProject(RefreshOptions options) void QmlProject::refresh(RefreshOptions options) { - QSet<QString> oldFileList; - if (!(options & Configuration)) - oldFileList = m_files.toSet(); + const QSet<QString> oldFiles = m_files.toSet(); parseProject(options); if (options & Files) m_rootNode->refresh(); + + const QSet<QString> newFiles = m_files.toSet(); + QStringList removedPaths; + foreach (const QString &oldFile, oldFiles) + if (!newFiles.contains(oldFile)) + removedPaths.append(oldFile); + if (!removedPaths.isEmpty()) + emit filesRemovedFromProject(removedPaths); } QStringList QmlProject::convertToAbsoluteFiles(const QStringList &paths) const diff --git a/src/plugins/qmlprojectmanager/qmlproject.h b/src/plugins/qmlprojectmanager/qmlproject.h index a1903dfc0851b1e48b0e540efbdd396808b96f22..bab39524c42bf3801c1ea953e59db856436c270b 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.h +++ b/src/plugins/qmlprojectmanager/qmlproject.h @@ -101,6 +101,9 @@ public: bool addFiles(const QStringList &filePaths); +signals: + void filesRemovedFromProject(const QStringList removedPaths); + private slots: void refreshProjectFile(); void refreshFiles(); diff --git a/src/plugins/qmlprojectmanager/qmlprojectmanager.cpp b/src/plugins/qmlprojectmanager/qmlprojectmanager.cpp index e82b0ba3195215fafdbeb3a81668c62d5accbba0..a1d3092bdb9ba20d14f8fa2d33510c8a15197a77 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectmanager.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectmanager.cpp @@ -30,6 +30,7 @@ #include "qmlprojectmanager.h" #include "qmlprojectconstants.h" #include "qmlproject.h" +#include "qmltaskmanager.h" #include <coreplugin/icore.h> #include <coreplugin/ifile.h> @@ -79,7 +80,12 @@ ProjectExplorer::Project *Manager::openProject(const QString &fileName) } if (fileInfo.isFile()) { - return new QmlProject(this, fileName); + QmlProject *project = new QmlProject(this, fileName); + QmlTaskManager *taskManager = QmlTaskManager::instance(); + if (taskManager) + connect(project, SIGNAL(filesRemovedFromProject(QStringList)), + taskManager, SLOT(documentsRemoved(const QStringList))); + return project; } return 0; diff --git a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp index 3077d69f06cfdf7d67e5a2e4ed1d725298055ba4..f58d3ecb5e542a3b6242611cbede3d638e3e6908 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp @@ -77,6 +77,7 @@ bool QmlProjectPlugin::initialize(const QStringList &, QString *errorMessage) Manager *manager = new Manager; m_qmlTaskManager = new QmlTaskManager(this); + addAutoReleasedObject(m_qmlTaskManager); addAutoReleasedObject(manager); addAutoReleasedObject(new Internal::QmlProjectRunConfigurationFactory); @@ -100,8 +101,8 @@ void QmlProjectPlugin::extensionsInitialized() QmlJSEditor::ModelManagerInterface *modelManager = pluginManager->getObject<QmlJSEditor::ModelManagerInterface>(); Q_ASSERT(modelManager); - connect(modelManager, SIGNAL(documentUpdated(QmlJS::Document::Ptr)), - m_qmlTaskManager, SLOT(documentUpdated(QmlJS::Document::Ptr))); + connect(modelManager, SIGNAL(documentChangedOnDisk(QmlJS::Document::Ptr)), + m_qmlTaskManager, SLOT(documentChangedOnDisk(QmlJS::Document::Ptr))); } } // namespace Internal diff --git a/src/plugins/qmlprojectmanager/qmltaskmanager.cpp b/src/plugins/qmlprojectmanager/qmltaskmanager.cpp index cf5d8af2dcc5283019f1a83316f93952c44f6275..f17c2fc2a745ed256a651392caa8d7f8f65cd09d 100644 --- a/src/plugins/qmlprojectmanager/qmltaskmanager.cpp +++ b/src/plugins/qmlprojectmanager/qmltaskmanager.cpp @@ -29,6 +29,9 @@ #include "qmltaskmanager.h" #include "qmlprojectconstants.h" + +#include <extensionsystem/pluginmanager.h> + #include <QDebug> namespace QmlProjectManager { @@ -40,29 +43,58 @@ QmlTaskManager::QmlTaskManager(QObject *parent) : { } +QmlTaskManager *QmlTaskManager::instance() +{ + ExtensionSystem::PluginManager *pluginManager = ExtensionSystem::PluginManager::instance(); + return pluginManager->getObject<QmlTaskManager>(); +} + void QmlTaskManager::setTaskWindow(ProjectExplorer::TaskWindow *taskWindow) { Q_ASSERT(taskWindow); m_taskWindow = taskWindow; - m_taskWindow->addCategory(Constants::TASK_CATEGORY_QML, "QML"); + m_taskWindow->addCategory(Constants::TASK_CATEGORY_QML, tr("QML")); } -void QmlTaskManager::documentUpdated(QmlJS::Document::Ptr /*doc*/) +void QmlTaskManager::documentChangedOnDisk(QmlJS::Document::Ptr doc) { -#if 0 // This will give way too many flickering errors in the build-results pane *when you're typing* - m_taskWindow->clearTasks(Constants::TASK_CATEGORY_QML); + const QString fileName = doc->fileName(); + removeTasksForFile(fileName); foreach (const QmlJS::DiagnosticMessage &msg, doc->diagnosticMessages()) { ProjectExplorer::Task::TaskType type = msg.isError() ? ProjectExplorer::Task::Error : ProjectExplorer::Task::Warning; - ProjectExplorer::Task task(type, msg.message, doc->fileName(), msg.loc.startLine, + ProjectExplorer::Task task(type, msg.message, fileName, msg.loc.startLine, Constants::TASK_CATEGORY_QML); - m_taskWindow->addTask(task); + insertTask(fileName, task); + } +} + +void QmlTaskManager::documentsRemoved(const QStringList path) +{ + foreach (const QString &item, path) + removeTasksForFile(item); +} + +void QmlTaskManager::insertTask(const QString &fileName, const ProjectExplorer::Task &task) +{ + QList<ProjectExplorer::Task> tasks = m_docsWithTasks.value(fileName); + tasks.append(task); + m_docsWithTasks.insert(fileName, tasks); + m_taskWindow->addTask(task); +} + +void QmlTaskManager::removeTasksForFile(const QString &fileName) +{ + if (m_docsWithTasks.contains(fileName)) { + const QList<ProjectExplorer::Task> tasks = m_docsWithTasks.value(fileName); + foreach (const ProjectExplorer::Task &task, tasks) + m_taskWindow->removeTask(task); + m_docsWithTasks.remove(fileName); } -#endif } } // Internal diff --git a/src/plugins/qmlprojectmanager/qmltaskmanager.h b/src/plugins/qmlprojectmanager/qmltaskmanager.h index 3fd47d64affa42a5cf0dea35bdb84c177aa34653..369c95a78abd49aecff1c028545c8659e27f67bc 100644 --- a/src/plugins/qmlprojectmanager/qmltaskmanager.h +++ b/src/plugins/qmlprojectmanager/qmltaskmanager.h @@ -34,6 +34,8 @@ #include <qmljs/qmljsdocument.h> #include <QtCore/QObject> +#include <QtCore/QList> +#include <QtCore/QSet> namespace QmlProjectManager { namespace Internal { @@ -43,13 +45,22 @@ class QmlTaskManager : public QObject Q_OBJECT public: QmlTaskManager(QObject *parent = 0); + void setTaskWindow(ProjectExplorer::TaskWindow *taskWindow); + static QmlTaskManager *instance(); + public slots: - void documentUpdated(QmlJS::Document::Ptr doc); + void documentChangedOnDisk(QmlJS::Document::Ptr doc); + void documentsRemoved(const QStringList path); + +private: + void insertTask(const QString &fileName, const ProjectExplorer::Task &task); + void removeTasksForFile(const QString &fileName); private: ProjectExplorer::TaskWindow *m_taskWindow; + QMap<QString, QList<ProjectExplorer::Task> > m_docsWithTasks; }; } // Internal