mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
Implement basic tab autocomplete (#75)
This commit is contained in:
parent
fef62fda80
commit
2425ddbd2c
|
@ -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 \
|
||||||
|
|
|
@ -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);
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
113
src/widgets/resizingtextedit.cpp
Normal file
113
src/widgets/resizingtextedit.cpp
Normal 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;
|
||||||
|
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue