From 81a27a92524da8498a597b70dadfd663e72b14be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Br=C3=A6strup=20Sayoc?= Date: Sun, 6 Oct 2024 23:54:20 +0200 Subject: [PATCH] [Gui] Make autocompletion global Now auto complete is in all TextEdit objects. Fixes #12850 --- src/Gui/CallTips.h | 1 + src/Gui/PythonConsole.cpp | 45 +++++++++++---------------------------- src/Gui/PythonConsole.h | 2 ++ src/Gui/TextEdit.cpp | 42 ++++++++++++++++++++++++++++++++++++ src/Gui/TextEdit.h | 8 +++++++ 5 files changed, 65 insertions(+), 33 deletions(-) diff --git a/src/Gui/CallTips.h b/src/Gui/CallTips.h index 91253f21a0..a94a875847 100644 --- a/src/Gui/CallTips.h +++ b/src/Gui/CallTips.h @@ -31,6 +31,7 @@ class QPlainTextEdit; namespace Py { class Object; class List; +class String; } namespace Gui { diff --git a/src/Gui/PythonConsole.cpp b/src/Gui/PythonConsole.cpp index ed5a21eafd..f6b566c5a4 100644 --- a/src/Gui/PythonConsole.cpp +++ b/src/Gui/PythonConsole.cpp @@ -43,7 +43,6 @@ #include "PythonConsolePy.h" #include "PythonTracing.h" #include "Application.h" -#include "CallTips.h" #include "FileDialog.h" #include "MainWindow.h" #include "Tools.h" @@ -90,7 +89,6 @@ struct PythonConsoleP CopyType type; PyObject *_stdoutPy=nullptr, *_stderrPy=nullptr, *_stdinPy=nullptr, *_stdin=nullptr; InteractiveInterpreter* interpreter=nullptr; - CallTipsList* callTipsList=nullptr; ConsoleHistory history; QString output, error, info, historyFile; QStringList statements; @@ -439,17 +437,6 @@ PythonConsole::PythonConsole(QWidget *parent) setVisibleLineNumbers(false); setEnabledHighlightCurrentLine(false); - - // create the window for call tips - d->callTipsList = new CallTipsList(this); - d->callTipsList->setFrameStyle(QFrame::Box); - d->callTipsList->setFrameShadow(QFrame::Raised); - d->callTipsList->setLineWidth(2); - installEventFilter(d->callTipsList); - viewport()->installEventFilter(d->callTipsList); - d->callTipsList->setSelectionMode( QAbstractItemView::SingleSelection ); - d->callTipsList->hide(); - QFont serifFont(QLatin1String("Courier"), 10, QFont::Normal); setFont(serifFont); @@ -536,6 +523,18 @@ void PythonConsole::OnChange(Base::Subject &rCaller, const char* sR } } +int PythonConsole::getInputStringPosition() +{ + QString rawLine = textCursor().block().text(); + return textCursor().positionInBlock() - promptLength(rawLine); +} + +QString PythonConsole::getInputString() +{ + QString rawLine = textCursor().block().text(); + return stripPromptFrom(rawLine); +} + /** * Checks the input of the console to make the correct indentations. * After a command is prompted completely the Python interpreter is started. @@ -625,22 +624,6 @@ void PythonConsole::keyPressEvent(QKeyEvent * e) runSource( inputStrg ); //< commit input string } break; - case Qt::Key_Period: - { - // In Qt 4.8 there is a strange behaviour because when pressing ":" - // then key is also set to 'Period' instead of 'Colon'. So we have - // to make sure we only handle the period. - if (e->text() == QLatin1String(".")) { - // analyse context and show available call tips - int contextLength = cursor.position() - inputLineBegin.position(); - PythonTextEditor::keyPressEvent(e); - d->callTipsList->showTips( inputStrg.left( contextLength ) ); - } - else { - PythonTextEditor::keyPressEvent(e); - } - } break; - case Qt::Key_Home: { QTextCursor::MoveMode mode = (e->modifiers() & Qt::ShiftModifier)? QTextCursor::KeepAnchor @@ -690,10 +673,6 @@ void PythonConsole::keyPressEvent(QKeyEvent * e) PythonTextEditor::keyPressEvent(e); } break; } - // This can't be done in CallTipsList::eventFilter() because we must first perform - // the event and afterwards update the list widget - if (d->callTipsList->isVisible()) - { d->callTipsList->validateCursor(); } // disable history restart if input line changed restartHistory &= (inputLine != inputBlock.text()); diff --git a/src/Gui/PythonConsole.h b/src/Gui/PythonConsole.h index 633d22a297..05e188bfe9 100644 --- a/src/Gui/PythonConsole.h +++ b/src/Gui/PythonConsole.h @@ -115,6 +115,8 @@ public: void OnChange( Base::Subject &rCaller,const char* rcReason ) override; void printStatement( const QString& cmd ); QString readline( ); + int getInputStringPosition() override; + QString getInputString() override; public Q_SLOTS: void onSaveHistoryAs(); diff --git a/src/Gui/TextEdit.cpp b/src/Gui/TextEdit.cpp index 64c7d56982..5e19327e10 100644 --- a/src/Gui/TextEdit.cpp +++ b/src/Gui/TextEdit.cpp @@ -32,6 +32,7 @@ # include #endif +#include "CallTips.h" #include "TextEdit.h" #include "SyntaxHighlighter.h" #include "Tools.h" @@ -46,6 +47,16 @@ using namespace Gui; TextEdit::TextEdit(QWidget* parent) : QPlainTextEdit(parent), cursorPosition(0), listBox(nullptr) { + // create the window for call tips + callTipsList = new CallTipsList(this); + callTipsList->setFrameStyle(QFrame::Box); + callTipsList->setFrameShadow(QFrame::Raised); + callTipsList->setLineWidth(2); + installEventFilter(callTipsList); + viewport()->installEventFilter(callTipsList); + callTipsList->setSelectionMode( QAbstractItemView::SingleSelection ); + callTipsList->hide(); + //Note: Set the correct context to this shortcut as we may use several instances of this //class at a time auto shortcut = new QShortcut(this); @@ -77,7 +88,9 @@ TextEdit::~TextEdit() = default; */ void TextEdit::keyPressEvent(QKeyEvent* e) { + // We want input to be appended to document before doing calltips QPlainTextEdit::keyPressEvent(e); + // This can't be done in CompletionList::eventFilter() because we must first perform // the event and afterwards update the list widget if (listBox && listBox->isVisible()) { @@ -94,6 +107,35 @@ void TextEdit::keyPressEvent(QKeyEvent* e) listBox->keyboardSearch(cursor.selectedText()); cursor.clearSelection(); } + + + if (e->key() == Qt::Key_Period) + { + // QTextCursor cursor = this->textCursor(); + // In Qt 4.8 there is a strange behaviour because when pressing ":" + // then key is also set to 'Period' instead of 'Colon'. So we have + // to make sure we only handle the period. + if (e->text() == QLatin1String(".")) { + // analyse context and show available call tips + // TODO: idk why we need to remove the . from the input string (- 1). This shouldn't be needed + QString textToBeCompleted = getInputString().left(getInputStringPosition() - 1); + callTipsList->showTips( textToBeCompleted ); + } + } + + // This can't be done in CallTipsList::eventFilter() because we must first perform + // the event and afterwards update the list widget + if (callTipsList->isVisible()) { + callTipsList->validateCursor(); + } +} + +int TextEdit::getInputStringPosition() { + return textCursor().positionInBlock(); +} + +QString TextEdit::getInputString() { + return textCursor().block().text(); } void TextEdit::wheelEvent(QWheelEvent* e) diff --git a/src/Gui/TextEdit.h b/src/Gui/TextEdit.h index 87e0bce5cf..c24bf15b26 100644 --- a/src/Gui/TextEdit.h +++ b/src/Gui/TextEdit.h @@ -27,6 +27,8 @@ #include #include + +#include "CallTips.h" #include "Window.h" @@ -60,6 +62,11 @@ public: explicit TextEdit(QWidget *parent = nullptr); ~TextEdit() override; + //! Get the cursor position of the current line being edited + virtual int getInputStringPosition(); + //! Get the text of the current line being edited + virtual QString getInputString(); + private Q_SLOTS: void complete(); @@ -71,6 +78,7 @@ Q_SIGNALS: protected: void keyPressEvent(QKeyEvent *) override; void wheelEvent(QWheelEvent* e) override; + CallTipsList* callTipsList = nullptr; private: void createListBox();