itom  4.1.0
codeCompletion.h
1 /* ********************************************************************
2  itom software
3  URL: http://www.uni-stuttgart.de/ito
4  Copyright (C) 2020, Institut fuer Technische Optik (ITO),
5  Universitaet Stuttgart, Germany
6 
7  This file is part of itom.
8 
9  itom is free software; you can redistribute it and/or modify it
10  under the terms of the GNU Library General Public Licence as published by
11  the Free Software Foundation; either version 2 of the Licence, or (at
12  your option) any later version.
13 
14  itom is distributed in the hope that it will be useful, but
15  WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
17  General Public Licence for more details.
18 
19  You should have received a copy of the GNU Library General Public License
20  along with itom. If not, see <http://www.gnu.org/licenses/>.
21 
22  Further hints:
23  ------------------------
24 
25  This file belongs to the code editor of itom. The code editor is
26  in major parts a fork / rewritten version of the python-based source
27  code editor PyQode from Colin Duquesnoy and others
28  (see https://github.com/pyQode). PyQode itself is licensed under
29  the MIT License (MIT).
30 
31  Some parts of the code editor of itom are also inspired by the
32  source code editor of the Spyder IDE (https://github.com/spyder-ide),
33  also licensed under the MIT License and developed by the Spyder Project
34  Contributors.
35 
36 *********************************************************************** */
37 
38 #ifndef CODECOMPLETION_H
39 #define CODECOMPLETION_H
40 
41 
42 #include "../../python/pythonJedi.h"
43 
44 #include "../utils/utils.h"
45 #include "../toolTip.h"
46 #include "../mode.h"
47 #include <qevent.h>
48 #include <qobject.h>
49 #include <qpair.h>
50 #include <qstring.h>
51 #include <qlist.h>
52 #include <qsortfilterproxymodel.h>
53 #include <qregexp.h>
54 #include <qcompleter.h>
55 #include <qsharedpointer.h>
56 
57 class QStandardItemModel;
58 
59 namespace ito {
60 
61 /*
62 This module contains the code completion mode and the related classes.
63 */
64 
65 /*
66 Performs subsequence matching/sorting (see pyQode/pyQode#1)
67 */
68 class SubsequenceSortFilterProxyModel : public QSortFilterProxyModel
69 {
70 public:
71  SubsequenceSortFilterProxyModel(Qt::CaseSensitivity caseSensitivity, QObject *parent = NULL);
72 
73  void setPrefix(const QString &prefix);
74 
75 protected:
76  virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
77 
78  Qt::CaseSensitivity m_caseSensitivity;
79  QList<QRegExp> m_filterPatterns;
80  QList<QRegExp> m_filterPatternsCaseSensitive;
81  QList<QRegExp> m_sortPatterns;
82  QString m_prefix;
83 };
84 
85 /*
86 QCompleter specialised for subsequence matching
87 */
88 class SubsequenceCompleter : public QCompleter
89 {
90 public:
91  SubsequenceCompleter(QObject *parent = NULL);
92  void setModel(QAbstractItemModel *model);
93  void updateModel();
94  virtual QStringList splitPath(const QString &path) const;
95 
96 protected:
97  QString m_localCompletionPrefix;
98  SubsequenceSortFilterProxyModel *m_pFilterProxyModel;
99  QAbstractItemModel *m_pSourceModel;
100  bool m_forceNextUpdate;
101 };
102 
103 
104 /*
105 Provides code completions when typing or when pressing Ctrl+Space.
106 
107 This mode provides a code completion system which is extensible.
108 It takes care of running the completion request in a background process
109 using one or more completion provider and display the results in a
110 QCompleter.
111 
112 To add code completion for a specific language, you only need to
113 implement a new
114 :class:`pyqode.core.backend.workers.CodeCompletionWorker.Provider`
115 
116 The completion popup is shown when the user press **ctrl+space** or
117 automatically while the user is typing some code (this can be configured
118 using a series of properties).
119 */
120 class CodeCompletionMode : public QObject, public Mode
121 {
122  Q_OBJECT
123 public:
124  CodeCompletionMode(const QString &name, const QString &description = "", QObject *parent = NULL);
125  virtual ~CodeCompletionMode();
126 
127  enum FilterMode
128  {
129  FilterPrefix = 0, //Filter completions based on the prefix, FAST
130  FilterContains = 1, //Filter completions based on whether the prefix is contained in the
131  //suggestion. Only available with PyQt5, if set with PyQt4, FILTER_PREFIX
132  //will be used instead. FAST
133  FilterFuzzy = 2, //Fuzzy filtering, using the subsequence matcher. This is the most powerful filter mode but also the SLOWEST.
134  };
135 
136  FilterMode filterMode() const;
137  void setFilterMode(FilterMode mode);
138 
139  Qt::Key triggerKey() const;
140  void setTriggerKey(Qt::Key key);
141 
142  bool selectWithReturn() const;
143  void setSelectWithReturn(bool select);
144 
145  int triggerLength() const;
146  void setTriggerLength(int length);
147 
148  QStringList triggerSymbols() const;
149  void setTriggerSymbols(const QStringList &symbols);
150 
151  bool caseSensitive() const;
152  void setCaseSensitive(bool cs);
153 
154  QString completionPrefix() const;
155 
156  bool showTooltips() const;
157  void setShowTooltips(bool show);
158 
159  int tooltipsMaxLength() const;
160  void setTooltipsMaxLength(int length);
161 
162  virtual void onStateChanged(bool state);
163  virtual void onInstall(CodeEditor *editor);
164  virtual void onUninstall();
165 
166  void hidePopup();
167 
168 private slots:
169  void onJediCompletionResultAvailable(int line, int col, int requestId, QVector<ito::JediCompletion> completions);
170 
171  virtual void onKeyPressed(QKeyEvent *e);
172  virtual void onKeyReleased(QKeyEvent *e);
173  virtual void onFocusIn(QFocusEvent *e);
174 
175  void insertCompletion(const QString &completion);
176  void onSelectedCompletionChanged(const QString &completion);
177  void displayCompletionTooltip(const QString &completion) const;
178 
179 protected:
180  bool requestCompletion();
181 
182  void createCompleter();
183 
184 
185  void handleCompleterEvents(QKeyEvent *e);
186  bool isPopupVisible() const;
187  void resetSyncDataAndHidePopup();
188  bool isShortcut(QKeyEvent *e) const;
189  QRect getPopupRect() const;
190  void showPopup(int index = 0);
191  void showCompletions(const QVector<JediCompletion> &completions);
192  QStandardItemModel* updateModel(const QVector<JediCompletion> &completions);
193 
194  /*
195  \returns (stringlist os signatures, docstring)
196  */
197  QPair<QStringList, QString> parseTooltipDocstring(const QString &docstring) const;
198 
199  static bool isNavigationKey(QKeyEvent *e);
200 
201 private:
202  QObject *m_pPythonEngine;
203  int m_requestCount;
204 
205  /* maps the completion name to a a list of (string list of signatures and a docstring) */
206  QMap<QString, QList<QPair<QStringList, QString>>> m_tooltips;
207  bool m_showTooltips;
208  QCompleter *m_pCompleter;
209  QString m_completionPrefix;
210  bool m_caseSensitive;
211  int m_lastCursorColumn;
212  int m_lastCursorLine;
213  Qt::Key m_triggerKey;
215  int m_lastRequestId;
216  QString m_currentCompletion;
217  QStringList m_triggerSymbols;
218  int m_triggerLen;
219  FilterMode m_filterMode;
220  int m_tooltipsMaxLength;
221  bool m_selectWithReturn;
222 };
223 
224 } //end namespace ito
225 
226 #endif
Definition: codeCompletion.h:120
int m_requestId
auto-incremented number for the last enqueued completion request.
Definition: codeCompletion.h:214
Definition: codeEditor.h:110
Definition: apiFunctionsGraph.cpp:39
Definition: codeCompletion.h:68
Definition: codeCompletion.h:88
Definition: mode.h:69