File indexing completed on 2024-04-28 04:38:10
0001 /* 0002 SPDX-FileCopyrightText: 2006 Adam Treat <treat@kde.org> 0003 SPDX-FileCopyrightText: 2006-2008 Hamish Rodda <rodda@kde.org> 0004 SPDX-FileCopyrightText: 2009 Lior Mualem <lior.m.kde@gmail.com> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #include "classbrowserplugin.h" 0010 0011 #include <QAction> 0012 0013 #include <KLocalizedString> 0014 #include <KPluginFactory> 0015 0016 #include "interfaces/icore.h" 0017 #include "interfaces/iuicontroller.h" 0018 #include "interfaces/idocumentcontroller.h" 0019 #include "interfaces/contextmenuextension.h" 0020 0021 #include "language/interfaces/codecontext.h" 0022 #include "language/duchain/duchainbase.h" 0023 #include "language/duchain/duchain.h" 0024 #include "language/duchain/duchainlock.h" 0025 #include "language/duchain/declaration.h" 0026 0027 #include "debug.h" 0028 #include "classtree.h" 0029 #include "classwidget.h" 0030 #include <language/duchain/persistentsymboltable.h> 0031 #include <language/duchain/functiondeclaration.h> 0032 #include <language/duchain/classfunctiondeclaration.h> 0033 #include <language/duchain/functiondefinition.h> 0034 #include <interfaces/iprojectcontroller.h> 0035 0036 K_PLUGIN_FACTORY_WITH_JSON(KDevClassBrowserFactory, "kdevclassbrowser.json", registerPlugin<ClassBrowserPlugin>(); ) 0037 0038 using namespace KDevelop; 0039 0040 class ClassBrowserFactory 0041 : public KDevelop::IToolViewFactory 0042 { 0043 public: 0044 explicit ClassBrowserFactory(ClassBrowserPlugin* plugin) : m_plugin(plugin) {} 0045 0046 QWidget* create(QWidget* parent = nullptr) override 0047 { 0048 return new ClassWidget(parent, m_plugin); 0049 } 0050 0051 Qt::DockWidgetArea defaultPosition() const override 0052 { 0053 return Qt::LeftDockWidgetArea; 0054 } 0055 0056 QString id() const override 0057 { 0058 return QStringLiteral("org.kdevelop.ClassBrowserView"); 0059 } 0060 0061 private: 0062 ClassBrowserPlugin* m_plugin; 0063 }; 0064 0065 ClassBrowserPlugin::ClassBrowserPlugin(QObject* parent, const QVariantList&) 0066 : KDevelop::IPlugin(QStringLiteral("kdevclassbrowser"), parent) 0067 , m_factory(new ClassBrowserFactory(this)) 0068 , m_activeClassTree(nullptr) 0069 { 0070 core()->uiController()->addToolView(i18nc("@title:window", "Classes"), m_factory); 0071 setXMLFile(QStringLiteral("kdevclassbrowser.rc")); 0072 0073 m_findInBrowser = new QAction(i18nc("@action", "Find in &Class Browser"), this); 0074 connect(m_findInBrowser, &QAction::triggered, this, &ClassBrowserPlugin::findInClassBrowser); 0075 } 0076 0077 ClassBrowserPlugin::~ClassBrowserPlugin() 0078 { 0079 } 0080 0081 void ClassBrowserPlugin::unload() 0082 { 0083 core()->uiController()->removeToolView(m_factory); 0084 } 0085 0086 KDevelop::ContextMenuExtension ClassBrowserPlugin::contextMenuExtension(KDevelop::Context* context, QWidget* parent) 0087 { 0088 KDevelop::ContextMenuExtension menuExt = KDevelop::IPlugin::contextMenuExtension(context, parent); 0089 0090 // No context menu if we don't have a class browser at hand. 0091 if (m_activeClassTree == nullptr) 0092 return menuExt; 0093 0094 auto* codeContext = dynamic_cast<KDevelop::DeclarationContext*>(context); 0095 0096 if (!codeContext) 0097 return menuExt; 0098 0099 DUChainReadLocker readLock(DUChain::lock()); 0100 Declaration* decl(codeContext->declaration().data()); 0101 0102 if (decl) { 0103 if (decl->inSymbolTable()) { 0104 if (!ClassTree::populatingClassBrowserContextMenu() && 0105 ICore::self()->projectController()->findProjectForUrl(decl->url().toUrl()) && 0106 decl->kind() == Declaration::Type && decl->internalContext() && 0107 decl->internalContext()->type() == DUContext::Class) { 0108 //Currently "Find in Class Browser" seems to only work for classes, so only show it in that case 0109 0110 m_findInBrowser->setData(QVariant::fromValue(DUChainBasePointer(decl))); 0111 menuExt.addAction(KDevelop::ContextMenuExtension::NavigationGroup, m_findInBrowser); 0112 } 0113 } 0114 } 0115 0116 return menuExt; 0117 } 0118 0119 void ClassBrowserPlugin::findInClassBrowser() 0120 { 0121 ICore::self()->uiController()->findToolView(i18nc("@title:window", "Classes"), m_factory, KDevelop::IUiController::CreateAndRaise); 0122 0123 Q_ASSERT(qobject_cast<QAction*>(sender())); 0124 0125 if (m_activeClassTree == nullptr) 0126 return; 0127 0128 DUChainReadLocker readLock(DUChain::lock()); 0129 0130 auto* a = static_cast<QAction*>(sender()); 0131 0132 Q_ASSERT(a->data().canConvert<DUChainBasePointer>()); 0133 0134 DeclarationPointer decl = qvariant_cast<DUChainBasePointer>(a->data()).dynamicCast<Declaration>(); 0135 if (decl) 0136 m_activeClassTree->highlightIdentifier(decl->qualifiedIdentifier()); 0137 } 0138 0139 void ClassBrowserPlugin::showDefinition(const DeclarationPointer& declaration) 0140 { 0141 DUChainReadLocker readLock(DUChain::lock()); 0142 0143 if (!declaration) 0144 return; 0145 0146 Declaration* decl = declaration.data(); 0147 // If it's a function, find the function definition to go to the actual declaration. 0148 if (decl && decl->isFunctionDeclaration()) { 0149 if (auto* funcDefinition = FunctionDefinition::definition(decl)) 0150 decl = funcDefinition; 0151 } 0152 0153 if (decl) { 0154 QUrl url = decl->url().toUrl(); 0155 KTextEditor::Range range = decl->rangeInCurrentRevision(); 0156 0157 readLock.unlock(); 0158 0159 ICore::self()->documentController()->openDocument(url, range.start()); 0160 } 0161 } 0162 0163 #include "classbrowserplugin.moc" 0164 #include "moc_classbrowserplugin.cpp"