diff --git a/plugins/problemreporter/problemhighlighter.cpp b/plugins/problemreporter/problemhighlighter.cpp --- a/plugins/problemreporter/problemhighlighter.cpp +++ b/plugins/problemreporter/problemhighlighter.cpp @@ -100,6 +100,9 @@ if (!m_document) return; + if (m_problems == problems) + return; + const bool hadProblems = !m_problems.isEmpty(); m_problems = problems; diff --git a/plugins/problemreporter/problemreporterplugin.h b/plugins/problemreporter/problemreporterplugin.h --- a/plugins/problemreporter/problemreporterplugin.h +++ b/plugins/problemreporter/problemreporterplugin.h @@ -64,13 +64,16 @@ void updateReady(const KDevelop::IndexedString& url, const KDevelop::ReferencedTopDUContext&); void updateHighlight(const KDevelop::IndexedString& url); void textDocumentCreated(KDevelop::IDocument* document); + void documentActivated(KDevelop::IDocument* document); void showModel(const QString& name); private: + void updateOpenedDocumentsHighlight(); class ProblemReporterFactory* m_factory; ProblemReporterModel* m_model; QHash m_highlighters; + QSet m_reHighlightNeeded; public slots: void documentClosed(KDevelop::IDocument*); }; diff --git a/plugins/problemreporter/problemreporterplugin.cpp b/plugins/problemreporter/problemreporterplugin.cpp --- a/plugins/problemreporter/problemreporterplugin.cpp +++ b/plugins/problemreporter/problemreporterplugin.cpp @@ -94,11 +94,14 @@ &ProblemReporterPlugin::documentClosed); connect(ICore::self()->documentController(), &IDocumentController::textDocumentCreated, this, &ProblemReporterPlugin::textDocumentCreated); + connect(ICore::self()->documentController(), &IDocumentController::documentActivated, this, + &ProblemReporterPlugin::documentActivated); connect(DUChain::self(), &DUChain::updateReady, this, &ProblemReporterPlugin::updateReady); connect(ICore::self()->languageController()->staticAssistantsManager(), &StaticAssistantsManager::problemsChanged, this, &ProblemReporterPlugin::updateHighlight); connect(pms, &ProblemModelSet::showRequested, this, &ProblemReporterPlugin::showModel); + connect(pms, &ProblemModelSet::problemsChanged, this, &ProblemReporterPlugin::updateOpenedDocumentsHighlight); } ProblemReporterPlugin::~ProblemReporterPlugin() @@ -126,6 +129,7 @@ IndexedString url(doc->url()); delete m_highlighters.take(url); + m_reHighlightNeeded.remove(url); } void ProblemReporterPlugin::textDocumentCreated(KDevelop::IDocument* document) @@ -136,19 +140,36 @@ KDevelop::TopDUContext::AllDeclarationsContextsAndUses, this); } +void ProblemReporterPlugin::documentActivated(KDevelop::IDocument* document) +{ + IndexedString documentUrl(document->url()); + + if (m_reHighlightNeeded.contains(documentUrl)) { + m_reHighlightNeeded.remove(documentUrl); + updateHighlight(documentUrl); + } +} + void ProblemReporterPlugin::updateReady(const IndexedString& url, const KDevelop::ReferencedTopDUContext&) { m_model->problemsUpdated(url); updateHighlight(url); } void ProblemReporterPlugin::updateHighlight(const KDevelop::IndexedString& url) { - ProblemHighlighter* ph = m_highlighters.value(url); - if (ph) { - auto allProblems = m_model->problems(url, false); - ph->setProblems(allProblems); + ProblemHighlighter* ph = m_highlighters.value(url); + if (!ph) + return; + + KDevelop::ProblemModelSet* pms(core()->languageController()->problemModelSet()); + QVector documentProblems; + + foreach (const ModelData& modelData, pms->models()) { + documentProblems += modelData.model->problems(url); } + + ph->setProblems(documentProblems); } void ProblemReporterPlugin::showModel(const QString& name) @@ -208,6 +229,18 @@ return extension; } +void ProblemReporterPlugin::updateOpenedDocumentsHighlight() +{ + foreach(auto document, core()->documentController()->openDocuments()) { + IndexedString documentUrl(document->url()); + + if (document->isActive()) + updateHighlight(documentUrl); + else + m_reHighlightNeeded.insert(documentUrl); + } +} + #include "problemreporterplugin.moc" // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/shell/problemmodel.h b/shell/problemmodel.h --- a/shell/problemmodel.h +++ b/shell/problemmodel.h @@ -129,12 +129,22 @@ /// Clears the problems void clearProblems(); + /// Retrieve problems for selected document + QVector problems(const KDevelop::IndexedString& document); + /// Retrieve the supported features Features features() const; /// Set the supported features void setFeatures(Features features); +signals: + /// Emitted when the stored problems are changed with addProblem(), setProblems() and + /// clearProblems() methods. This signal emitted only when internal problems storage is + /// really changed: for example, it is not emitted when we call clearProblems() method + /// for empty model. + void problemsChanged(); + public slots: /// Show imports virtual void setShowImports(bool){} diff --git a/shell/problemmodel.cpp b/shell/problemmodel.cpp --- a/shell/problemmodel.cpp +++ b/shell/problemmodel.cpp @@ -94,6 +94,8 @@ connect(d->m_problems.data(), &ProblemStore::beginRebuild, this, &ProblemModel::onBeginRebuild); connect(d->m_problems.data(), &ProblemStore::endRebuild, this, &ProblemModel::onEndRebuild); + + connect(d->m_problems.data(), &ProblemStore::problemsChanged, this, &ProblemModel::problemsChanged); } ProblemModel::~ ProblemModel() @@ -253,6 +255,10 @@ endResetModel(); } +QVector ProblemModel::problems(const KDevelop::IndexedString& document) +{ + return d->m_problems->problems(document); +} QVariant ProblemModel::headerData(int section, Qt::Orientation orientation, int role) const { diff --git a/shell/problemmodelset.h b/shell/problemmodelset.h --- a/shell/problemmodelset.h +++ b/shell/problemmodelset.h @@ -89,6 +89,9 @@ /// Emitted when showModel() is called void showRequested(const QString &name); + /// Emitted when any model emits problemsChanged() + void problemsChanged(); + private: QScopedPointer d; diff --git a/shell/problemmodelset.cpp b/shell/problemmodelset.cpp --- a/shell/problemmodelset.cpp +++ b/shell/problemmodelset.cpp @@ -18,6 +18,7 @@ */ #include "problemmodelset.h" +#include "problemmodel.h" #include namespace KDevelop @@ -43,6 +44,8 @@ m.model = model; d->data.push_back(m); + connect(model, &ProblemModel::problemsChanged, this, &ProblemModelSet::problemsChanged); + emit added(m); } @@ -69,8 +72,10 @@ ++itr; } - if(itr != d->data.end()) + if(itr != d->data.end()) { + (*itr).model->disconnect(this); d->data.erase(itr); + } emit removed(name); } diff --git a/shell/problemstore.h b/shell/problemstore.h --- a/shell/problemstore.h +++ b/shell/problemstore.h @@ -82,6 +82,9 @@ /// Clears the current problems, and adds new ones from a list virtual void setProblems(const QVector &problems); + /// Retrieve problems for selected document + QVector problems(const KDevelop::IndexedString& document) const; + /// Finds the specified node virtual const ProblemStoreNode* findNode(int row, ProblemStoreNode *parent = nullptr) const; @@ -123,9 +126,14 @@ const KDevelop::IndexedString& currentDocument() const; signals: - /// Emitted when the problems change + /// Emitted when any store setting (grouping, scope, severity, document) is changed void changed(); + /// Emitted when the stored problems are changed with clear(), addProblem() and setProblems() + /// methods. This signal emitted only when internal problems storage is really changed: + /// for example, it is not emitted when we call clear() method for empty storage. + void problemsChanged(); + /// Emitted before the problemlist is rebuilt void beginRebuild(); diff --git a/shell/problemstore.cpp b/shell/problemstore.cpp --- a/shell/problemstore.cpp +++ b/shell/problemstore.cpp @@ -43,6 +43,9 @@ /// Path of the currently open document KDevelop::IndexedString m_currentDocument; + + /// All stored problems + QVector m_allProblems; }; namespace KDevelop @@ -66,17 +69,43 @@ ProblemNode *node = new ProblemNode(d->m_rootNode); node->setProblem(problem); d->m_rootNode->addChild(node); + + d->m_allProblems += problem; + emit problemsChanged(); } void ProblemStore::setProblems(const QVector &problems) { - clear(); + int oldSize = d->m_allProblems.size(); + + // set signals block to prevent problemsChanged() emitting during clean + { + QSignalBlocker blocker(this); + clear(); + } foreach (const IProblem::Ptr &problem, problems) { d->m_rootNode->addChild(new ProblemNode(d->m_rootNode, problem)); } rebuild(); + + if (d->m_allProblems.size() != oldSize || d->m_allProblems != problems) { + d->m_allProblems = problems; + emit problemsChanged(); + } +} + +QVector ProblemStore::problems(const KDevelop::IndexedString& document) const +{ + QVector documentProblems; + + foreach (auto problem, d->m_allProblems) { + if (problem->finalLocation().document == document) + documentProblems += problem; + } + + return documentProblems; } const ProblemStoreNode* ProblemStore::findNode(int row, ProblemStoreNode *parent) const @@ -96,6 +125,11 @@ void ProblemStore::clear() { d->m_rootNode->clear(); + + if (!d->m_allProblems.isEmpty()) { + d->m_allProblems.clear(); + emit problemsChanged(); + } } void ProblemStore::rebuild()