summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorBenjamin Saunders <ben.e.saunders@gmail.com>2017-11-05 13:01:21 -0800
committermujx <mujx@users.noreply.github.com>2017-11-05 23:01:21 +0200
commit4ccb5ed81f1787a3cca12e5ca705fad4e3fa8ca5 (patch)
tree397e54883914fc354c06b27640282e7e941c7bd1 /src
parentFix .travis.yml format (diff)
downloadnheko-4ccb5ed81f1787a3cca12e5ca705fad4e3fa8ca5.tar.xz
Add input history, enable multi-line input, refactor commands (#119)
This also fixes the transmission of mis-typed commands as messages,
fixes inability to send messages that start with a command, and does
some initial work towards automatically resizing the input field to fit
the input message.


Diffstat (limited to 'src')
-rw-r--r--src/TextInputWidget.cc164
1 files changed, 114 insertions, 50 deletions
diff --git a/src/TextInputWidget.cc b/src/TextInputWidget.cc

index cad54d96..e7c48b5f 100644 --- a/src/TextInputWidget.cc +++ b/src/TextInputWidget.cc
@@ -15,6 +15,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <QAbstractTextDocumentLayout> #include <QDebug> #include <QFile> #include <QFileDialog> @@ -25,9 +26,21 @@ #include "Config.h" #include "TextInputWidget.h" +static constexpr size_t INPUT_HISTORY_SIZE = 127; + FilteredTextEdit::FilteredTextEdit(QWidget *parent) - : QTextEdit(parent) + : QTextEdit{ parent } + , history_index_{ 0 } { + connect(document()->documentLayout(), + &QAbstractTextDocumentLayout::documentSizeChanged, + this, + &FilteredTextEdit::updateGeometry); + QSizePolicy policy(QSizePolicy::Expanding, QSizePolicy::Fixed); + policy.setHeightForWidth(true); + setSizePolicy(policy); + working_history_.push_back(""); + connect(this, &QTextEdit::textChanged, this, &FilteredTextEdit::textChanged); setAcceptRichText(false); typingTimer_ = new QTimer(this); @@ -49,12 +62,40 @@ FilteredTextEdit::keyPressEvent(QKeyEvent *event) typingTimer_->start(); } - if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) { - stopTyping(); - - emit enterPressed(); - } else { + switch (event->key()) { + case Qt::Key_Return: + case Qt::Key_Enter: + if (!(event->modifiers() & Qt::ShiftModifier)) { + stopTyping(); + submit(); + } else { + QTextEdit::keyPressEvent(event); + } + break; + case Qt::Key_Up: { + auto initial_cursor = textCursor(); + QTextEdit::keyPressEvent(event); + if (textCursor() == initial_cursor && + history_index_ + 1 < working_history_.size()) { + ++history_index_; + setPlainText(working_history_[history_index_]); + moveCursor(QTextCursor::End); + } + break; + } + case Qt::Key_Down: { + auto initial_cursor = textCursor(); QTextEdit::keyPressEvent(event); + if (textCursor() == initial_cursor && history_index_ > 0) { + --history_index_; + setPlainText(working_history_[history_index_]); + moveCursor(QTextCursor::End); + } + break; + } + default: + QTextEdit::keyPressEvent(event); + break; } } @@ -65,6 +106,65 @@ FilteredTextEdit::stopTyping() emit stoppedTyping(); } +QSize +FilteredTextEdit::sizeHint() const +{ + ensurePolished(); + auto margins = viewportMargins(); + margins += document()->documentMargin(); + QSize size = document()->size().toSize(); + size.rwidth() += margins.left() + margins.right(); + size.rheight() += margins.top() + margins.bottom(); + return size; +} + +QSize +FilteredTextEdit::minimumSizeHint() const +{ + ensurePolished(); + auto margins = viewportMargins(); + margins += document()->documentMargin(); + margins += contentsMargins(); + QSize size(fontMetrics().averageCharWidth() * 10, + fontMetrics().lineSpacing() + margins.top() + margins.bottom()); + return size; +} + +void +FilteredTextEdit::submit() +{ + if (true_history_.size() == INPUT_HISTORY_SIZE) + true_history_.pop_back(); + true_history_.push_front(toPlainText()); + working_history_ = true_history_; + working_history_.push_front(""); + history_index_ = 0; + + QString text = toPlainText(); + if (text.startsWith('/')) { + int command_end = text.indexOf(' '); + if (command_end == -1) + command_end = text.size(); + auto name = text.mid(1, command_end - 1); + auto args = text.mid(command_end + 1); + if (name.isEmpty() || name == "/") { + message(args); + } else { + command(name, args); + } + } else { + message(std::move(text)); + } + + clear(); +} + +void +FilteredTextEdit::textChanged() +{ + working_history_[history_index_] = toPlainText(); +} + TextInputWidget::TextInputWidget(QWidget *parent) : QFrame(parent) { @@ -122,9 +222,10 @@ TextInputWidget::TextInputWidget(QWidget *parent) setLayout(topLayout_); - connect(sendMessageBtn_, SIGNAL(clicked()), this, SLOT(onSendButtonClicked())); + connect(sendMessageBtn_, &FlatButton::clicked, input_, &FilteredTextEdit::submit); connect(sendFileBtn_, SIGNAL(clicked()), this, SLOT(openFileSelection())); - connect(input_, SIGNAL(enterPressed()), sendMessageBtn_, SIGNAL(clicked())); + connect(input_, &FilteredTextEdit::message, this, &TextInputWidget::sendTextMessage); + connect(input_, &FilteredTextEdit::command, this, &TextInputWidget::command); connect(emojiBtn_, SIGNAL(emojiSelected(const QString &)), this, @@ -160,50 +261,13 @@ TextInputWidget::addSelectedEmoji(const QString &emoji) } void -TextInputWidget::onSendButtonClicked() +TextInputWidget::command(QString command, QString args) { - auto msgText = input_->document()->toPlainText().trimmed(); - - if (msgText.isEmpty()) - return; - - if (msgText.startsWith(EMOTE_COMMAND)) { - auto text = parseEmoteCommand(msgText); - - if (!text.isEmpty()) - emit sendEmoteMessage(text); - } else if (msgText.startsWith(JOIN_COMMAND)) { - auto room = parseJoinCommand(msgText); - - if (!room.isEmpty()) - emit sendJoinRoomRequest(room); - } else { - emit sendTextMessage(msgText); + if (command == "me") { + sendEmoteMessage(args); + } else if (command == "join") { + sendJoinRoomRequest(args); } - - input_->clear(); -} - -QString -TextInputWidget::parseJoinCommand(const QString &cmd) -{ - auto room = cmd.right(cmd.size() - JOIN_COMMAND.size()).trimmed(); - - if (!room.isEmpty()) - return room; - - return QString(""); -} - -QString -TextInputWidget::parseEmoteCommand(const QString &cmd) -{ - auto text = cmd.right(cmd.size() - EMOTE_COMMAND.size()).trimmed(); - - if (!text.isEmpty()) - return text; - - return QString(""); } void