diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp index 344830e90bc..9ef22349f14 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 6bfb3b4722c..1fb222e51b5 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 0788dc4a997..8c60de1a38b 100644 --- a/src/plugins/qmljseditor/qmljsmodelmanager.cpp +++ b/src/plugins/qmljseditor/qmljsmodelmanager.cpp @@ -112,7 +112,7 @@ QFuture ModelManager::refreshSourceFiles(const QStringList &sourceFiles) QFuture result = QtConcurrent::run(&ModelManager::parse, workingCopy, sourceFiles, - this); + this, false); if (m_synchronizer.futures().size() > 10) { QList > futures = m_synchronizer.futures(); @@ -154,6 +154,16 @@ QMap 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 &future, QMap 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 &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 d83d6547c2c..f43f7c61291 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 &future, QMap 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 280828c0e75..706e574f874 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 1b495017ce8..548c4026886 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 oldFileList; - if (!(options & Configuration)) - oldFileList = m_files.toSet(); + const QSet oldFiles = m_files.toSet(); parseProject(options); if (options & Files) m_rootNode->refresh(); + + const QSet 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 a1903dfc085..bab39524c42 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 e82b0ba3195..a1d3092bdb9 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 #include @@ -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 3077d69f06c..f58d3ecb5e5 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(); 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 cf5d8af2dcc..f17c2fc2a74 100644 --- a/src/plugins/qmlprojectmanager/qmltaskmanager.cpp +++ b/src/plugins/qmlprojectmanager/qmltaskmanager.cpp @@ -29,6 +29,9 @@ #include "qmltaskmanager.h" #include "qmlprojectconstants.h" + +#include + #include namespace QmlProjectManager { @@ -40,29 +43,58 @@ QmlTaskManager::QmlTaskManager(QObject *parent) : { } +QmlTaskManager *QmlTaskManager::instance() +{ + ExtensionSystem::PluginManager *pluginManager = ExtensionSystem::PluginManager::instance(); + return pluginManager->getObject(); +} + 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 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 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 3fd47d64aff..369c95a78ab 100644 --- a/src/plugins/qmlprojectmanager/qmltaskmanager.h +++ b/src/plugins/qmlprojectmanager/qmltaskmanager.h @@ -34,6 +34,8 @@ #include #include +#include +#include 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 > m_docsWithTasks; }; } // Internal