KTextEditor

codecompletionmodel.h
1/*
2 SPDX-FileCopyrightText: 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de>
3 SPDX-FileCopyrightText: 2005-2006 Hamish Rodda <rodda@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#ifndef KTEXTEDITOR_CODECOMPLETIONMODEL_H
9#define KTEXTEDITOR_CODECOMPLETIONMODEL_H
10
11#include <QModelIndex>
12#include <ktexteditor/range.h>
13#include <ktexteditor_export.h>
14
15namespace KTextEditor
16{
17class Document;
18class View;
19
20/**
21 * \class CodeCompletionModel codecompletionmodel.h <KTextEditor/CodeCompletionModel>
22 *
23 * \short An item model for providing code completion, and meta information for
24 * enhanced presentation.
25 *
26 * \section compmodel_intro Introduction
27 *
28 * The CodeCompletionModel is the actual workhorse to provide code completions
29 * in a KTextEditor::View. It is meant to be used in conjunction with the
30 * View. The CodeCompletionModel is not meant to be used as
31 * is. Rather you need to implement a subclass of CodeCompletionModel to actually
32 * generate completions appropriate for your type of Document.
33 *
34 * \section compmodel_implementing Implementing a CodeCompletionModel
35 *
36 * The CodeCompletionModel is a QAbstractItemModel, and can be subclassed in the
37 * same way. It provides default implementations of several members, however, so
38 * in most cases (if your completions are essentially a non-hierarchical, flat list
39 * of matches) you will only need to overload few virtual functions.
40 *
41 * \section compmodel_flatlist Implementing a CodeCompletionModel for a flat list
42 *
43 * For the simple case of a flat list of completions, you will need to:
44 * - Implement completionInvoked() to actually generate/update the list of completion
45 * matches
46 * - implement itemData() (or QAbstractItemModel::data()) to return the information that
47 * should be displayed for each match.
48 * - use setRowCount() to reflect the number of matches.
49 *
50 * \section compmodel_roles_columns Columns and roles
51 *
52 * \todo document the meaning and usage of the columns and roles used by the
53 * Completion Interface
54 *
55 * \section compmodel_usage Using the new CodeCompletionModel
56 *
57 * To start using your KTextEditor::View Completion Interface.
58 *
59 * \section compmodel_controller ControllerInterface to get more control
60 *
61 * To have more control over code completion implement
62 * CodeCompletionModelControllerInterface in your CodeCompletionModel.
63 *
64 * \see CodeCompletionModelControllerInterface
65 * @author Hamish Rodda <rodda@kde.org>
66 */
67class KTEXTEDITOR_EXPORT CodeCompletionModel : public QAbstractItemModel
68{
69 Q_OBJECT
70
71public:
72 explicit CodeCompletionModel(QObject *parent);
73 ~CodeCompletionModel() override;
74
75 enum Columns {
76 Prefix = 0,
77 /// Icon representing the type of completion. We have a separate icon field
78 /// so that names remain aligned where only some completions have icons,
79 /// and so that they can be rearranged by the user.
81 Scope,
82 Name,
83 Arguments,
84 Postfix
85 };
86 static const int ColumnCount = Postfix + 1;
87
88 /// @see CompletionProperties
90 NoProperty = 0x0,
91 FirstProperty = 0x1,
92
93 // Access specifiers - no more than 1 per item
94 Public = 0x1,
95 Protected = 0x2,
96 Private = 0x4,
97
98 // Extra access specifiers - any number per item
99 Static = 0x8,
100 Const = 0x10,
101
102 // Type - no more than 1 per item (except for Template)
103 Namespace = 0x20,
104 Class = 0x40,
105 Struct = 0x80,
106 Union = 0x100,
107 Function = 0x200,
108 Variable = 0x400,
109 Enum = 0x800,
110 Template = 0x1000,
111 TypeAlias = 0x2000,
112
113 // Special attributes - any number per item
114 Virtual = 0x4000,
115 Override = 0x8000,
116 Inline = 0x10000,
117 Friend = 0x20000,
118 Signal = 0x40000,
119 Slot = 0x80000,
120
121 // Scope - no more than 1 per item
122 LocalScope = 0x100000,
123 NamespaceScope = 0x200000,
124 GlobalScope = 0x400000,
125
126 // Keep this in sync so the code knows when to stop
127 LastProperty = GlobalScope
128 };
129 /// Stores a combination of #CompletionProperty values.
131
132 /// @see HighlightMethods
134 NoHighlighting = 0x0,
135 InternalHighlighting = 0x1,
136 CustomHighlighting = 0x2
137 };
138 /// Stores a combination of #HighlightMethod values.
140
141 /// Meta information is passed through extra {Qt::ItemDataRole}s.
142 /// This information should be returned when requested on the Name column.
144 /// The model should return a set of CompletionProperties.
145 CompletionRole = Qt::UserRole,
146
147 /// The model should return an index to the scope
148 /// -1 represents no scope
149 /// \todo how to sort scope?
151
152 /**
153 * If requested, your model should try to determine whether the
154 * completion in question is a suitable match for the context (ie.
155 * is accessible, exported, + returns the data type required).
156 *
157 * The returned data should ideally be matched against the argument-hint context
158 * set earlier by SetMatchContext.
159 *
160 * Return an integer value that should be positive if the completion is suitable,
161 * and zero if the completion is not suitable. The value should be between 0 an 10, where
162 * 10 means perfect match.
163 *
164 * Return QVariant::Invalid if you are unable to determine this.
165 */
167
168 /**
169 * Is requested before MatchQuality(..) is requested. The item on which this is requested
170 * is an argument-hint item(@see ArgumentHintDepth). When this role is requested, the item should
171 * be noted, and whenever MatchQuality is requested, it should be computed by matching the item given
172 * with MatchQuality into the context chosen by SetMatchContext.
173 *
174 * Feel free to ignore this, but ideally you should return QVariant::Invalid to make clear that your model does not support this.
175 * */
177
178 /**
179 * Define which highlighting method will be used:
180 * - QVariant::Invalid - allows the editor to choose (usually internal highlighting)
181 * - QVariant::Integer - highlight as specified by HighlightMethods.
182 */
184
185 /**
186 * Allows an item to provide custom highlighting. Return a
187 * QList<QVariant> in the following format:
188 * - int startColumn (where 0 = start of the completion entry)
189 * - int endColumn (note: not length)
190 * - QTextFormat attribute (note: attribute may be a KTextEditor::Attribute, as it is a child class)
191 * If the attribute is invalid, and the item is an argument-hint, the text will be drawn with
192 * a background-color depending on match-quality, or yellow.
193 * You can use that to mark the actual arguments that are matched in an argument-hint.
194 *
195 * Repeat this triplet as many times as required, however each column must be >= the previous,
196 * and startColumn != endColumn.
197 */
199
200 /**
201 * Returns the inheritance depth of the completion. For example, a completion
202 * which comes from the base class would have depth 0, one from a parent class
203 * would have depth 1, one from that class' parent 2, etc. you can use this to
204 * symbolize the general distance of a completion-item from a user. It will be used
205 * for sorting.
206 */
208
209 /**
210 * This allows items in the completion-list to be expandable. If a model returns an QVariant bool value
211 * that evaluates to true, the completion-widget will draw a handle to expand the item, and will also make
212 * that action accessible through keyboard.
213 */
215 /**
216 * After a model returned true for a row on IsExpandable, the row may be expanded by the user.
217 * When this happens, ExpandingWidget is requested.
218 *
219 * The model may return two types of values:
220 * QWidget*:
221 * If the model returns a QVariant of type QWidget*, the code-completion takes over the given widget
222 * and embeds it into the completion-list under the completion-item. The widget will be automatically deleted at some point.
223 * The completion-widget will use the height of the widget as a hint for its preferred size, but it will
224 * resize the widget at will.
225 * QString:
226 * If the mode returns a QVariant of type QString, it will create a small html-widget showing the given html-code,
227 * and embed it into the completion-list under the completion-item.
228 *
229 * @warning
230 * @code
231 * QWidget* widget;
232 * return QVariant(widget);
233 * @endcode
234 * Will not work correctly!
235 * Use the following instead.:
236 * @code
237 * QVariant v;
238 * v.setValue<QWidget*>(widget);
239 * return v;
240 * @endcode
241 *
242 * */
244 /**
245 * Whenever an item is selected, this will be requested from the underlying model.
246 * It may be used as a simple notification that the item was selected.
247 *
248 * Above that, the model may return a QString, which then should then contain html-code. A html-widget
249 * will then be displayed as a one- or two-liner under the currently selected item(it will be partially expanded)
250 * */
252
253 /**Is this completion-item an argument-hint?
254 * The model should return an integral positive number if the item is an argument-hint, and QVariant() or 0 if it is not one.
255 *
256 * The returned depth-integer is important for sorting and matching.
257 * Example:
258 * "otherFunction(function1(function2("
259 * all functions named function2 should have ArgumentHintDepth 1, all functions found for function1 should have ArgumentHintDepth 2,
260 * and all functions named otherFunction should have ArgumentHintDepth 3
261 *
262 * Later, a completed item may then be matched with the first argument of function2, the return-type of function2 with the first
263 * argument-type of function1, and the return-type of function1 with the argument-type of otherFunction.
264 *
265 * If the model returns a positive value on this role for a row, the content will be treated specially:
266 * - It will be shown in a separate argument-hint list
267 * - It will be sorted by Argument-hint depth
268 * - Match-qualities will be illustrated by differently highlighting the matched argument if possible
269 * The argument-hint list strings will be built from all source-model, with a little special behavior:
270 * Prefix - Should be all text of the function-signature up to left of the matched argument of the function
271 * Name - Should be the type and name of the function's matched argument. This part will be highlighted differently depending on the match-quality
272 * Suffix - Should be all the text of the function-signature behind the matched argument
273 *
274 * Example: You are matching a function with signature "void test(int param1, int param2)", and you are matching the first argument.
275 * The model should then return:
276 * Prefix: "void test("
277 * Name: "int param1"
278 * Suffix: ", int param2)"
279 *
280 * If you don't use the highlighting, matching, etc. you can also return the columns in the usual way.
281 * */
283
284 /**
285 * This will be requested for each item to ask whether it should be included in computing a best-matches list.
286 * If you return a valid positive integer n here, the n best matches will be listed at top of the completion-list separately.
287 *
288 * This is expensive because all items of the whole completion-list will be tested for their matching-quality, with each of the level 1
289 * argument-hints.
290 *
291 * For that reason the end-user should be able to disable this feature.
292 */
294
295 /**
296 * The following three enumeration-values are only used on expanded completion-list items that contain an expanding-widget(@see ExpandingWidget)
297 *
298 * You can use them to allow the user to interact with the widget by keyboard.
299 *
300 * AccessibilityNext will be requested on an item if it is expanded, contains an expanding-widget, and the user triggers a special navigation
301 * short-cut to go to navigate to the next position within the expanding-widget(if applicable).
302 *
303 * Return QVariant(true) if the input was used.
304 * */
306 /**
307 * AccessibilityPrevious will be requested on an item if it is expanded, contains an expanding-widget, and the user triggers a special navigation
308 * short-cut to go to navigate to the previous position within the expanding-widget(if applicable).
309 *
310 * Return QVariant(true) if the input was used.
311 * */
313 /**
314 * AccessibilityAccept will be requested on an item if it is expanded, contains an expanding-widget, and the user triggers a special
315 * shortcut to trigger the action associated with the position within the expanding-widget the user has navigated to using AccessibilityNext and
316 * AccessibilityPrevious.
317 *
318 * This should return QVariant(true) if an action was triggered, else QVariant(false) or QVariant().
319 * */
321
322 /**
323 * Using this Role, it is possible to greatly optimize the time needed to process very long completion-lists.
324 *
325 * In the completion-list, the items are usually ordered by some properties like argument-hint depth,
326 * inheritance-depth and attributes. Kate usually has to query the completion-models for these values
327 * for each item in the completion-list in order to extract the argument-hints and correctly sort the
328 * completion-list. However, with a very long completion-list, only a very small fraction of the items is actually
329 * visible.
330 *
331 * By using a tree structure you can give the items in a grouped order to kate, so it does not need to look at each
332 * item and query data in order to initially show the completion-list.
333 *
334 * This is how it works:
335 * - You create a tree-structure for your items
336 * - Every inner node of the tree defines one attribute value that all sub-nodes have in common.
337 * - When the inner node is queried for GroupRole, it should return the "ExtraItemDataRoles" that all sub-nodes have in common
338 * - When the inner node is then queried for that exact role, it should return that value.
339 * - No other queries will be done to inner nodes.
340 * - Every leaf node stands for an actual item in the completion list.
341 *
342 * The recommended grouping order is: Argument-hint depth, inheritance depth, attributes.
343 *
344 * This role can also be used to define completely custom groups, bypassing the editors builtin grouping:
345 * - Return Qt::DisplayRole when GroupRole is requested
346 * - Return the label text of the group when Qt::DisplayRole
347 * - Optional: Return an integer sorting-value when InheritanceDepth is requested. This number will
348 * be used to determine the order of the groups. The order of the builtin groups is:
349 * 1 = Best Matches, 100 = Local Scope, 200 = Public, 300 = Protected, 400 = Private, 500 = Namespace, 600 = Global
350 * You can pick any arbitrary number to position your group relative to these builtin groups.
351 * */
353
354 /**
355 * Return a nonzero value here to enforce sorting the item at the end of the list.
356 */
358
359 LastExtraItemDataRole
360 };
361
362 void setRowCount(int rowCount);
363
364 enum InvocationType {
365 AutomaticInvocation,
366 UserInvocation,
367 ManualInvocation
368 };
369
370 /**
371 * This function is responsible to generating / updating the list of current
372 * completions. The default implementation does nothing.
373 *
374 * When implementing this function, remember to call setRowCount() (or implement
375 * rowCount()), and to generate the appropriate change notifications (for instance
376 * by calling QAbstractItemModel::reset()).
377 * @param view The view to generate completions for
378 * @param range The range of text to generate completions for
379 * @param invocationType How the code completion was triggered
380 * */
381 virtual void completionInvoked(KTextEditor::View *view, const KTextEditor::Range &range, InvocationType invocationType);
382
383 /**
384 * This function is responsible for inserting a selected completion into the
385 * view. The default implementation replaces the text that the completions
386 * were based on with the Qt::DisplayRole of the Name column of the given match.
387 *
388 * @param view the view to insert the completion into
389 * @param word the Range that the completions are based on (what the user entered
390 * so far)
391 * @param index identifies the completion match to insert
392 * */
393 virtual void executeCompletionItem(KTextEditor::View *view, const Range &word, const QModelIndex &index) const;
394
395 // Reimplementations
396 /**
397 * Reimplemented from QAbstractItemModel::columnCount(). The default implementation
398 * returns ColumnCount for all indices.
399 * */
400 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
401 /**
402 * Reimplemented from QAbstractItemModel::index(). The default implementation
403 * returns a standard QModelIndex as long as the row and column are valid.
404 * */
405 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
406 /**
407 * Reimplemented from QAbstractItemModel::itemData(). The default implementation
408 * returns a map with the QAbstractItemModel::data() for all roles that are used
409 * by the CodeCompletionInterface. You will need to reimplement either this
410 * function or QAbstractItemModel::data() in your CodeCompletionModel.
411 * */
412 QMap<int, QVariant> itemData(const QModelIndex &index) const override;
413 /**
414 * Reimplemented from QAbstractItemModel::parent(). The default implementation
415 * returns an invalid QModelIndex for all items. This is appropriate for
416 * non-hierarchical / flat lists of completions.
417 * */
418 QModelIndex parent(const QModelIndex &index) const override;
419 /**
420 * Reimplemented from QAbstractItemModel::rowCount(). The default implementation
421 * returns the value set by setRowCount() for invalid (toplevel) indices, and 0
422 * for all other indices. This is appropriate for non-hierarchical / flat lists
423 * of completions
424 * */
425 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
426
427 /**
428 * This function returns true if the model needs grouping, otherwise false.
429 * The default is false if not changed via setHasGroups().
430 */
431 bool hasGroups() const;
432
433Q_SIGNALS:
434
435 /**
436 * Emit this if the code-completion for this model was invoked, some time is needed in order to get the data,
437 * and the model is reset once the data is available.
438 *
439 * This only has an effect if emitted from within completionInvoked(..).
440 *
441 * This prevents the code-completion list from showing until this model is reset,
442 * so there is no annoying flashing in the user-interface resulting from other models
443 * supplying their data earlier.
444 *
445 * @note The implementation may choose to show the completion-list anyway after some timeout
446 *
447 * @warning If you emit this, you _must_ also reset the model at some point,
448 * else the code-completion will be completely broken to the user.
449 * Consider that there may always be additional completion-models apart from yours.
450 *
451 * @since 4.3
452 */
454
455 /**
456 * Internal
457 */
459
460protected:
461 void setHasGroups(bool hasGroups);
462
463private:
464 class CodeCompletionModelPrivate *const d;
465};
466
467Q_DECLARE_OPERATORS_FOR_FLAGS(CodeCompletionModel::CompletionProperties)
468Q_DECLARE_OPERATORS_FOR_FLAGS(CodeCompletionModel::HighlightMethods)
469
470}
471
472#endif // KTEXTEDITOR_CODECOMPLETIONMODEL_H
An item model for providing code completion, and meta information for enhanced presentation.
@ Icon
Icon representing the type of completion.
void hasGroupsChanged(KTextEditor::CodeCompletionModel *model, bool hasGroups)
Internal.
void waitForReset()
Emit this if the code-completion for this model was invoked, some time is needed in order to get the ...
ExtraItemDataRoles
Meta information is passed through extra {Qt::ItemDataRole}s.
@ InheritanceDepth
Returns the inheritance depth of the completion.
@ GroupRole
Using this Role, it is possible to greatly optimize the time needed to process very long completion-l...
@ SetMatchContext
Is requested before MatchQuality(..) is requested.
@ HighlightingMethod
Define which highlighting method will be used:
@ ItemSelected
Whenever an item is selected, this will be requested from the underlying model.
@ AccessibilityAccept
AccessibilityAccept will be requested on an item if it is expanded, contains an expanding-widget,...
@ UnimportantItemRole
Return a nonzero value here to enforce sorting the item at the end of the list.
@ BestMatchesCount
This will be requested for each item to ask whether it should be included in computing a best-matches...
@ ScopeIndex
The model should return an index to the scope -1 represents no scope.
@ ExpandingWidget
After a model returned true for a row on IsExpandable, the row may be expanded by the user.
@ ArgumentHintDepth
Is this completion-item an argument-hint? The model should return an integral positive number if the ...
@ AccessibilityNext
The following three enumeration-values are only used on expanded completion-list items that contain a...
@ MatchQuality
If requested, your model should try to determine whether the completion in question is a suitable mat...
@ AccessibilityPrevious
AccessibilityPrevious will be requested on an item if it is expanded, contains an expanding-widget,...
@ CustomHighlight
Allows an item to provide custom highlighting.
@ IsExpandable
This allows items in the completion-list to be expandable.
An object representing a section of text, from one Cursor to another.
Variable for variable expansion.
Definition variable.h:35
A text widget with KXMLGUIClient that represents a Document.
Definition view.h:244
The KTextEditor namespace contains all the public API that is required to use the KTextEditor compone...
UserRole
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 17:01:56 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.