mirror-chatterino2/src/widgets/helper/resizingtextedit.cpp

176 lines
4.5 KiB
C++
Raw Normal View History

2017-11-12 17:21:50 +01:00
#include "widgets/helper/resizingtextedit.hpp"
2018-02-05 15:11:50 +01:00
#include "common.hpp"
#include "singletons/helper/completionmodel.hpp"
2017-07-09 00:09:02 +02:00
ResizingTextEdit::ResizingTextEdit()
{
auto sizePolicy = this->sizePolicy();
sizePolicy.setHeightForWidth(true);
sizePolicy.setVerticalPolicy(QSizePolicy::Preferred);
this->setSizePolicy(sizePolicy);
this->setAcceptRichText(false);
2017-07-09 00:09:02 +02:00
QObject::connect(this, &QTextEdit::textChanged, this, &QWidget::updateGeometry);
this->setFocusPolicy(Qt::ClickFocus);
2017-07-09 00:09:02 +02:00
}
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(bool *hadSpace) const
2017-07-09 00:09:02 +02:00
{
auto currentText = this->toPlainText();
QTextCursor tc = this->textCursor();
auto textUpToCursor = currentText.left(tc.selectionStart());
auto words = textUpToCursor.splitRef(' ');
if (words.size() == 0) {
return QString();
}
bool first = true;
QString lastWord;
for (auto it = words.crbegin(); it != words.crend(); ++it) {
auto word = *it;
if (first && word.isEmpty()) {
first = false;
if (hadSpace != nullptr) {
*hadSpace = true;
}
continue;
}
lastWord = word.toString();
break;
}
if (lastWord.isEmpty()) {
return QString();
}
return lastWord;
2017-07-09 00:09:02 +02:00
}
void ResizingTextEdit::keyPressEvent(QKeyEvent *event)
{
event->ignore();
this->keyPressed(event);
2017-07-09 00:09:02 +02:00
if (event->key() == Qt::Key_Backtab) {
// Ignore for now. We want to use it for autocomplete later
return;
}
2018-02-05 15:11:50 +01:00
bool doComplete =
event->key() == Qt::Key_Tab && (event->modifiers() & Qt::ControlModifier) == Qt::NoModifier;
if (doComplete) {
// check if there is a completer
if (!this->completer) {
return;
}
2018-02-05 15:11:50 +01:00
2017-07-09 00:09:02 +02:00
QString currentCompletionPrefix = this->textUnderCursor();
2018-02-05 15:11:50 +01:00
// check if there is something to complete
2017-07-09 00:09:02 +02:00
if (!currentCompletionPrefix.size()) {
return;
}
auto *completionModel =
2017-12-31 22:58:35 +01:00
static_cast<chatterino::singletons::CompletionModel *>(this->completer->model());
if (!this->completionInProgress) {
// First type pressing tab after modifying a message, we refresh our completion model
completionModel->refresh();
this->completionInProgress = true;
2017-07-09 00:09:02 +02:00
this->completer->setCompletionPrefix(currentCompletionPrefix);
this->completer->complete();
return;
}
// scrolling through selections
if (!this->completer->setCurrentRow(this->completer->currentRow() + 1)) {
// wrap over and start again
this->completer->setCurrentRow(0);
}
2017-07-09 00:09:02 +02:00
this->completer->complete();
return;
}
2018-02-05 15:11:50 +01:00
2017-07-09 00:09:02 +02:00
// (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->completionInProgress = false;
2017-07-09 00:09:02 +02:00
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(completer,
static_cast<void (QCompleter::*)(const QString &)>(&QCompleter::highlighted),
this, &ResizingTextEdit::insertCompletion);
}
void ResizingTextEdit::insertCompletion(const QString &completion)
{
if (this->completer->widget() != this) {
return;
}
bool hadSpace = false;
auto prefix = this->textUnderCursor(&hadSpace);
int prefixSize = prefix.size();
if (hadSpace) {
++prefixSize;
}
2017-07-09 00:09:02 +02:00
QTextCursor tc = this->textCursor();
tc.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor, prefixSize);
2017-07-09 00:09:02 +02:00
tc.insertText(completion);
this->setTextCursor(tc);
}
QCompleter *ResizingTextEdit::getCompleter() const
{
return this->completer;
}