KTextEditor

katekeywordcompletion.cpp
1 /* SPDX-License-Identifier: LGPL-2.0-or-later
2 
3  Copyright (C) 2014 Sven Brauch <[email protected]>
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19 */
20 
21 #include "katekeywordcompletion.h"
22 
23 #include "katedocument.h"
24 #include "katehighlight.h"
25 #include "katetextline.h"
26 
27 #include <ktexteditor/view.h>
28 
29 #include <KLocalizedString>
30 #include <QString>
31 
32 KateKeywordCompletionModel::KateKeywordCompletionModel(QObject *parent)
33  : CodeCompletionModel(parent)
34 {
35  setHasGroups(false);
36 }
37 
38 void KateKeywordCompletionModel::completionInvoked(KTextEditor::View *view, const KTextEditor::Range &range, KTextEditor::CodeCompletionModel::InvocationType /*invocationType*/)
39 {
40  KTextEditor::DocumentPrivate *doc = static_cast<KTextEditor::DocumentPrivate *>(view->document());
41  if (!doc->highlight() || doc->highlight()->noHighlighting()) {
42  return;
43  }
44  m_items = doc->highlight()->keywordsForLocation(doc, range.end());
45  std::sort(m_items.begin(), m_items.end());
46 }
47 
49 {
50  if (index.internalId())
51  return createIndex(0, 0);
52  else
53  return QModelIndex();
54 }
55 
56 QModelIndex KateKeywordCompletionModel::index(int row, int column, const QModelIndex &parent) const
57 {
58  if (!parent.isValid()) {
59  if (row == 0)
60  return createIndex(row, column);
61  else
62  return QModelIndex();
63  } else if (parent.parent().isValid()) {
64  return QModelIndex();
65  }
66 
67  if (row < 0 || row >= m_items.count() || column < 0 || column >= ColumnCount) {
68  return QModelIndex();
69  }
70 
71  return createIndex(row, column, 1);
72 }
73 
74 int KateKeywordCompletionModel::rowCount(const QModelIndex &parent) const
75 {
76  if (!parent.isValid() && !m_items.isEmpty())
77  return 1; // One root node to define the custom group
78  else if (parent.parent().isValid())
79  return 0; // Completion-items have no children
80  else
81  return m_items.count();
82 }
83 
84 static bool isInWord(const KTextEditor::View *view, const KTextEditor::Cursor &position, QChar c)
85 {
86  KTextEditor::DocumentPrivate *document = static_cast<KTextEditor::DocumentPrivate *>(view->document());
87  KateHighlighting *highlight = document->highlight();
88  Kate::TextLine line = document->kateTextLine(position.line());
89  return highlight->isInWord(c, line->attribute(position.column() - 1));
90 }
91 
93 {
94  const QString &text = view->document()->text(KTextEditor::Range(position, KTextEditor::Cursor(position.line(), 0)));
95  int pos;
96  for (pos = text.size() - 1; pos >= 0; pos--) {
97  if (isInWord(view, position, text.at(pos))) {
98  // This needs to be aware of what characters are word-characters in the
99  // active language, so that languages which prefix commands with e.g. @
100  // or \ have properly working completion.
101  continue;
102  }
103  break;
104  }
105  return KTextEditor::Range(KTextEditor::Cursor(position.line(), pos + 1), position);
106 }
107 
109 {
110  if (view->cursorPosition() < range.start() || view->cursorPosition() > range.end())
111  return true; // Always abort when the completion-range has been left
112  // Do not abort completions when the text has been empty already before and a newline has been entered
113 
114  for (QChar c : currentCompletion) {
115  if (!isInWord(view, range.start(), c)) {
116  return true;
117  }
118  }
119  return false;
120 }
121 
122 bool KateKeywordCompletionModel::shouldStartCompletion(KTextEditor::View * /*view*/, const QString &insertedText, bool userInsertion, const KTextEditor::Cursor & /*position*/)
123 {
124  if (userInsertion && insertedText.size() > 3 && !insertedText.contains(QLatin1Char(' ')) && insertedText.at(insertedText.size() - 1).isLetter()) {
125  return true;
126  }
127  return false;
128 }
129 
131 {
132  return true;
133 }
134 
135 QVariant KateKeywordCompletionModel::data(const QModelIndex &index, int role) const
136 {
137  if (role == UnimportantItemRole)
138  return QVariant(true);
139  if (role == InheritanceDepth)
140  return 9000;
141 
142  if (!index.parent().isValid()) {
143  // group header
144  switch (role) {
145  case Qt::DisplayRole:
146  return i18n("Language keywords");
147  case GroupRole:
148  return Qt::DisplayRole;
149  }
150  }
151 
152  if (index.column() == KTextEditor::CodeCompletionModel::Name && role == Qt::DisplayRole)
153  return m_items.at(index.row());
154 
155  if (index.column() == KTextEditor::CodeCompletionModel::Icon && role == Qt::DecorationRole) {
156  static const QIcon icon(QIcon::fromTheme(QStringLiteral("code-variable")).pixmap(QSize(16, 16)));
157  return icon;
158  }
159 
160  return QVariant();
161 }
162 
164 {
165  return KTextEditor::CodeCompletionModelControllerInterface::HideListIfAutomaticInvocation;
166 }
167 
168 // kate: indent-width 4; replace-tabs on
KTextEditor::Range completionRange(KTextEditor::View *view, const KTextEditor::Cursor &position) override
This function returns the completion range that will be used for the current completion.
virtual Document * document() const =0
Get the view&#39;s document, that means the view is a view of the returned document.
virtual QString text() const =0
Get the document content.
int size() const const
bool shouldHideItemsWithEqualNames() const override
When multiple completion models are used at the same time, it may happen that multiple models add ite...
quintptr internalId() const const
The Cursor represents a position in a Document.
Definition: cursor.h:83
Icon representing the type of completion.
void completionInvoked(KTextEditor::View *view, const KTextEditor::Range &range, InvocationType invocationType) override
This function is responsible to generating / updating the list of current completions.
bool isValid() const const
bool shouldAbortCompletion(KTextEditor::View *view, const KTextEditor::Range &range, const QString &currentCompletion) override
This function decides if the completion should be aborted.
int row() const const
MatchReaction matchingItem(const QModelIndex &matched) override
Called whenever an item in the completion-list perfectly matches the current filter text...
virtual Cursor cursorPosition() const =0
Get the view&#39;s current cursor position.
constexpr int column() const Q_DECL_NOEXCEPT
Retrieve the column on which this cursor is situated.
Definition: cursor.h:215
QModelIndex parent() const const
constexpr Cursor start() const Q_DECL_NOEXCEPT
Get the start position of this range.
bool shouldStartCompletion(KTextEditor::View *view, const QString &insertedText, bool userInsertion, const KTextEditor::Cursor &position) override
This function decides if the automatic completion should be started when the user entered some text...
An object representing a section of text, from one Cursor to another.
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
QString i18n(const char *text, const TYPE &arg...)
constexpr Cursor end() const Q_DECL_NOEXCEPT
Get the end position of this range.
const QChar at(int position) const const
constexpr int line() const Q_DECL_NOEXCEPT
Retrieve the line on which this cursor is situated.
Definition: cursor.h:197
int column() const const
QIcon fromTheme(const QString &name)
A text widget with KXMLGUIClient that represents a Document.
Definition: view.h:153
QObject * parent() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Sun May 24 2020 23:10:48 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.