1 /*
2 SPDX-FileCopyrightText: 2006 Adam Treat <treat@kde.org>
3 SPDX-FileCopyrightText: 2006-2007 Hamish Rodda <rodda@kde.org>
4 SPDX-FileCopyrightText: 2009 Lior Mualem <lior.m.kde@gmail.com>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8
9 #include "classtree.h"
10
11 #include <QMenu>
12 #include <QHeaderView>
13 #include <QContextMenuEvent>
14 #include <QScrollBar>
15
16 #include "interfaces/contextmenuextension.h"
17 #include "interfaces/icore.h"
18 #include "interfaces/idocument.h"
19 #include "interfaces/iplugincontroller.h"
20
21 #include "language/interfaces/codecontext.h"
22
23 #include "language/duchain/duchainbase.h"
24 #include "language/duchain/duchain.h"
25 #include "language/duchain/duchainlock.h"
26 #include "language/duchain/declaration.h"
27
28 #include "language/classmodel/classmodel.h"
29 #include "classbrowserplugin.h"
30
31 using namespace KDevelop;
32
ClassTree(QWidget * parent,ClassBrowserPlugin * plugin)33 ClassTree::ClassTree(QWidget* parent, ClassBrowserPlugin* plugin)
34 : QTreeView(parent)
35 , m_plugin(plugin)
36 , m_tooltip(nullptr)
37 {
38 header()->hide();
39
40 setIndentation(10);
41 setUniformRowHeights(true);
42
43 connect(this, &ClassTree::activated, this, &ClassTree::itemActivated);
44 }
45
~ClassTree()46 ClassTree::~ClassTree()
47 {
48 }
49
50 static bool _populatingClassBrowserContextMenu = false;
51
populatingClassBrowserContextMenu()52 bool ClassTree::populatingClassBrowserContextMenu()
53 {
54 return _populatingClassBrowserContextMenu;
55 }
56
contextMenuEvent(QContextMenuEvent * e)57 void ClassTree::contextMenuEvent(QContextMenuEvent* e)
58 {
59 auto* menu = new QMenu(this);
60 QModelIndex index = indexAt(e->pos());
61 if (index.isValid()) {
62 Context* c;
63 {
64 DUChainReadLocker readLock(DUChain::lock());
65 if (auto* decl = dynamic_cast<Declaration*>(model()->duObjectForIndex(index)))
66 c = new DeclarationContext(decl);
67 else
68 {
69 delete menu;
70 return;
71 }
72 }
73 _populatingClassBrowserContextMenu = true;
74
75 QList<ContextMenuExtension> extensions =
76 ICore::self()->pluginController()->queryPluginsForContextMenuExtensions(c, menu);
77 ContextMenuExtension::populateMenu(menu, extensions);
78
79 _populatingClassBrowserContextMenu = false;
80 }
81
82 if (!menu->actions().isEmpty())
83 menu->exec(e->globalPos());
84 delete menu;
85 }
86
event(QEvent * event)87 bool ClassTree::event(QEvent* event)
88 {
89 if (event->type() == QEvent::ToolTip) {
90 // if we request a tooltip over a duobject item, show a tooltip for it
91 auto* helpEvent = static_cast<QHelpEvent*>(event);
92 const QModelIndex idxView = indexAt(helpEvent->pos());
93
94 DUChainReadLocker readLock(DUChain::lock());
95 if (auto* decl = dynamic_cast<Declaration*>(model()->duObjectForIndex(idxView))) {
96 if (m_tooltip) {
97 m_tooltip->close();
98 }
99 if (auto* navigationWidget = decl->topContext()->createNavigationWidget(decl)) {
100 m_tooltip = new KDevelop::NavigationToolTip(this, helpEvent->globalPos() + QPoint(40,
101 0), navigationWidget);
102 m_tooltip->resize(navigationWidget->sizeHint() + QSize(10, 10));
103 ActiveToolTip::showToolTip(m_tooltip);
104 return true;
105 }
106 }
107 }
108
109 return QAbstractItemView::event(event);
110 }
111
model()112 ClassModel* ClassTree::model()
113 {
114 return static_cast<ClassModel*>(QTreeView::model());
115 }
116
itemActivated(const QModelIndex & index)117 void ClassTree::itemActivated(const QModelIndex& index)
118 {
119 DUChainReadLocker readLock(DUChain::lock());
120
121 DeclarationPointer decl = DeclarationPointer(dynamic_cast<Declaration*>(model()->duObjectForIndex(index)));
122 readLock.unlock();
123
124 // Delegate to plugin function
125 m_plugin->showDefinition(decl);
126
127 if (isExpanded(index))
128 collapse(index);
129 else
130 expand(index);
131 }
132
highlightIdentifier(const KDevelop::IndexedQualifiedIdentifier & a_id)133 void ClassTree::highlightIdentifier(const KDevelop::IndexedQualifiedIdentifier& a_id)
134 {
135 QModelIndex index = model()->indexForIdentifier(a_id);
136 if (!index.isValid())
137 return;
138
139 // expand and select the item.
140 selectionModel()->select(index, QItemSelectionModel::ClearAndSelect);
141 scrollTo(index, PositionAtCenter);
142 horizontalScrollBar()->setValue(horizontalScrollBar()->minimum());
143 expand(index);
144 }
145