KTextEditor

katecompletionmodel.h
1/*
2 SPDX-FileCopyrightText: 2005-2006 Hamish Rodda <rodda@kde.org>
3 SPDX-FileCopyrightText: 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#ifndef KATECOMPLETIONMODEL_H
9#define KATECOMPLETIONMODEL_H
10
11#include <QAbstractProxyModel>
12#include <QList>
13#include <QPair>
14
15#include <ktexteditor/codecompletionmodel.h>
16
17#include "expandingtree/expandingwidgetmodel.h"
18#include <ktexteditor_export.h>
19
20#include <set>
21
23class KateArgumentHintModel;
24namespace KTextEditor
25{
26class ViewPrivate;
27}
28class QWidget;
29class QTextEdit;
30class QTimer;
31class HierarchicalModelHandler;
32
33/**
34 * This class has the responsibility for filtering, sorting, and manipulating
35 * code completion data provided by a CodeCompletionModel.
36 *
37 * @author Hamish Rodda <rodda@kde.org>
38 */
39class KateCompletionModel : public ExpandingWidgetModel
40{
42
43public:
44 enum InternalRole {
45 IsNonEmptyGroup = KTextEditor::CodeCompletionModel::LastExtraItemDataRole + 1,
46 };
47
48 explicit KateCompletionModel(KateCompletionWidget *parent = nullptr);
49 ~KateCompletionModel() override;
50
51 QList<KTextEditor::CodeCompletionModel *> completionModels() const;
52 void clearCompletionModels();
53 KTEXTEDITOR_EXPORT void addCompletionModel(KTextEditor::CodeCompletionModel *model);
54 KTEXTEDITOR_EXPORT void setCompletionModel(KTextEditor::CodeCompletionModel *model);
55 void setCompletionModels(const QList<KTextEditor::CodeCompletionModel *> &models);
56 KTEXTEDITOR_EXPORT void removeCompletionModel(KTextEditor::CodeCompletionModel *model);
57
58 KTextEditor::ViewPrivate *view() const;
59 KateCompletionWidget *widget() const;
60
61 KTEXTEDITOR_EXPORT QString currentCompletion(KTextEditor::CodeCompletionModel *model) const;
62 void setCurrentCompletion(QMap<KTextEditor::CodeCompletionModel *, QString> currentMatch);
63
64 int translateColumn(int sourceColumn) const;
65
66 /// Returns a common prefix for all current visible completion entries
67 /// If there is no common prefix, extracts the next useful prefix for the selected index
68 QString commonPrefix(QModelIndex selectedIndex) const;
69
70 void rowSelected(const QModelIndex &row) const;
71
72 bool indexIsItem(const QModelIndex &index) const override;
73
74 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
75 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
76 Qt::ItemFlags flags(const QModelIndex &index) const override;
77 bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
78 virtual bool hasIndex(int row, int column, const QModelIndex &parent = QModelIndex()) const;
79 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
80
81 // Disabled in case of bugs, reenable once fully debugged.
82 // virtual QMap<int, QVariant> itemData ( const QModelIndex & index ) const;
83 QModelIndex parent(const QModelIndex &index) const override;
84 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
85
86 /// Maps from this display-model into the appropriate source code-completion model
87 virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const;
88
89 /// Maps from an index in a source-model to the index of the item in this display-model
90 virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const;
91
92 enum gm {
93 ScopeType = 0x1,
94 Scope = 0x2,
95 AccessType = 0x4,
96 ItemType = 0x8
97 };
98
99 enum { // An own property that will be used to mark the best-matches group internally
100 BestMatchesProperty = 2 * KTextEditor::CodeCompletionModel::LastProperty
101 };
102
103 Q_DECLARE_FLAGS(GroupingMethods, gm)
104
105 static const int ScopeTypeMask = 0x380000;
106 static const int AccessTypeMask = 0x7;
107 static const int ItemTypeMask = 0xfe0;
108
109 void debugStats();
110
111 /// Returns whether one of the filtered items exactly matches its completion string
113
114 KTEXTEDITOR_EXPORT uint filteredItemCount() const;
115
116protected:
117 int contextMatchQuality(const QModelIndex &index) const override;
118
120 void expandIndex(const QModelIndex &index);
121 // Emitted whenever something has changed about the group of argument-hints
122 void argumentHintsChanged();
123
124private Q_SLOTS:
125 void slotRowsInserted(const QModelIndex &parent, int start, int end);
126 void slotRowsRemoved(const QModelIndex &parent, int start, int end);
127 void slotModelReset();
128
129 // Updates the best-matches group
130 void updateBestMatches();
131 // Makes sure that the ungrouped group contains each item only once
132 // Must only be called right after the group was created
133 void makeGroupItemsUnique(bool onlyFiltered = false);
134
135private:
136 typedef QPair<KTextEditor::CodeCompletionModel *, QModelIndex> ModelRow;
137 virtual int contextMatchQuality(const ModelRow &sourceRow) const;
138
139 QTreeView *treeView() const override;
140
141 friend class KateArgumentHintModel;
142 static ModelRow modelRowPair(const QModelIndex &index);
143
144 // Represents a source row; provides sorting method
145 class Item
146 {
147 public:
148 Item(bool doInitialMatch, KateCompletionModel *model, const HierarchicalModelHandler &handler, ModelRow sourceRow);
149
150 // Returns true if the item is not filtered and matches the current completion string
151 bool isVisible() const;
152
153 enum MatchType {
154 NoMatch = 0,
155 PerfectMatch,
156 StartsWithMatch,
157 AbbreviationMatch,
158 ContainsMatch
159 };
160 MatchType match(KateCompletionModel *model);
161
162 const ModelRow &sourceRow() const;
163
164 // Sorting operator
165 bool lessThan(KateCompletionModel *model, const Item &rhs) const;
166
167 bool haveExactMatch() const
168 {
169 return m_haveExactMatch;
170 }
171
172 QString name() const
173 {
174 return m_nameColumn;
175 }
176
177 private:
178 ModelRow m_sourceRow;
179
180 QString m_nameColumn;
181
182 int inheritanceDepth;
183
184 // True when currently matching completion string
185 MatchType matchCompletion;
186 bool m_haveExactMatch;
187 bool m_unimportant;
188 };
189
190public:
191 // Grouping and sorting of rows
192 class Group
193 {
194 public:
195 explicit Group(const QString &title, int attribute, KateCompletionModel *model);
196
197 void addItem(const Item &i, bool notifyModel = false);
198 /// Removes the item specified by \a row. Returns true if a change was made to rows.
199 bool removeItem(const ModelRow &row);
200 void resort();
201 void clear();
202 // Returns whether this group should be ordered before other
203 bool orderBefore(Group *other) const;
204 // Returns a number that can be used for ordering
205 int orderNumber() const;
206
207 /// Returns the row in the this group's filtered list of the given model-row in a source-model
208 ///-1 if the item is not in the filtered list
209 ///@todo Implement an efficient way of doing this map, that does _not_ iterate over all items!
210 int rowOf(const ModelRow &item)
211 {
212 for (int a = 0; a < (int)filtered.size(); ++a) {
213 if (filtered[a].sourceRow() == item) {
214 return a;
215 }
216 }
217 return -1;
218 }
219
220 KateCompletionModel *model;
221 int attribute;
222 QString title, scope;
223 std::vector<Item> filtered;
224 std::vector<Item> prefilter;
225 bool isEmpty;
226 //-1 if none was set
227 int customSortingKey;
228 };
229
230 typedef std::set<Group *> GroupSet;
231
232 bool hasGroups() const
233 {
234 // qCDebug(LOG_KTE) << "m_groupHash.size()"<<m_groupHash.size();
235 // qCDebug(LOG_KTE) << "m_rowTable.count()"<<m_rowTable.count();
236 return m_hasGroups;
237 }
238
239private:
240 QString commonPrefixInternal(const QString &forcePrefix) const;
241 /// @note performs model reset
242 void createGroups();
243 /// Creates all sub-items of index i, or the item corresponding to index i. Returns the affected groups.
244 /// i must be an index in the source model
245 GroupSet createItems(const HierarchicalModelHandler &, const QModelIndex &i, bool notifyModel = false);
246 /// Deletes all sub-items of index i, or the item corresponding to index i. Returns the affected groups.
247 /// i must be an index in the source model
248 GroupSet deleteItems(const QModelIndex &i);
249 Group *createItem(const HierarchicalModelHandler &, const QModelIndex &i, bool notifyModel = false);
250 /// @note Make sure you're in a {begin,end}ResetModel block when calling this!
251 void clearGroups();
252 void hideOrShowGroup(Group *g, bool notifyModel = false);
253 /// When forceGrouping is enabled, all given attributes will be used for grouping, regardless of the completion settings.
254 Group *fetchGroup(int attribute, bool forceGrouping = false);
255 // If this returns nonzero on an index, the index is the header of the returned group
256 Group *groupForIndex(const QModelIndex &index) const;
257 inline Group *groupOfParent(const QModelIndex &child) const
258 {
259 return static_cast<Group *>(child.internalPointer());
260 }
261 QModelIndex indexForRow(Group *g, int row) const;
262 QModelIndex indexForGroup(Group *g) const;
263
264 enum changeTypes {
265 Broaden,
266 Narrow,
267 Change
268 };
269
270 // Returns whether the model needs to be reset
271 void changeCompletions(Group *g);
272
273 bool hasCompletionModel() const;
274
275 /// Removes attributes not used in grouping from the input \a attribute
276 int groupingAttributes(int attribute) const;
277 static int countBits(int value);
278
279 void resort();
280
281 KTEXTEDITOR_EXPORT static bool matchesAbbreviation(const QString &word, const QString &typed, int &score);
282 // exported for completion_test
283
284 bool m_hasGroups = false;
285
286 // ### Runtime state
287 // General
290
291 // Column merging
292 const std::array<std::vector<int>, 3> m_columnMerges = {{
293 {0},
294 {1, 2, 3, 4},
295 {5},
296 }};
297
298 QTimer *m_updateBestMatchesTimer;
299
300 Group *m_ungrouped;
301 Group *m_argumentHints; // The argument-hints will be passed on to another model, to be shown in another widget
302 Group *m_bestMatches; // A temporary group used for holding the best matches of all visible items
303
304 // Storing the sorted order
305 std::vector<Group *> m_rowTable;
306 std::vector<Group *> m_emptyGroups;
307 // Quick access to each specific group (if it exists)
308 QMultiHash<int, Group *> m_groupHash;
309 // Maps custom group-names to their specific groups
310 QHash<QString, Group *> m_customGroupHash;
311
312 friend class CompletionTest;
313};
314
315Q_DECLARE_OPERATORS_FOR_FLAGS(KateCompletionModel::GroupingMethods)
316
317#endif
An item model for providing code completion, and meta information for enhanced presentation.
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Does not request data from index, this only returns local data like highlighting for expanded rows an...
virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const
Maps from this display-model into the appropriate source code-completion model.
bool indexIsItem(const QModelIndex &index) const override
Should return true if the given row should be painted like a contained item(as opposed to label-rows ...
bool shouldMatchHideCompletionList() const
Returns whether one of the filtered items exactly matches its completion string.
QString commonPrefix(QModelIndex selectedIndex) const
Returns a common prefix for all current visible completion entries If there is no common prefix,...
int contextMatchQuality(const QModelIndex &index) const override
virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const
Maps from an index in a source-model to the index of the item in this display-model.
void rowSelected(const QModelIndex &row) const
This is the code completion's main widget, and also contains the core interface logic.
Q_SCRIPTABLE QString start(QString train="")
The KTextEditor namespace contains all the public API that is required to use the KTextEditor compone...
virtual QModelIndexList match(const QModelIndex &start, int role, const QVariant &value, int hits, Qt::MatchFlags flags) const const
void * internalPointer() const const
Q_OBJECTQ_OBJECT
Q_SIGNALSQ_SIGNALS
Q_SLOTSQ_SLOTS
QObject * parent() const const
DisplayRole
typedef ItemFlags
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Feb 21 2025 11:52:51 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.