diff --git a/interfaces/iassistant.cpp b/interfaces/iassistant.cpp index 35c3ce43c..930742dcc 100644 --- a/interfaces/iassistant.cpp +++ b/interfaces/iassistant.cpp @@ -1,143 +1,143 @@ /* Copyright 2009 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "iassistant.h" #include "icore.h" #include #include using namespace KDevelop; Q_DECLARE_METATYPE(QExplicitlySharedDataPointer) //BEGIN IAssistant void IAssistant::createActions() { } -QAction* IAssistantAction::toKAction(QObject* parent) const +QAction* IAssistantAction::toQAction(QObject* parent) const { Q_ASSERT(QThread::currentThread() == ICore::self()->thread() && "Actions must be created in the application main thread" "(implement createActions() to create your actions)"); QAction* ret = new QAction(icon(), description(), parent); ret->setToolTip(toolTip()); //Add the data as a QExplicitlySharedDataPointer to the action, so this assistant stays alive at least as long as the QAction ret->setData(QVariant::fromValue(QExplicitlySharedDataPointer(const_cast(this)))); connect(ret, &QAction::triggered, this, &IAssistantAction::execute); return ret; } IAssistant::~IAssistant() { } IAssistantAction::IAssistantAction() : QObject() , KSharedObject(*(QObject*)this) { } IAssistantAction::~IAssistantAction() { } QIcon IAssistantAction::icon() const { return QIcon(); } QString IAssistantAction::toolTip() const { return QString(); } //END IAssistantAction //BEGIN AssistantLabelAction AssistantLabelAction::AssistantLabelAction(const QString& description) : m_description(description) { } QString AssistantLabelAction::description() const { return m_description; } void AssistantLabelAction::execute() { // do nothing } -QAction* AssistantLabelAction::toKAction(QObject* parent) const +QAction* AssistantLabelAction::toQAction(QObject* parent) const { Q_UNUSED(parent); return nullptr; } //END AssistantLabelAction //BEGIN: IAssistant IAssistant::IAssistant() : KSharedObject(*(QObject*)this) { } QIcon IAssistant::icon() const { return QIcon(); } QString IAssistant::title() const { return QString(); } void IAssistant::doHide() { emit hide(); } QList< IAssistantAction::Ptr > IAssistant::actions() const { if ( m_actions.isEmpty() ) { const_cast(this)->createActions(); } return m_actions; } void IAssistant::addAction(const IAssistantAction::Ptr& action) { m_actions << action; } void IAssistant::clearActions() { m_actions.clear(); } //END IAssistant diff --git a/interfaces/iassistant.h b/interfaces/iassistant.h index 0e12dabd1..35f6eb781 100644 --- a/interfaces/iassistant.h +++ b/interfaces/iassistant.h @@ -1,150 +1,150 @@ /* Copyright 2009 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_IASSISTANT_H #define KDEVPLATFORM_IASSISTANT_H #include #include #include "interfacesexport.h" #include class QAction; namespace KDevelop { ///Represents a single assistant action. ///Subclass it to create your own actions. class KDEVPLATFORMINTERFACES_EXPORT IAssistantAction : public QObject, public KSharedObject { Q_OBJECT public: IAssistantAction(); typedef QExplicitlySharedDataPointer Ptr; ~IAssistantAction() override; ///Creates a QAction that represents this exact assistant action. ///The caller owns the action, and is responsible for deleting it. - virtual QAction* toKAction(QObject* parent = nullptr) const; + virtual QAction* toQAction(QObject* parent = nullptr) const; ///Should return a short description of the action. ///It may contain simple HTML formatting. ///Must be very short, so it nicely fits into the assistant popups. virtual QString description() const = 0; ///May return additional tooltip hover information. ///The default implementation returns an empty string. virtual QString toolTip() const; ///May return an icon for this action. ///The default implementation returns an invalid icon, which means that no icon is shown. virtual QIcon icon() const; public Q_SLOTS: /** * Execute this action. * * NOTE: Implementations should properly emit executed(this) after being executed. */ virtual void execute() = 0; Q_SIGNALS: /** * Gets emitted when this action was executed. */ void executed(IAssistantAction* action); }; /** * A fake action that only shows a label. */ class KDEVPLATFORMINTERFACES_EXPORT AssistantLabelAction : public IAssistantAction { Q_OBJECT public: /** * @p description The label to show. */ explicit AssistantLabelAction(const QString& description); /** * @return the label contents. */ QString description() const override; /** * The label cannot be executed. */ void execute() override; /** * No action is returned. */ - QAction* toKAction(QObject* parent = nullptr) const override; + QAction* toQAction(QObject* parent = nullptr) const override; private: QString m_description; }; ///Represents a single assistant popup. ///Subclass it to create your own assistants. class KDEVPLATFORMINTERFACES_EXPORT IAssistant : public QObject, public KSharedObject { Q_OBJECT public: IAssistant(); ~IAssistant() override; typedef QExplicitlySharedDataPointer Ptr; ///Returns the stored list of actions QList actions() const; ///Implement this and have it create the actions for your assistant. ///It will only be called if the assistant is displayed, which saves ///memory compared to creating the actions right away. ///Default implementation does nothing. virtual void createActions(); ///Adds the given action to the list of actions. ///Does not emit actionsChanged(), you have to do that when you're ready. virtual void addAction(const IAssistantAction::Ptr& action); ///Clears the stored list of actions. ///Does not emit actionsChanged(), you have to do that when you're ready. virtual void clearActions(); ///May return an icon for this assistant virtual QIcon icon() const; ///May return the title of this assistant ///The text may be html formatted. If it can be confused with HTML, ///use Qt::escape(..). virtual QString title() const; public Q_SLOTS: ///Emits hide(), which causes this assistant to be hidden virtual void doHide(); Q_SIGNALS: ///Can be emitted by the assistant when it should be hidden void hide(); ///Can be emitted by the assistant when its actions have changed and should be re-read void actionsChanged(); private: QList m_actions; }; } #endif // KDEVPLATFORM_IASSISTANT_H diff --git a/plugins/problemreporter/problemreporterplugin.cpp b/plugins/problemreporter/problemreporterplugin.cpp index e4b3e1a07..8ccd92148 100644 --- a/plugins/problemreporter/problemreporterplugin.cpp +++ b/plugins/problemreporter/problemreporterplugin.cpp @@ -1,251 +1,251 @@ /* * KDevelop Problem Reporter * * Copyright 2006 Adam Treat * Copyright 2006-2007 Hamish Rodda * Copyright 2007-2008 David Nolden * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "problemreporterplugin.h" #include #include #include #include #include #include #include #include #include #include #include #include "problemhighlighter.h" #include "problemreportermodel.h" #include "language/assistant/staticassistantsmanager.h" #include #include #include #include #include #include #include "shell/problemmodelset.h" #include "problemsview.h" #include #include K_PLUGIN_FACTORY_WITH_JSON(KDevProblemReporterFactory, "kdevproblemreporter.json", registerPlugin();) using namespace KDevelop; class ProblemReporterFactory : public KDevelop::IToolViewFactory { public: QWidget* create(QWidget* parent = nullptr) override { Q_UNUSED(parent); ProblemsView* v = new ProblemsView(); v->load(); return v; } Qt::DockWidgetArea defaultPosition() override { return Qt::BottomDockWidgetArea; } QString id() const override { return QStringLiteral("org.kdevelop.ProblemReporterView"); } }; ProblemReporterPlugin::ProblemReporterPlugin(QObject* parent, const QVariantList&) : KDevelop::IPlugin(QStringLiteral("kdevproblemreporter"), parent) , m_factory(new ProblemReporterFactory) , m_model(new ProblemReporterModel(this)) { KDevelop::ProblemModelSet* pms = core()->languageController()->problemModelSet(); pms->addModel(QStringLiteral("Parser"), i18n("Parser"), m_model); core()->uiController()->addToolView(i18n("Problems"), m_factory); setXMLFile(QStringLiteral("kdevproblemreporter.rc")); connect(ICore::self()->documentController(), &IDocumentController::documentClosed, this, &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() { qDeleteAll(m_highlighters); } ProblemReporterModel* ProblemReporterPlugin::model() const { return m_model; } void ProblemReporterPlugin::unload() { KDevelop::ProblemModelSet* pms = KDevelop::ICore::self()->languageController()->problemModelSet(); pms->removeModel(QStringLiteral("Parser")); core()->uiController()->removeToolView(m_factory); } void ProblemReporterPlugin::documentClosed(IDocument* doc) { if (!doc->textDocument()) return; IndexedString url(doc->url()); delete m_highlighters.take(url); m_reHighlightNeeded.remove(url); } void ProblemReporterPlugin::textDocumentCreated(KDevelop::IDocument* document) { Q_ASSERT(document->textDocument()); m_highlighters.insert(IndexedString(document->url()), new ProblemHighlighter(document->textDocument())); DUChain::self()->updateContextForUrl(IndexedString(document->url()), 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) 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& id) { auto w = dynamic_cast(core()->uiController()->findToolView(i18n("Problems"), m_factory)); if (w) w->showModel(id); } KDevelop::ContextMenuExtension ProblemReporterPlugin::contextMenuExtension(KDevelop::Context* context) { KDevelop::ContextMenuExtension extension; KDevelop::EditorContext* editorContext = dynamic_cast(context); if (editorContext) { DUChainReadLocker lock(DUChain::lock(), 1000); if (!lock.locked()) { qCDebug(PLUGIN_PROBLEMREPORTER) << "failed to lock duchain in time"; return extension; } QString title; QList actions; TopDUContext* top = DUChainUtils::standardContextForUrl(editorContext->url()); if (top) { foreach (KDevelop::ProblemPointer problem, top->problems()) { if (problem->range().contains( top->transformToLocalRevision(KTextEditor::Cursor(editorContext->position())))) { KDevelop::IAssistant::Ptr solution = problem->solutionAssistant(); if (solution) { title = solution->title(); foreach (KDevelop::IAssistantAction::Ptr action, solution->actions()) - actions << action->toKAction(); + actions << action->toQAction(); } } } } if (!actions.isEmpty()) { QString text; if (title.isEmpty()) text = i18n("Solve Problem"); else { text = i18n("Solve: %1", KDevelop::htmlToPlainText(title)); } QAction* menuAction = new QAction(text, nullptr); QMenu* menu(new QMenu(text, nullptr)); menuAction->setMenu(menu); foreach (QAction* action, actions) menu->addAction(action); extension.addAction(ContextMenuExtension::ExtensionGroup, menuAction); } } return extension; } void ProblemReporterPlugin::updateOpenedDocumentsHighlight() { foreach(auto document, core()->documentController()->openDocuments()) { // Skip non-text documents. // This also fixes crash caused by calling updateOpenedDocumentsHighlight() method without // any opened documents. In this case documentController()->openDocuments() returns single // (non-text) document with url like file:///tmp/kdevelop_QW2530.patch which has fatal bug: // if we call isActive() method from this document the crash will happens. if (!document->isTextDocument()) continue; 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/plugins/problemreporter/problemtreeview.cpp b/plugins/problemreporter/problemtreeview.cpp index fef3e6899..a37c98dee 100644 --- a/plugins/problemreporter/problemtreeview.cpp +++ b/plugins/problemreporter/problemtreeview.cpp @@ -1,224 +1,224 @@ /* * KDevelop Problem Reporter * * Copyright (c) 2006-2007 Hamish Rodda * Copyright 2006 Adam Treat * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "problemtreeview.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "problemreporterplugin.h" #include #include #include //#include "modeltest.h" using namespace KDevelop; namespace KDevelop { class ProblemTreeViewItemDelegate : public QItemDelegate { Q_OBJECT public: explicit ProblemTreeViewItemDelegate(QObject* parent = nullptr); void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; }; } ProblemTreeViewItemDelegate::ProblemTreeViewItemDelegate(QObject* parent) : QItemDelegate(parent) { } void ProblemTreeViewItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { QStyleOptionViewItem newOption(option); newOption.textElideMode = index.column() == ProblemModel::File ? Qt::ElideMiddle : Qt::ElideRight; QItemDelegate::paint(painter, newOption, index); } ProblemTreeView::ProblemTreeView(QWidget* parent, QAbstractItemModel* itemModel) : QTreeView(parent) , m_proxy(new QSortFilterProxyModel(this)) { setObjectName(QStringLiteral("Problem Reporter Tree")); setWhatsThis(i18n("Problems")); setItemDelegate(new ProblemTreeViewItemDelegate(this)); setSelectionBehavior(QAbstractItemView::SelectRows); m_proxy->setSortRole(ProblemModel::SeverityRole); m_proxy->setDynamicSortFilter(true); m_proxy->sort(0, Qt::AscendingOrder); ProblemModel* problemModel = dynamic_cast(itemModel); Q_ASSERT(problemModel); setModel(problemModel); header()->setStretchLastSection(false); if (!problemModel->features().testFlag(ProblemModel::ShowSource)) { hideColumn(ProblemModel::Source); } connect(this, &ProblemTreeView::clicked, this, &ProblemTreeView::itemActivated); connect(model(), &QAbstractItemModel::rowsInserted, this, &ProblemTreeView::changed); connect(model(), &QAbstractItemModel::rowsRemoved, this, &ProblemTreeView::changed); connect(model(), &QAbstractItemModel::modelReset, this, &ProblemTreeView::changed); m_proxy->setFilterKeyColumn(-1); m_proxy->setFilterCaseSensitivity(Qt::CaseInsensitive); } ProblemTreeView::~ProblemTreeView() { } void ProblemTreeView::openDocumentForCurrentProblem() { itemActivated(currentIndex()); } void ProblemTreeView::itemActivated(const QModelIndex& index) { if (!index.isValid()) return; KTextEditor::Cursor start; QUrl url; { // TODO: is this really necessary? DUChainReadLocker lock(DUChain::lock()); const auto problem = index.data(ProblemModel::ProblemRole).value(); if (!problem) return; url = problem->finalLocation().document.toUrl(); start = problem->finalLocation().start(); } if (QFile::exists(url.toLocalFile())) { ICore::self()->documentController()->openDocument(url, start); } } void ProblemTreeView::resizeColumns() { for (int i = 0; i < model()->columnCount(); ++i) resizeColumnToContents(i); } void ProblemTreeView::dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector& roles) { QTreeView::dataChanged(topLeft, bottomRight, roles); resizeColumns(); } void ProblemTreeView::reset() { QTreeView::reset(); resizeColumns(); } int ProblemTreeView::setFilter(const QString& filterText) { m_proxy->setFilterFixedString(filterText); return m_proxy->rowCount(); } ProblemModel* ProblemTreeView::model() const { return static_cast(m_proxy->sourceModel()); } void ProblemTreeView::setModel(QAbstractItemModel* model) { Q_ASSERT(qobject_cast(model)); m_proxy->setSourceModel(model); QTreeView::setModel(m_proxy); } void ProblemTreeView::contextMenuEvent(QContextMenuEvent* event) { QModelIndex index = indexAt(event->pos()); if (!index.isValid()) return; const auto problem = index.data(ProblemModel::ProblemRole).value(); if (!problem) { return; } QExplicitlySharedDataPointer solution = problem->solutionAssistant(); if (!solution) { return; } QList actions; foreach (KDevelop::IAssistantAction::Ptr action, solution->actions()) { - actions << action->toKAction(); + actions << action->toQAction(); } if (actions.isEmpty()) { return; } QString title = solution->title(); title = KDevelop::htmlToPlainText(title); title.replace(QLatin1String("'"), QLatin1String("\'")); QPointer m = new QMenu(this); m->addSection(title); m->addActions(actions); m->exec(event->globalPos()); delete m; qDeleteAll(actions); } void ProblemTreeView::showEvent(QShowEvent* event) { Q_UNUSED(event) resizeColumns(); } #include "problemtreeview.moc"