Implement basic tab autocomplete (#75)

This commit is contained in:
hemirt 2017-07-09 00:09:02 +02:00 committed by pajlada
parent fef62fda80
commit 2425ddbd2c
5 changed files with 138 additions and 41 deletions

View file

@ -94,7 +94,8 @@ SOURCES += \
src/ircaccount.cpp \ src/ircaccount.cpp \
src/widgets/accountpopup.cpp \ src/widgets/accountpopup.cpp \
src/messagefactory.cpp \ src/messagefactory.cpp \
src/widgets/basewidget.cpp src/widgets/basewidget.cpp \
src/widgets/resizingtextedit.cpp
HEADERS += \ HEADERS += \
src/asyncexec.hpp \ src/asyncexec.hpp \

View file

@ -43,17 +43,18 @@ ChatWidgetInput::ChatWidgetInput(ChatWidget *_chatWidget)
connect(&textInput, &ResizingTextEdit::textChanged, this, &ChatWidgetInput::editTextChanged); connect(&textInput, &ResizingTextEdit::textChanged, this, &ChatWidgetInput::editTextChanged);
this->refreshTheme(); this->refreshTheme();
this->setMessageLengthVisisble(SettingsManager::getInstance().showMessageLength.get()); this->setMessageLengthVisible(SettingsManager::getInstance().showMessageLength.get());
QStringList list; QStringList list;
list.append("asd"); /*list.append("asd");
list.append("asdf"); list.append("asdf");
list.append("asdg"); list.append("asdg");
list.append("asdh"); list.append("asdh");
*/
list << "Kappa" << "asd" << "asdf" << "asdg";
QCompleter *completer = new QCompleter(list, &this->textInput); QCompleter *completer = new QCompleter(list, &this->textInput);
completer->setWidget(&textInput); this->textInput.setCompleter(completer);
this->textInput.keyPressed.connect([this /*, completer*/](QKeyEvent *event) { this->textInput.keyPressed.connect([this /*, completer*/](QKeyEvent *event) {
if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
@ -76,7 +77,7 @@ ChatWidgetInput::ChatWidgetInput(ChatWidget *_chatWidget)
/* XXX(pajlada): FIX THIS /* XXX(pajlada): FIX THIS
QObject::connect(&Settings::getInstance().showMessageLength, QObject::connect(&Settings::getInstance().showMessageLength,
&BoolSetting::valueChanged, this, &BoolSetting::valueChanged, this,
&ChatWidgetInput::setMessageLengthVisisble); &ChatWidgetInput::setMessageLengthVisible);
*/ */
} }
@ -86,7 +87,7 @@ ChatWidgetInput::~ChatWidgetInput()
QObject::disconnect( QObject::disconnect(
&Settings::getInstance().getShowMessageLength(), &Settings::getInstance().getShowMessageLength(),
&BoolSetting::valueChanged, this, &BoolSetting::valueChanged, this,
&ChatWidgetInput::setMessageLengthVisisble); &ChatWidgetInput::setMessageLengthVisible);
*/ */
} }

View file

@ -42,7 +42,7 @@ private:
virtual void refreshTheme() override; virtual void refreshTheme() override;
private slots: private slots:
void setMessageLengthVisisble(bool value) void setMessageLengthVisible(bool value)
{ {
textLengthLabel.setHidden(!value); textLengthLabel.setHidden(!value);
} }

View file

@ -0,0 +1,113 @@
#include "widgets/resizingtextedit.hpp"
ResizingTextEdit::ResizingTextEdit()
: keyPressed()
{
auto sizePolicy = this->sizePolicy();
sizePolicy.setHeightForWidth(true);
sizePolicy.setVerticalPolicy(QSizePolicy::Preferred);
this->setSizePolicy(sizePolicy);
QObject::connect(this, &QTextEdit::textChanged, this, &QWidget::updateGeometry);
}
QSize ResizingTextEdit::sizeHint() const
{
return QSize(this->width(), this->heightForWidth(this->width()));
}
bool ResizingTextEdit::hasHeightForWidth() const
{
return true;
}
int ResizingTextEdit::heightForWidth(int) const
{
auto margins = this->contentsMargins();
return margins.top() + document()->size().height() + margins.bottom() + 5;
}
QString ResizingTextEdit::textUnderCursor() const
{
QTextCursor tc = textCursor();
tc.select(QTextCursor::WordUnderCursor);
return tc.selectedText();
}
void ResizingTextEdit::keyPressEvent(QKeyEvent *event)
{
event->ignore();
keyPressed(event);
if (event->key() == Qt::Key_Tab) {
QString currentCompletionPrefix = this->textUnderCursor();
if (!currentCompletionPrefix.size()) {
return;
}
if (!this->nextCompletion) {
// first selection
this->completer->setCompletionPrefix(currentCompletionPrefix);
this->nextCompletion = true;
this->completer->complete();
return;
}
// scrolling through selections
if (!this->completer->setCurrentRow(this->completer->currentRow() + 1)) {
// wrap over and start again
this->completer->setCurrentRow(0);
}
this->completer->complete();
return;
}
// (hemirt)
// this resets the selection in the completion list, it should probably only trigger on actual
// chat input (space, character) and not on every key input (pressing alt for example)
this->nextCompletion = false;
if (!event->isAccepted()) {
QTextEdit::keyPressEvent(event);
}
}
void ResizingTextEdit::setCompleter(QCompleter *c)
{
if (this->completer) {
QObject::disconnect(this->completer, 0, this, 0);
}
this->completer = c;
if (!this->completer) {
return;
}
this->completer->setWidget(this);
this->completer->setCompletionMode(QCompleter::InlineCompletion);
this->completer->setCaseSensitivity(Qt::CaseInsensitive);
/*QObject::connect(this->completer, SIGNAL(highlighted(QString)), this,
SLOT(insertCompletion(QString)));
*/
QObject::connect(completer,
static_cast<void (QCompleter::*)(const QString &)>(&QCompleter::highlighted),
this, &ResizingTextEdit::insertCompletion);
}
void ResizingTextEdit::insertCompletion(const QString &completion)
{
if (this->completer->widget() != this) {
return;
}
QTextCursor tc = this->textCursor();
tc.select(QTextCursor::SelectionType::WordUnderCursor);
tc.insertText(completion);
this->setTextCursor(tc);
}
QCompleter *ResizingTextEdit::getCompleter() const
{
return this->completer;
}

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <QCompleter>
#include <QKeyEvent> #include <QKeyEvent>
#include <QTextEdit> #include <QTextEdit>
#include <boost/signals2.hpp> #include <boost/signals2.hpp>
@ -7,45 +8,26 @@
class ResizingTextEdit : public QTextEdit class ResizingTextEdit : public QTextEdit
{ {
public: public:
ResizingTextEdit() ResizingTextEdit();
: keyPressed()
{
auto sizePolicy = this->sizePolicy();
sizePolicy.setHeightForWidth(true);
sizePolicy.setVerticalPolicy(QSizePolicy::Preferred);
this->setSizePolicy(sizePolicy);
QObject::connect(this, &QTextEdit::textChanged, this, &QWidget::updateGeometry); QSize sizeHint() const override;
}
QSize sizeHint() const override bool hasHeightForWidth() const override;
{
return QSize(this->width(), this->heightForWidth(this->width()));
}
bool hasHeightForWidth() const override
{
return true;
}
boost::signals2::signal<void(QKeyEvent *)> keyPressed; boost::signals2::signal<void(QKeyEvent *)> keyPressed;
void setCompleter(QCompleter *c);
QCompleter *getCompleter() const;
protected: protected:
int heightForWidth(int) const override int heightForWidth(int) const override;
{ void keyPressEvent(QKeyEvent *event) override;
auto margins = this->contentsMargins();
return margins.top() + document()->size().height() + margins.bottom() + 5; private:
} QCompleter *completer = nullptr;
QString textUnderCursor() const;
bool nextCompletion = false;
void keyPressEvent(QKeyEvent *event) override private slots:
{ void insertCompletion(const QString &completion);
event->ignore();
keyPressed(event);
if (!event->isAccepted()) {
QTextEdit::keyPressEvent(event);
}
}
}; };