From 7a74b863402e5f67ce7fd0a99ab3ad64b7296344 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sat, 31 Oct 2020 23:24:07 +0100 Subject: [PATCH] Pasteable textinput --- CMakeLists.txt | 2 ++ resources/qml/MessageInput.qml | 24 +++++++++++++++++- resources/qml/TimelineView.qml | 4 +-- src/timeline/InputBar.cpp | 46 ++++++++++++++++++++++++++++++++++ src/timeline/InputBar.h | 25 ++++++++++++++++++ src/timeline/TimelineModel.cpp | 1 + src/timeline/TimelineModel.h | 5 ++++ 7 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 src/timeline/InputBar.cpp create mode 100644 src/timeline/InputBar.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b5bffd7..d8e048fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -252,6 +252,7 @@ set(SRC_FILES # Timeline src/timeline/EventStore.cpp + src/timeline/InputBar.cpp src/timeline/Reaction.cpp src/timeline/TimelineViewManager.cpp src/timeline/TimelineModel.cpp @@ -463,6 +464,7 @@ qt5_wrap_cpp(MOC_HEADERS # Timeline src/timeline/EventStore.h + src/timeline/InputBar.h src/timeline/Reaction.h src/timeline/TimelineViewManager.h src/timeline/TimelineModel.h diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index 71da9cae..3b424bb3 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -3,6 +3,8 @@ import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 import QtQuick.Window 2.2 +import im.nheko 1.0 + Rectangle { color: colors.window Layout.fillWidth: true @@ -44,16 +46,36 @@ Rectangle { Layout.fillWidth: true TextArea { + id: textArea + placeholderText: qsTr("Write a message...") placeholderTextColor: colors.buttonText color: colors.text wrapMode: TextEdit.Wrap + onTextChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) + onCursorPositionChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) + onSelectionStartChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) + onSelectionEndChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) + + Keys.onPressed: { + if (event.matches(StandardKey.Paste)) { + TimelineManager.timeline.input.paste(false) || textArea.paste() + event.accepted = true + } + else if (event.matches(StandardKey.InsertParagraphSeparator)) { + TimelineManager.timeline.input.send() + textArea.clear() + event.accepted = true + } + } + MouseArea { // workaround for wrong cursor shape on some platforms anchors.fill: parent - acceptedButtons: Qt.NoButton + acceptedButtons: Qt.MiddleButton cursorShape: Qt.IBeamCursor + onClicked: TimelineManager.timeline.input.paste(true) || textArea.paste() } background: Rectangle { diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index 95143b18..d85167af 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -234,8 +234,8 @@ Page { ReplyPopup { } - //MessageInput { - //} + MessageInput { + } } diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp new file mode 100644 index 00000000..d128631d --- /dev/null +++ b/src/timeline/InputBar.cpp @@ -0,0 +1,46 @@ +#include "InputBar.h" + +#include +#include +#include + +#include "Logging.h" + +bool +InputBar::paste(bool fromMouse) +{ + const QMimeData *md = nullptr; + + if (fromMouse) { + if (QGuiApplication::clipboard()->supportsSelection()) { + md = QGuiApplication::clipboard()->mimeData(QClipboard::Selection); + } + } else { + md = QGuiApplication::clipboard()->mimeData(QClipboard::Clipboard); + } + + if (!md) + return false; + + if (md->hasImage()) { + return true; + } else { + nhlog::ui()->debug("formats: {}", md->formats().join(", ").toStdString()); + return false; + } +} + +void +InputBar::updateState(int selectionStart_, int selectionEnd_, int cursorPosition_, QString text_) +{ + selectionStart = selectionStart_; + selectionEnd = selectionEnd_; + cursorPosition = cursorPosition_; + text = text_; +} + +void +InputBar::send() +{ + nhlog::ui()->debug("Send: {}", text.toStdString()); +} diff --git a/src/timeline/InputBar.h b/src/timeline/InputBar.h new file mode 100644 index 00000000..78b06960 --- /dev/null +++ b/src/timeline/InputBar.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +class TimelineModel; + +class InputBar : public QObject { + Q_OBJECT + +public: + InputBar(TimelineModel *parent) + : QObject() + , room(parent) + {} + +public slots: + void send(); + bool paste(bool fromMouse); + void updateState(int selectionStart, int selectionEnd, int cursorPosition, QString text); + +private: + TimelineModel *room; + QString text; + int selectionStart = 0, selectionEnd = 0, cursorPosition = 0; +}; diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 8b80ea51..aeb4e8f5 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -1567,3 +1567,4 @@ TimelineModel::roomTopic() const return utils::replaceEmoji(utils::linkifyMessage( utils::escapeBlacklistedHtml(QString::fromStdString(info[room_id_].topic)))); } + diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index e1fb9196..58a1496c 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h @@ -10,6 +10,7 @@ #include "CacheCryptoStructs.h" #include "EventStore.h" +#include "InputBar.h" #include "ui/UserProfile.h" namespace mtx::http { @@ -149,6 +150,7 @@ class TimelineModel : public QAbstractListModel Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged) Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY roomAvatarUrlChanged) Q_PROPERTY(QString roomTopic READ roomTopic NOTIFY roomTopicChanged) + Q_PROPERTY(InputBar *input READ input) public: explicit TimelineModel(TimelineViewManager *manager, @@ -271,6 +273,7 @@ public slots: QString roomName() const; QString roomTopic() const; + InputBar *input() { return &input_; } QString roomAvatarUrl() const; QString roomId() const { return room_id_; } @@ -320,6 +323,8 @@ private: TimelineViewManager *manager_; + InputBar input_{this}; + friend struct SendMessageVisitor; };