[rkward/work/unified_hinting2] rkward/windows: Fix some bugs. Integrated calltip hinting now works.
Thomas Friedrichsmeier
null at kde.org
Fri Feb 15 19:24:48 GMT 2019
Git commit 3de64bd7d1a7c0a1c3b9edf61f63f1817fa1098a by Thomas Friedrichsmeier.
Committed on 15/02/2019 at 19:10.
Pushed by tfry into branch 'work/unified_hinting2'.
Fix some bugs. Integrated calltip hinting now works.
M +88 -42 rkward/windows/rkcommandeditorwindow.cpp
M +6 -1 rkward/windows/rkcommandeditorwindow.h
https://commits.kde.org/rkward/3de64bd7d1a7c0a1c3b9edf61f63f1817fa1098a
diff --git a/rkward/windows/rkcommandeditorwindow.cpp b/rkward/windows/rkcommandeditorwindow.cpp
index 1e35cf90..a48b7b53 100644
--- a/rkward/windows/rkcommandeditorwindow.cpp
+++ b/rkward/windows/rkcommandeditorwindow.cpp
@@ -1186,7 +1186,7 @@ bool RKFunctionArgHinter::eventFilter (QObject *, QEvent *e) {
RKCompletionManager::RKCompletionManager (KTextEditor::View* view) : QObject (view) {
RK_TRACE (COMMANDEDITOR);
- RKCompletionManager::view = view;
+ _view = view;
active = false;
update_call = true;
cached_position = KTextEditor::Cursor (-1, -1);
@@ -1236,7 +1236,7 @@ void RKCompletionManager::tryCompletionProxy () {
QString RKCompletionManager::currentCompletionWord () const {
RK_TRACE (COMMANDEDITOR);
- if (symbol_range.isValid ()) return view->document ()->text (symbol_range);
+ if (symbol_range.isValid ()) return _view->document ()->text (symbol_range);
return QString ();
}
@@ -1249,8 +1249,8 @@ void RKCompletionManager::tryCompletion () {
return;
}
- KTextEditor::Document *doc = view->document ();
- KTextEditor::Cursor c = view->cursorPosition();
+ KTextEditor::Document *doc = _view->document ();
+ KTextEditor::Cursor c = _view->cursorPosition();
cached_position = c;
uint para=c.line(); int cursor_pos=c.column();
@@ -1258,6 +1258,7 @@ void RKCompletionManager::tryCompletion () {
int start;
int end;
RKCommonFunctions::getCurrentSymbolOffset (current_line, cursor_pos, false, &start, &end);
+ symbol_range = KTextEditor::Range (para, start, para, end);
if (end > cursor_pos) {
symbol_range = KTextEditor::Range (-1, -1, -1, -1); // Only hint when at the end of a word/symbol: https://mail.kde.org/pipermail/rkward-devel/2015-April/004122.html
} else if (current_line.lastIndexOf ("#", cursor_pos) >= 0) symbol_range = KTextEditor::Range (); // do not hint while in comments
@@ -1270,6 +1271,9 @@ void RKCompletionManager::tryCompletion () {
completion_model->updateCompletionList (filename_completion ? QString () : word);
file_completion_model->updateCompletionList (filename_completion ? word.mid (1) : QString ());
+ } else {
+ completion_model->updateCompletionList (QString ());
+ file_completion_model->updateCompletionList (QString ());
}
updateCallHint ();
@@ -1285,7 +1289,7 @@ void RKCompletionManager::updateCallHint () {
int line = cached_position.line () + 1;
QString full_context;
int potential_symbol_end = -2;
- KTextEditor::Document *doc = view->document ();
+ KTextEditor::Document *doc = _view->document ();
while (potential_symbol_end < -1 && line >= 0) {
--line;
QString context_line = doc->line (line);
@@ -1326,30 +1330,32 @@ void RKCompletionManager::updateCallHint () {
callhint_model->setFunction (object);
}
-bool startModel (KTextEditor::CodeCompletionInterface* iface, KTextEditor::CodeCompletionModel *model, const KTextEditor::Range &range) {
- if (model->rowCount () > 0) {
- iface->startCompletion (range, model);
- return true;
+void startModel (KTextEditor::CodeCompletionInterface* iface, KTextEditor::CodeCompletionModel *model, bool start, const KTextEditor::Range &range, QList<KTextEditor::CodeCompletionModel*> *active_models) {
+ if (start && model->rowCount () > 0) {
+ if (!active_models->contains (model)) {
+ iface->startCompletion (range, model);
+ active_models->append (model);
+ }
+ } else {
+ active_models->removeAll (model);
}
- return false;
}
void RKCompletionManager::updateVisibility () {
RK_TRACE (COMMANDEDITOR);
- bool any_hint = false;
-
- QString word = currentCompletionWord ();
- if (word.length () >= RKSettingsModuleCommandEditor::completionMinChars ()) {
- // TODO: To avoid flicker, we should only start the models that still need starting, but how to figure out which ones are those?
- any_hint |= startModel (cc_iface, completion_model, symbol_range);
- any_hint |= startModel (cc_iface, file_completion_model, symbol_range);
- if (kate_keyword_completion_model) any_hint |= startModel (cc_iface, kate_keyword_completion_model, symbol_range);
+ if (!cc_iface->isCompletionActive ()) {
+ active_models.clear ();
}
+
+ bool min_len = (currentCompletionWord ().length () >= RKSettingsModuleCommandEditor::completionMinChars ());
+ startModel (cc_iface, completion_model, min_len, symbol_range, &active_models);
+ startModel (cc_iface, file_completion_model, min_len, symbol_range, &active_models);
+ if (kate_keyword_completion_model) startModel (cc_iface, kate_keyword_completion_model, min_len, symbol_range, &active_models);
// NOTE: Freaky bug in KF 5.44.0: Call hint will not show for the first time, if logically above the primary screen. TODO: provide patch for kateargumenthinttree.cpp:166pp
- any_hint |= startModel (cc_iface, callhint_model, currentCallRange ());
+ startModel (cc_iface, callhint_model, true, currentCallRange (), &active_models);
- if (any_hint) {
+ if (!active_models.isEmpty ()) {
active = true;
} else {
cc_iface->abortCompletion ();
@@ -1359,7 +1365,7 @@ void RKCompletionManager::updateVisibility () {
if (!active) update_call = true;
}
-void RKCompletionManager::textInserted(KTextEditor::Document*, const KTextEditor::Cursor& position, const QString& text) {
+void RKCompletionManager::textInserted (KTextEditor::Document*, const KTextEditor::Cursor& position, const QString& text) {
if (active) {
if (position < call_opening) update_call = true;
else if (text.contains (QChar ('(')) || text.contains (QChar (')'))) update_call = true;
@@ -1367,7 +1373,7 @@ void RKCompletionManager::textInserted(KTextEditor::Document*, const KTextEditor
tryCompletionProxy();
}
-void RKCompletionManager::textRemoved(KTextEditor::Document*, const KTextEditor::Range& range, const QString& text) {
+void RKCompletionManager::textRemoved (KTextEditor::Document*, const KTextEditor::Range& range, const QString& text) {
if (active) {
if (range.start () < call_opening) update_call = true;
else if (text.contains (QChar ('(')) || text.contains (QChar (')'))) update_call = true;
@@ -1375,23 +1381,29 @@ void RKCompletionManager::textRemoved(KTextEditor::Document*, const KTextEditor:
tryCompletionProxy();
}
-void RKCompletionManager::lineWrapped(KTextEditor::Document* , const KTextEditor::Cursor& ) {
+void RKCompletionManager::lineWrapped (KTextEditor::Document* , const KTextEditor::Cursor& ) {
// should already have been handled by textInserted()
- tryCompletionProxy();
+ tryCompletionProxy ();
}
-void RKCompletionManager::lineUnwrapped(KTextEditor::Document* , int ) {
+void RKCompletionManager::lineUnwrapped (KTextEditor::Document* , int ) {
// should already have been handled by textRemoved()
- tryCompletionProxy();
+ tryCompletionProxy ();
}
-void RKCompletionManager::cursorPositionChanged(KTextEditor::View* view, const KTextEditor::Cursor& newPosition) {
- // TODO!!
- tryCompletionProxy();
+void RKCompletionManager::cursorPositionChanged (KTextEditor::View* view, const KTextEditor::Cursor& newPosition) {
+ if (active) {
+ if (newPosition < call_opening) update_call = true;
+ else {
+ QString text = view->document ()->text (KTextEditor::Range (newPosition, cached_position));
+ if (text.contains (QChar ('(')) || text.contains (QChar (')'))) update_call = true;
+ }
+ }
+ tryCompletionProxy ();
}
KTextEditor::Range RKCompletionManager::currentCallRange () const {
- return KTextEditor::Range (call_opening, view->cursorPosition ());
+ return KTextEditor::Range (call_opening, _view->cursorPosition ());
}
@@ -1510,20 +1522,50 @@ QVariant RKCodeCompletionModel::data (const QModelIndex& index, int role) const
//////////////////////// RKCallHintModel //////////////////////////
RKCallHintModel::RKCallHintModel (RKCompletionManager* manager) : RKCompletionModelBase (manager) {
RK_TRACE (COMMANDEDITOR);
+ function = 0;
}
-void RKCallHintModel::setFunction(RObject* function) {
+#include <QDesktopWidget>
+// TODO: There could be more than one function by a certain name, and we could support this!
+void RKCallHintModel::setFunction(RObject* _function) {
RK_TRACE (COMMANDEDITOR);
+
+ if (function == _function) return;
+ function = _function;
+
beginResetModel ();
if (function && function->isType (RObject::Function)) {
- // initialize and show popup
+ // initialize hint
+ RFunctionObject *fo = static_cast<RFunctionObject*> (function);
+ QStringList args = fo->argumentNames ();
+ QStringList defs = fo->argumentDefaults ();
+
name = function->getFullName ();
- formals = QStringLiteral ("(") + static_cast<RFunctionObject*>(function)->printArgs () + ')';
- n_completions = 1; // TODO: There could be more than one function by the name, and we could support this!
+
+ formals = '(';
+ formatting.clear ();
+ KTextEditor::Attribute format;
+// format.setFontBold (); // NOTE: Not good. makes size mis-calculation worse.
+ format.setForeground (QBrush (Qt::green)); // But turns out purple?!
+
+ // NOTE: Unfortunately, adding new-lines within (long) formals does not work. If this issue turns out to be relevant, we'll have to resort to breaking the formals into
+ // several (dummy) items.
+ int pos = 1;
+ for (int i = 0; i < args.size (); ++i) {
+ QString pair = args[i];
+ if (!defs.value(i).isEmpty ()) pair.append ('=' + defs[i]);
+ formatting.append ({ pos + args[i].length (), pair.length ()-args[i].length (), format });
+
+ if (i < (args.size () - 1)) pair.append (", ");
+ formals.append (pair);
+
+ pos = pos + pair.length ();
+ }
+ formals.append (')');
+ n_completions = 1;
} else {
n_completions = 0;
}
-// RK_DEBUG(COMMANDEDITOR, DL_ERROR, "%d, %p", n_completions, function);
endResetModel ();
}
@@ -1535,16 +1577,20 @@ QVariant RKCallHintModel::data (const QModelIndex& index, int role) const {
}
int col = index.column ();
- if ((role == Qt::DisplayRole) || (role == KTextEditor::CodeCompletionModel::CompletionRole)) {
+ if (role == Qt::DisplayRole) {
if (col == KTextEditor::CodeCompletionModel::Prefix) return (name);
if (col == KTextEditor::CodeCompletionModel::Arguments) return (formals);
- }
-
- if (role == KTextEditor::CodeCompletionModel::ArgumentHintDepth) {
+ if (col == KTextEditor::CodeCompletionModel::Postfix) return (" "); // Size is of a bit for KF5 5.44.0. Provide some padding to work around cut-off parts.
+ } else if (role == KTextEditor::CodeCompletionModel::ArgumentHintDepth) {
return 1;
- }
- if (role == KTextEditor::CodeCompletionModel::MatchQuality) {
- return 10;
+ } else if (role == KTextEditor::CodeCompletionModel::CompletionRole) {
+ return KTextEditor::CodeCompletionModel::Function;
+ } else if (role == KTextEditor::CodeCompletionModel::HighlightingMethod) {
+ if (col == KTextEditor::CodeCompletionModel::Arguments) return KTextEditor::CodeCompletionModel::CustomHighlighting;
+ } else if (role == KTextEditor::CodeCompletionModel::CustomHighlight) {
+ if (col == KTextEditor::CodeCompletionModel::Arguments) return formatting;
+ } else if (role == KTextEditor::CodeCompletionModel::MatchQuality) {
+ return (10);
}
return QVariant ();
diff --git a/rkward/windows/rkcommandeditorwindow.h b/rkward/windows/rkcommandeditorwindow.h
index 6c48709c..c7c41c0d 100644
--- a/rkward/windows/rkcommandeditorwindow.h
+++ b/rkward/windows/rkcommandeditorwindow.h
@@ -116,6 +116,7 @@ public:
QString currentCompletionWord () const;
KTextEditor::Range currentSymbolRange () const { return symbol_range; };
KTextEditor::Range currentCallRange () const;
+ KTextEditor::View* view () const { return (_view); };
private slots:
void lineWrapped (KTextEditor::Document *document, const KTextEditor::Cursor &position);
void lineUnwrapped (KTextEditor::Document *document, int line);
@@ -136,7 +137,7 @@ private:
KTextEditor::CodeCompletionModel* kate_keyword_completion_model;
QTimer *completion_timer;
- KTextEditor::View *view;
+ KTextEditor::View *_view;
KTextEditor::Cursor cached_position;
KTextEditor::Range symbol_range;
@@ -144,6 +145,8 @@ private:
bool update_call;
bool active;
+
+ QList<KTextEditor::CodeCompletionModel*> active_models;
};
/** Base class for the completion models employed in script editor. Essentially it takes care of the bureaucratic overhead involved in providing a group header */
@@ -199,8 +202,10 @@ public:
QVariant data (const QModelIndex& index, int role=Qt::DisplayRole) const override;
KTextEditor::Range completionRange (KTextEditor::View *view, const KTextEditor::Cursor &position) override;
private:
+ RObject *function;
QString name;
QString formals;
+ QVariantList formatting;
};
#include <QThread>
More information about the rkward-tracker
mailing list