File indexing completed on 2024-04-28 04:38:10

0001 /*
0002     SPDX-FileCopyrightText: 2006 Adam Treat <treat@kde.org>
0003     SPDX-FileCopyrightText: 2006-2007 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 "classtree.h"
0010 
0011 #include <QMenu>
0012 #include <QHeaderView>
0013 #include <QContextMenuEvent>
0014 #include <QScrollBar>
0015 
0016 #include "interfaces/contextmenuextension.h"
0017 #include "interfaces/icore.h"
0018 #include "interfaces/idocument.h"
0019 #include "interfaces/iplugincontroller.h"
0020 
0021 #include "language/interfaces/codecontext.h"
0022 
0023 #include "language/duchain/duchainbase.h"
0024 #include "language/duchain/duchain.h"
0025 #include "language/duchain/duchainlock.h"
0026 #include "language/duchain/declaration.h"
0027 
0028 #include "language/classmodel/classmodel.h"
0029 #include "classbrowserplugin.h"
0030 
0031 using namespace KDevelop;
0032 
0033 ClassTree::ClassTree(QWidget* parent, ClassBrowserPlugin* plugin)
0034     : QTreeView(parent)
0035     , m_plugin(plugin)
0036     , m_tooltip(nullptr)
0037 {
0038     header()->hide();
0039 
0040     setIndentation(10);
0041     setUniformRowHeights(true);
0042 
0043     connect(this, &ClassTree::activated, this, &ClassTree::itemActivated);
0044 }
0045 
0046 ClassTree::~ClassTree()
0047 {
0048 }
0049 
0050 static bool _populatingClassBrowserContextMenu = false;
0051 
0052 bool ClassTree::populatingClassBrowserContextMenu()
0053 {
0054     return _populatingClassBrowserContextMenu;
0055 }
0056 
0057 void ClassTree::contextMenuEvent(QContextMenuEvent* e)
0058 {
0059     auto* menu = new QMenu(this);
0060     QModelIndex index = indexAt(e->pos());
0061     if (index.isValid()) {
0062         Context* c;
0063         {
0064             DUChainReadLocker readLock(DUChain::lock());
0065             if (auto* decl = dynamic_cast<Declaration*>(model()->duObjectForIndex(index)))
0066                 c = new DeclarationContext(decl);
0067             else
0068             {
0069                 delete menu;
0070                 return;
0071             }
0072         }
0073         _populatingClassBrowserContextMenu = true;
0074 
0075         QList<ContextMenuExtension> extensions =
0076             ICore::self()->pluginController()->queryPluginsForContextMenuExtensions(c, menu);
0077         ContextMenuExtension::populateMenu(menu, extensions);
0078 
0079         _populatingClassBrowserContextMenu = false;
0080     }
0081 
0082     if (!menu->actions().isEmpty())
0083         menu->exec(e->globalPos());
0084     delete menu;
0085 }
0086 
0087 bool ClassTree::event(QEvent* event)
0088 {
0089     if (event->type() == QEvent::ToolTip) {
0090         // if we request a tooltip over a duobject item, show a tooltip for it
0091         auto* helpEvent = static_cast<QHelpEvent*>(event);
0092         const QModelIndex idxView = indexAt(helpEvent->pos());
0093 
0094         DUChainReadLocker readLock(DUChain::lock());
0095         if (auto* decl = dynamic_cast<Declaration*>(model()->duObjectForIndex(idxView))) {
0096             if (m_tooltip) {
0097                 m_tooltip->close();
0098             }
0099             if (auto* navigationWidget = decl->topContext()->createNavigationWidget(decl)) {
0100                 m_tooltip = new KDevelop::NavigationToolTip(this, helpEvent->globalPos() + QPoint(40,
0101                                                                                                   0), navigationWidget);
0102                 m_tooltip->resize(navigationWidget->sizeHint() + QSize(10, 10));
0103                 ActiveToolTip::showToolTip(m_tooltip);
0104                 return true;
0105             }
0106         }
0107     }
0108 
0109     return QAbstractItemView::event(event);
0110 }
0111 
0112 ClassModel* ClassTree::model()
0113 {
0114     return static_cast<ClassModel*>(QTreeView::model());
0115 }
0116 
0117 void ClassTree::itemActivated(const QModelIndex& index)
0118 {
0119     DUChainReadLocker readLock(DUChain::lock());
0120 
0121     DeclarationPointer decl = DeclarationPointer(dynamic_cast<Declaration*>(model()->duObjectForIndex(index)));
0122     readLock.unlock();
0123 
0124 // Delegate to plugin function
0125     m_plugin->showDefinition(decl);
0126 
0127     if (isExpanded(index))
0128         collapse(index);
0129     else
0130         expand(index);
0131 }
0132 
0133 void ClassTree::highlightIdentifier(const KDevelop::IndexedQualifiedIdentifier& a_id)
0134 {
0135     QModelIndex index = model()->indexForIdentifier(a_id);
0136     if (!index.isValid())
0137         return;
0138 
0139     // expand and select the item.
0140     selectionModel()->select(index, QItemSelectionModel::ClearAndSelect);
0141     scrollTo(index, PositionAtCenter);
0142     horizontalScrollBar()->setValue(horizontalScrollBar()->minimum());
0143     expand(index);
0144 }
0145 
0146 #include "moc_classtree.cpp"