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 | SPDX-FileCopyrightText: 2022-2024 Waqar Ahmed <waqar.17a@gmail.com> |
5 | |
6 | SPDX-License-Identifier: LGPL-2.0-or-later |
7 | */ |
8 | |
9 | #ifndef KATECOMPLETIONWIDGET_H |
10 | #define KATECOMPLETIONWIDGET_H |
11 | |
12 | #include <QElapsedTimer> |
13 | #include <QFrame> |
14 | #include <QObject> |
15 | #include <QPointer> |
16 | |
17 | #include <ktexteditor_export.h> |
18 | |
19 | #include <ktexteditor/codecompletionmodel.h> |
20 | #include <ktexteditor/movingrange.h> |
21 | |
22 | class QToolButton; |
23 | class QPushButton; |
24 | class QLabel; |
25 | class QTimer; |
26 | |
27 | namespace KTextEditor |
28 | { |
29 | class ViewPrivate; |
30 | } |
31 | class DocTip; |
32 | class KateCompletionModel; |
33 | class KateCompletionTree; |
34 | class KateArgumentHintTree; |
35 | class KateArgumentHintModel; |
36 | class ArgumentHintWidget; |
37 | |
38 | /** |
39 | * This is the code completion's main widget, and also contains the |
40 | * core interface logic. |
41 | * |
42 | * @author Hamish Rodda <rodda@kde.org> |
43 | */ |
44 | class KTEXTEDITOR_EXPORT KateCompletionWidget : public QFrame |
45 | { |
46 | Q_OBJECT |
47 | |
48 | public: |
49 | explicit KateCompletionWidget(KTextEditor::ViewPrivate *parent); |
50 | ~KateCompletionWidget() override; |
51 | |
52 | KTextEditor::ViewPrivate *view() const; |
53 | KateCompletionTree *treeView() const; |
54 | |
55 | bool isCompletionActive() const; |
56 | void startCompletion(KTextEditor::CodeCompletionModel::InvocationType invocationType, |
57 | const QList<KTextEditor::CodeCompletionModel *> &models = QList<KTextEditor::CodeCompletionModel *>()); |
58 | void startCompletion(KTextEditor::Range word, |
59 | KTextEditor::CodeCompletionModel *model, |
60 | KTextEditor::CodeCompletionModel::InvocationType invocationType = KTextEditor::CodeCompletionModel::ManualInvocation); |
61 | void startCompletion(KTextEditor::Range word, |
62 | const QList<KTextEditor::CodeCompletionModel *> &models = QList<KTextEditor::CodeCompletionModel *>(), |
63 | KTextEditor::CodeCompletionModel::InvocationType invocationType = KTextEditor::CodeCompletionModel::ManualInvocation); |
64 | void userInvokedCompletion(); |
65 | |
66 | public Q_SLOTS: |
67 | // Executed when return is pressed while completion is active. |
68 | bool execute(); |
69 | void cursorDown(); |
70 | void cursorUp(); |
71 | |
72 | public: |
73 | enum Direction { |
74 | Down, |
75 | Up, |
76 | }; |
77 | |
78 | void tabCompletion(Direction direction = Down); |
79 | |
80 | void toggleDocumentation(); |
81 | |
82 | const KateCompletionModel *model() const; |
83 | KateCompletionModel *model(); |
84 | |
85 | void registerCompletionModel(KTextEditor::CodeCompletionModel *model); |
86 | void unregisterCompletionModel(KTextEditor::CodeCompletionModel *model); |
87 | bool isCompletionModelRegistered(KTextEditor::CodeCompletionModel *model) const; |
88 | QList<KTextEditor::CodeCompletionModel *> codeCompletionModels() const; |
89 | |
90 | int automaticInvocationDelay() const; |
91 | void setAutomaticInvocationDelay(int delay); |
92 | |
93 | void setIgnoreBufferSignals(bool ignore) const; |
94 | |
95 | bool m_ignoreBufferSignals = false; |
96 | |
97 | struct CompletionRange { |
98 | CompletionRange() |
99 | { |
100 | } |
101 | explicit CompletionRange(KTextEditor::MovingRange *r) |
102 | : range(r) |
103 | { |
104 | } |
105 | |
106 | bool operator==(const CompletionRange &rhs) const |
107 | { |
108 | return range->toRange() == rhs.range->toRange(); |
109 | } |
110 | |
111 | KTextEditor::MovingRange *range = nullptr; |
112 | // Whenever the cursor goes before this position, the completion is stopped, unless it is invalid. |
113 | KTextEditor::Cursor leftBoundary; |
114 | }; |
115 | |
116 | KTextEditor::MovingRange *completionRange(KTextEditor::CodeCompletionModel *model = nullptr) const; |
117 | QMap<KTextEditor::CodeCompletionModel *, CompletionRange> completionRanges() const; |
118 | |
119 | // Navigation |
120 | void pageDown(); |
121 | void pageUp(); |
122 | void top(); |
123 | void bottom(); |
124 | |
125 | QWidget *currentEmbeddedWidget(); |
126 | |
127 | void updatePosition(bool force = false); |
128 | bool eventFilter(QObject *watched, QEvent *event) override; |
129 | |
130 | KateArgumentHintModel *argumentHintModel() const; |
131 | |
132 | /// Called by KateViewInternal, because we need the specific information from the event. |
133 | |
134 | void updateHeight(); |
135 | |
136 | void showDocTip(const QModelIndex &idx); |
137 | DocTip *docTip() const |
138 | { |
139 | return m_docTip; |
140 | } |
141 | |
142 | bool handleShortcutOverride(QKeyEvent *e); |
143 | |
144 | int elapsedMSSinceShowing() |
145 | { |
146 | return m_timeSinceShowing.elapsed(); |
147 | } |
148 | |
149 | static constexpr int minRequiredMsToAcceptCompletion() |
150 | { |
151 | return 200; |
152 | } |
153 | |
154 | public Q_SLOTS: |
155 | void waitForModelReset(); |
156 | |
157 | void abortCompletion(); |
158 | void automaticInvocation(); |
159 | |
160 | /* void updateFocus();*/ |
161 | void argumentHintsChanged(bool hasContent); |
162 | |
163 | bool navigateUp(); |
164 | bool navigateDown(); |
165 | bool navigateLeft(); |
166 | bool navigateRight(); |
167 | bool navigateAccept(); |
168 | bool navigateBack(); |
169 | |
170 | protected: |
171 | void showEvent(QShowEvent *event) override; |
172 | void resizeEvent(QResizeEvent *event) override; |
173 | void moveEvent(QMoveEvent *event) override; |
174 | void focusOutEvent(QFocusEvent *event) override; |
175 | |
176 | private Q_SLOTS: |
177 | void completionModelReset(); |
178 | void modelDestroyed(QObject *model); |
179 | void modelContentChanged(); |
180 | void cursorPositionChanged(); |
181 | void modelReset(); |
182 | void rowsInserted(const QModelIndex &parent, int row, int rowEnd); |
183 | void viewFocusOut(); |
184 | |
185 | void wrapLine(KTextEditor::Document *document, KTextEditor::Cursor position); |
186 | void unwrapLine(KTextEditor::Document *, int line); |
187 | void insertText(KTextEditor::Document *, KTextEditor::Cursor position, const QString &text); |
188 | void removeText(KTextEditor::Document *, KTextEditor::Range range, const QString &); |
189 | |
190 | private: |
191 | KTEXTEDITOR_NO_EXPORT |
192 | void updateAndShow(); |
193 | KTEXTEDITOR_NO_EXPORT |
194 | void updateArgumentHintGeometry(); |
195 | KTEXTEDITOR_NO_EXPORT |
196 | QModelIndex selectedIndex() const; |
197 | |
198 | KTEXTEDITOR_NO_EXPORT |
199 | void clear(); |
200 | |
201 | KTEXTEDITOR_NO_EXPORT |
202 | void completionRangeChanged(KTextEditor::CodeCompletionModel *, const KTextEditor::Range &word); |
203 | |
204 | KTEXTEDITOR_NO_EXPORT |
205 | QString tailString() const; |
206 | |
207 | KTEXTEDITOR_NO_EXPORT |
208 | void deleteCompletionRanges(); |
209 | |
210 | KTEXTEDITOR_NO_EXPORT |
211 | void onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList<int> &roles = QList<int>()); |
212 | |
213 | private: |
214 | QList<KTextEditor::CodeCompletionModel *> m_sourceModels; |
215 | KateCompletionModel *m_presentationModel; |
216 | |
217 | QMap<KTextEditor::CodeCompletionModel *, CompletionRange> m_completionRanges; |
218 | QSet<KTextEditor::CodeCompletionModel *> m_waitingForReset; |
219 | |
220 | KTextEditor::Cursor m_lastCursorPosition; |
221 | |
222 | KTextEditor::ViewPrivate *m_view; |
223 | KateCompletionTree *m_entryList; |
224 | KateArgumentHintModel *m_argumentHintModel; |
225 | // KateArgumentHintTree *m_argumentHintTree; |
226 | ArgumentHintWidget *m_argumentHintWidget; |
227 | DocTip *m_docTip; |
228 | |
229 | QTimer *m_automaticInvocationTimer; |
230 | |
231 | KTextEditor::Cursor m_automaticInvocationAt; |
232 | QString m_automaticInvocationLine; |
233 | int m_automaticInvocationDelay; |
234 | |
235 | bool m_lastInsertionByUser; |
236 | bool m_isSuspended; |
237 | bool m_dontShowArgumentHints; // Used temporarily to prevent flashing |
238 | bool m_needShow; |
239 | |
240 | bool m_hadCompletionNavigation; |
241 | |
242 | bool m_haveExactMatch; |
243 | |
244 | bool m_noAutoHide; |
245 | |
246 | /** |
247 | * is a completion edit ongoing? |
248 | */ |
249 | bool m_completionEditRunning; |
250 | |
251 | int m_expandedAddedHeightBase; |
252 | |
253 | KTextEditor::CodeCompletionModel::InvocationType m_lastInvocationType; |
254 | |
255 | QElapsedTimer m_timeSinceShowing; |
256 | }; |
257 | |
258 | #endif |
259 | |