From 0bb488563288da75566e7da883fda31914ecf281 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Mon, 9 Nov 2020 03:12:37 +0100 Subject: Basic text input in qml --- src/timeline/TimelineViewManager.cpp | 75 ------------------------------------ 1 file changed, 75 deletions(-) (limited to 'src/timeline/TimelineViewManager.cpp') diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index 3b80d020..f949498d 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -474,81 +474,6 @@ TimelineViewManager::initWithMessages(const std::vector &roomIds) addRoom(roomId); } -void -TimelineViewManager::queueTextMessage(const QString &msg) -{ - if (!timeline_) - return; - - mtx::events::msg::Text text = {}; - text.body = msg.trimmed().toStdString(); - - if (ChatPage::instance()->userSettings()->markdown()) { - text.formatted_body = utils::markdownToHtml(msg).toStdString(); - - // Don't send formatted_body, when we don't need to - if (text.formatted_body.find("<") == std::string::npos) - text.formatted_body = ""; - else - text.format = "org.matrix.custom.html"; - } - - if (!timeline_->reply().isEmpty()) { - auto related = timeline_->relatedInfo(timeline_->reply()); - - QString body; - bool firstLine = true; - for (const auto &line : related.quoted_body.split("\n")) { - if (firstLine) { - firstLine = false; - body = QString("> <%1> %2\n").arg(related.quoted_user).arg(line); - } else { - body = QString("%1\n> %2\n").arg(body).arg(line); - } - } - - text.body = QString("%1\n%2").arg(body).arg(msg).toStdString(); - - // NOTE(Nico): rich replies always need a formatted_body! - text.format = "org.matrix.custom.html"; - if (ChatPage::instance()->userSettings()->markdown()) - text.formatted_body = - utils::getFormattedQuoteBody(related, utils::markdownToHtml(msg)) - .toStdString(); - else - text.formatted_body = - utils::getFormattedQuoteBody(related, msg.toHtmlEscaped()).toStdString(); - - text.relates_to.in_reply_to.event_id = related.related_event; - timeline_->resetReply(); - } - - timeline_->sendMessageEvent(text, mtx::events::EventType::RoomMessage); -} - -void -TimelineViewManager::queueEmoteMessage(const QString &msg) -{ - auto html = utils::markdownToHtml(msg); - - mtx::events::msg::Emote emote; - emote.body = msg.trimmed().toStdString(); - - if (html != msg.trimmed().toHtmlEscaped() && - ChatPage::instance()->userSettings()->markdown()) { - emote.formatted_body = html.toStdString(); - emote.format = "org.matrix.custom.html"; - } - - if (!timeline_->reply().isEmpty()) { - emote.relates_to.in_reply_to.event_id = timeline_->reply().toStdString(); - timeline_->resetReply(); - } - - if (timeline_) - timeline_->sendMessageEvent(emote, mtx::events::EventType::RoomMessage); -} - void TimelineViewManager::queueReactionMessage(const QString &reactedEvent, const QString &reactionKey) { -- cgit 1.5.1 From d1af1a86691290c67ad9e2b6ae9440b1254a2c0b Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Sun, 15 Nov 2020 23:14:47 +0100 Subject: Move calls to new input bar --- resources/qml/MessageInput.qml | 13 +++- resources/qml/NhekoBusyIndicator.qml | 4 +- src/ChatPage.cpp | 32 --------- src/ChatPage.h | 1 + src/TextInputWidget.cpp | 30 -------- src/TextInputWidget.h | 5 -- src/timeline/InputBar.cpp | 45 ++++++++++++ src/timeline/InputBar.h | 1 + src/timeline/TimelineViewManager.cpp | 136 ++++++----------------------------- src/timeline/TimelineViewManager.h | 31 ++------ 10 files changed, 86 insertions(+), 212 deletions(-) (limited to 'src/timeline/TimelineViewManager.cpp') diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index a1220599..17e1198d 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -17,14 +17,18 @@ Rectangle { spacing: 16 ImageButton { + visible: TimelineManager.callsSupported Layout.alignment: Qt.AlignBottom hoverEnabled: true width: 22 height: 22 - image: ":/icons/icons/ui/place-call.png" + image: TimelineManager.isOnCall ? ":/icons/icons/ui/end-call.png" : ":/icons/icons/ui/place-call.png" + ToolTip.visible: hovered + ToolTip.text: TimelineManager.isOnCall ? qsTr("Hang up") : qsTr("Place a call") Layout.topMargin: 8 Layout.bottomMargin: 8 Layout.leftMargin: 16 + onClicked: TimelineManager.timeline.input.callButton() } ImageButton { @@ -35,7 +39,10 @@ Rectangle { image: ":/icons/icons/ui/paper-clip-outline.png" Layout.topMargin: 8 Layout.bottomMargin: 8 + Layout.leftMargin: TimelineManager.callsSupported ? 0 : 16 onClicked: TimelineManager.timeline.input.openFileSelection() + ToolTip.visible: hovered + ToolTip.text: qsTr("Send a file") Rectangle { anchors.fill: parent @@ -112,6 +119,8 @@ Rectangle { image: ":/icons/icons/ui/smile.png" Layout.topMargin: 8 Layout.bottomMargin: 8 + ToolTip.visible: hovered + ToolTip.text: qsTr("Emoji") } ImageButton { @@ -123,6 +132,8 @@ Rectangle { Layout.topMargin: 8 Layout.bottomMargin: 8 Layout.rightMargin: 16 + ToolTip.visible: hovered + ToolTip.text: qsTr("Send") onClicked: { TimelineManager.timeline.input.send(); textArea.clear(); diff --git a/resources/qml/NhekoBusyIndicator.qml b/resources/qml/NhekoBusyIndicator.qml index 8889989a..89a40dd5 100644 --- a/resources/qml/NhekoBusyIndicator.qml +++ b/resources/qml/NhekoBusyIndicator.qml @@ -6,8 +6,8 @@ BusyIndicator { id: control contentItem: Item { - implicitWidth: Math.min(parent.height, parent.width) - implicitHeight: implicitWidth + implicitWidth: 64 + implicitHeight: 64 Item { id: item diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp index e09041e7..c703d95f 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp @@ -268,38 +268,6 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) this, SIGNAL(unreadMessages(int))); - connect(text_input_, &TextInputWidget::callButtonPress, this, [this]() { - if (callManager_->onActiveCall()) { - callManager_->hangUp(); - } else { - if (auto roomInfo = cache::singleRoomInfo(current_room_.toStdString()); - roomInfo.member_count != 2) { - showNotification("Calls are limited to 1:1 rooms."); - } else { - std::vector members( - cache::getMembers(current_room_.toStdString())); - const RoomMember &callee = - members.front().user_id == utils::localUser() ? members.back() - : members.front(); - auto dialog = new dialogs::PlaceCall( - callee.user_id, - callee.display_name, - QString::fromStdString(roomInfo.name), - QString::fromStdString(roomInfo.avatar_url), - userSettings_, - MainWindow::instance()); - connect(dialog, &dialogs::PlaceCall::voice, this, [this]() { - callManager_->sendInvite(current_room_, false); - }); - connect(dialog, &dialogs::PlaceCall::video, this, [this]() { - callManager_->sendInvite(current_room_, true); - }); - utils::centerWidget(dialog, MainWindow::instance()); - dialog->show(); - } - } - }); - connect( this, &ChatPage::updateGroupsInfo, communitiesList_, &CommunitiesList::setCommunities); diff --git a/src/ChatPage.h b/src/ChatPage.h index 41c6f276..7eb37f04 100644 --- a/src/ChatPage.h +++ b/src/ChatPage.h @@ -88,6 +88,7 @@ public: static ChatPage *instance() { return instance_; } QSharedPointer userSettings() { return userSettings_; } + CallManager *callManager() { return callManager_; } void deleteConfigs(); CommunitiesList *communitiesList() { return communitiesList_; } diff --git a/src/TextInputWidget.cpp b/src/TextInputWidget.cpp index 232c0cad..1a856abb 100644 --- a/src/TextInputWidget.cpp +++ b/src/TextInputWidget.cpp @@ -431,15 +431,6 @@ TextInputWidget::TextInputWidget(QWidget *parent) topLayout_->setSpacing(0); topLayout_->setContentsMargins(13, 1, 13, 0); -#ifdef GSTREAMER_AVAILABLE - callBtn_ = new FlatButton(this); - changeCallButtonState(webrtc::State::DISCONNECTED); - connect(&WebRTCSession::instance(), - &WebRTCSession::stateChanged, - this, - &TextInputWidget::changeCallButtonState); -#endif - QIcon send_file_icon; send_file_icon.addFile(":/icons/icons/ui/paper-clip-outline.png"); @@ -508,9 +499,6 @@ TextInputWidget::TextInputWidget(QWidget *parent) emojiBtn_->setIcon(emoji_icon); emojiBtn_->setIconSize(QSize(ButtonHeight, ButtonHeight)); -#ifdef GSTREAMER_AVAILABLE - topLayout_->addWidget(callBtn_); -#endif topLayout_->addWidget(sendFileBtn_); topLayout_->addWidget(input_); topLayout_->addWidget(emojiBtn_); @@ -518,9 +506,6 @@ TextInputWidget::TextInputWidget(QWidget *parent) setLayout(topLayout_); -#ifdef GSTREAMER_AVAILABLE - connect(callBtn_, &FlatButton::clicked, this, &TextInputWidget::callButtonPress); -#endif connect(sendMessageBtn_, &FlatButton::clicked, input_, &FilteredTextEdit::submit); connect(sendFileBtn_, SIGNAL(clicked()), this, SLOT(openFileSelection())); connect(emojiBtn_, @@ -570,18 +555,3 @@ TextInputWidget::paintEvent(QPaintEvent *) style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } - -void -TextInputWidget::changeCallButtonState(webrtc::State state) -{ - QIcon icon; - if (state == webrtc::State::ICEFAILED || state == webrtc::State::DISCONNECTED) { - callBtn_->setToolTip(tr("Place a call")); - icon.addFile(":/icons/icons/ui/place-call.png"); - } else { - callBtn_->setToolTip(tr("Hang up")); - icon.addFile(":/icons/icons/ui/end-call.png"); - } - callBtn_->setIcon(icon); - callBtn_->setIconSize(QSize(ButtonHeight * 1.1, ButtonHeight * 1.1)); -} diff --git a/src/TextInputWidget.h b/src/TextInputWidget.h index 44419547..9613f209 100644 --- a/src/TextInputWidget.h +++ b/src/TextInputWidget.h @@ -26,7 +26,6 @@ #include #include -#include "WebRTCSession.h" #include "dialogs/PreviewUploadOverlay.h" #include "emoji/PickButton.h" #include "popups/SuggestionsPopup.h" @@ -155,7 +154,6 @@ public: public slots: void focusLineEdit() { input_->setFocus(); } - void changeCallButtonState(webrtc::State); private slots: void addSelectedEmoji(const QString &emoji); @@ -163,8 +161,6 @@ private slots: signals: void heightChanged(int height); - void callButtonPress(); - void sendJoinRoomRequest(const QString &room); void sendInviteRoomRequest(const QString &userid, const QString &reason); void sendKickRoomRequest(const QString &userid, const QString &reason); @@ -185,7 +181,6 @@ private: LoadingIndicator *spinner_; - FlatButton *callBtn_; FlatButton *sendFileBtn_; FlatButton *sendMessageBtn_; emoji::PickButton *emojiBtn_; diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp index bd8f6414..dc287f94 100644 --- a/src/timeline/InputBar.cpp +++ b/src/timeline/InputBar.cpp @@ -12,13 +12,16 @@ #include #include "Cache.h" +#include "CallManager.h" #include "ChatPage.h" #include "Logging.h" +#include "MainWindow.h" #include "MatrixClient.h" #include "Olm.h" #include "TimelineModel.h" #include "UserSettingsPage.h" #include "Utils.h" +#include "dialogs/PlaceCall.h" #include "dialogs/PreviewUploadOverlay.h" #include "blurhash.hpp" @@ -511,3 +514,45 @@ InputBar::showPreview(const QMimeData &source, QString path, const QStringList & }); }); } + +void +InputBar::callButton() +{ + auto callManager_ = ChatPage::instance()->callManager(); + if (callManager_->onActiveCall()) { + callManager_->hangUp(); + } else { + auto current_room_ = room->roomId(); + if (auto roomInfo = cache::singleRoomInfo(current_room_.toStdString()); + roomInfo.member_count != 2) { + ChatPage::instance()->showNotification("Calls are limited to 1:1 rooms."); + } else { + std::vector members( + cache::getMembers(current_room_.toStdString())); + const RoomMember &callee = members.front().user_id == utils::localUser() + ? members.back() + : members.front(); + auto dialog = + new dialogs::PlaceCall(callee.user_id, + callee.display_name, + QString::fromStdString(roomInfo.name), + QString::fromStdString(roomInfo.avatar_url), + ChatPage::instance()->userSettings(), + MainWindow::instance()); + connect(dialog, + &dialogs::PlaceCall::voice, + callManager_, + [callManager_, current_room_]() { + callManager_->sendInvite(current_room_, false); + }); + connect(dialog, + &dialogs::PlaceCall::video, + callManager_, + [callManager_, current_room_]() { + callManager_->sendInvite(current_room_, true); + }); + utils::centerWidget(dialog, MainWindow::instance()); + dialog->show(); + } + } +} diff --git a/src/timeline/InputBar.h b/src/timeline/InputBar.h index 35e3f8a4..a52a3904 100644 --- a/src/timeline/InputBar.h +++ b/src/timeline/InputBar.h @@ -27,6 +27,7 @@ public slots: void updateState(int selectionStart, int selectionEnd, int cursorPosition, QString text); void openFileSelection(); bool uploading() const { return uploading_; } + void callButton(); signals: void insertText(QString text); diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index f949498d..1392c505 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -244,6 +244,26 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par &CallManager::newVideoCallState, this, &TimelineViewManager::videoCallChanged); + + connect(&WebRTCSession::instance(), + &WebRTCSession::stateChanged, + this, + &TimelineViewManager::onCallChanged); +} + +bool +TimelineViewManager::isOnCall() const +{ + return callManager_->onActiveCall(); +} +bool +TimelineViewManager::callsSupported() const +{ +#ifdef GSTREAMER_AVAILABLE + return true; +#else + return false; +#endif } void @@ -506,122 +526,6 @@ TimelineViewManager::queueReactionMessage(const QString &reactedEvent, const QSt timeline_->redactEvent(selfReactedEvent); } } - -void -TimelineViewManager::queueImageMessage(const QString &roomid, - const QString &filename, - const std::optional &file, - const QString &url, - const QString &mime, - uint64_t dsize, - const QSize &dimensions, - const QString &blurhash) -{ - mtx::events::msg::Image image; - image.info.mimetype = mime.toStdString(); - image.info.size = dsize; - image.info.blurhash = blurhash.toStdString(); - image.body = filename.toStdString(); - image.info.h = dimensions.height(); - image.info.w = dimensions.width(); - - if (file) - image.file = file; - else - image.url = url.toStdString(); - - auto model = models.value(roomid); - if (!model->reply().isEmpty()) { - image.relates_to.in_reply_to.event_id = model->reply().toStdString(); - model->resetReply(); - } - - model->sendMessageEvent(image, mtx::events::EventType::RoomMessage); -} - -void -TimelineViewManager::queueFileMessage( - const QString &roomid, - const QString &filename, - const std::optional &encryptedFile, - const QString &url, - const QString &mime, - uint64_t dsize) -{ - mtx::events::msg::File file; - file.info.mimetype = mime.toStdString(); - file.info.size = dsize; - file.body = filename.toStdString(); - - if (encryptedFile) - file.file = encryptedFile; - else - file.url = url.toStdString(); - - auto model = models.value(roomid); - if (!model->reply().isEmpty()) { - file.relates_to.in_reply_to.event_id = model->reply().toStdString(); - model->resetReply(); - } - - model->sendMessageEvent(file, mtx::events::EventType::RoomMessage); -} - -void -TimelineViewManager::queueAudioMessage(const QString &roomid, - const QString &filename, - const std::optional &file, - const QString &url, - const QString &mime, - uint64_t dsize) -{ - mtx::events::msg::Audio audio; - audio.info.mimetype = mime.toStdString(); - audio.info.size = dsize; - audio.body = filename.toStdString(); - audio.url = url.toStdString(); - - if (file) - audio.file = file; - else - audio.url = url.toStdString(); - - auto model = models.value(roomid); - if (!model->reply().isEmpty()) { - audio.relates_to.in_reply_to.event_id = model->reply().toStdString(); - model->resetReply(); - } - - model->sendMessageEvent(audio, mtx::events::EventType::RoomMessage); -} - -void -TimelineViewManager::queueVideoMessage(const QString &roomid, - const QString &filename, - const std::optional &file, - const QString &url, - const QString &mime, - uint64_t dsize) -{ - mtx::events::msg::Video video; - video.info.mimetype = mime.toStdString(); - video.info.size = dsize; - video.body = filename.toStdString(); - - if (file) - video.file = file; - else - video.url = url.toStdString(); - - auto model = models.value(roomid); - if (!model->reply().isEmpty()) { - video.relates_to.in_reply_to.event_id = model->reply().toStdString(); - model->resetReply(); - } - - model->sendMessageEvent(video, mtx::events::EventType::RoomMessage); -} - void TimelineViewManager::queueCallMessage(const QString &roomid, const mtx::events::msg::CallInvite &callInvite) diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 02e0e132..371e9af2 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -41,6 +41,8 @@ class TimelineViewManager : public QObject Q_PROPERTY(QString callPartyName READ callPartyName NOTIFY callPartyChanged) Q_PROPERTY(QString callPartyAvatarUrl READ callPartyAvatarUrl NOTIFY callPartyChanged) Q_PROPERTY(bool isMicMuted READ isMicMuted NOTIFY micMuteChanged) + Q_PROPERTY(bool isOnCall READ isOnCall NOTIFY onCallChanged) + Q_PROPERTY(bool callsSupported READ callsSupported CONSTANT) public: TimelineViewManager(CallManager *callManager, ChatPage *parent = nullptr); @@ -95,6 +97,7 @@ signals: void videoCallChanged(); void callPartyChanged(); void micMuteChanged(); + void onCallChanged(); public slots: void updateReadReceipts(const QString &room_id, const std::vector &event_ids); @@ -104,38 +107,14 @@ public slots: void setHistoryView(const QString &room_id); void updateColorPalette(); void queueReactionMessage(const QString &reactedEvent, const QString &reactionKey); - void queueImageMessage(const QString &roomid, - const QString &filename, - const std::optional &file, - const QString &url, - const QString &mime, - uint64_t dsize, - const QSize &dimensions, - const QString &blurhash); - void queueFileMessage(const QString &roomid, - const QString &filename, - const std::optional &file, - const QString &url, - const QString &mime, - uint64_t dsize); - void queueAudioMessage(const QString &roomid, - const QString &filename, - const std::optional &file, - const QString &url, - const QString &mime, - uint64_t dsize); - void queueVideoMessage(const QString &roomid, - const QString &filename, - const std::optional &file, - const QString &url, - const QString &mime, - uint64_t dsize); void queueCallMessage(const QString &roomid, const mtx::events::msg::CallInvite &); void queueCallMessage(const QString &roomid, const mtx::events::msg::CallCandidates &); void queueCallMessage(const QString &roomid, const mtx::events::msg::CallAnswer &); void queueCallMessage(const QString &roomid, const mtx::events::msg::CallHangUp &); void updateEncryptedDescriptions(); + bool isOnCall() const; + bool callsSupported() const; void enableBackButton() { -- cgit 1.5.1 From c74077a41f5e89c0331d682b481408ad22d7ec78 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Wed, 25 Nov 2020 17:02:23 +0100 Subject: Implement Qml drag and drop --- CMakeLists.txt | 12 ++++++----- resources/qml/MessageInput.qml | 5 +++++ src/ChatPage.h | 1 + src/timeline/InputBar.cpp | 8 ++++++++ src/timeline/InputBar.h | 2 ++ src/timeline/TimelineViewManager.cpp | 3 +++ src/timeline/TimelineViewManager.h | 9 +++++++++ src/ui/NhekoDropArea.cpp | 39 ++++++++++++++++++++++++++++++++++++ src/ui/NhekoDropArea.h | 30 +++++++++++++++++++++++++++ 9 files changed, 104 insertions(+), 5 deletions(-) create mode 100644 src/ui/NhekoDropArea.cpp create mode 100644 src/ui/NhekoDropArea.h (limited to 'src/timeline/TimelineViewManager.cpp') diff --git a/CMakeLists.txt b/CMakeLists.txt index bd42938a..e8570c77 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -257,22 +257,23 @@ set(SRC_FILES src/ui/Avatar.cpp src/ui/Badge.cpp src/ui/DropShadow.cpp - src/ui/LoadingIndicator.cpp - src/ui/InfoMessage.cpp src/ui/FlatButton.cpp src/ui/FloatingButton.cpp + src/ui/InfoMessage.cpp src/ui/Label.cpp + src/ui/LoadingIndicator.cpp + src/ui/NhekoDropArea.cpp src/ui/OverlayModal.cpp - src/ui/SnackBar.cpp + src/ui/OverlayWidget.cpp src/ui/RaisedButton.cpp src/ui/Ripple.cpp src/ui/RippleOverlay.cpp - src/ui/OverlayWidget.cpp + src/ui/SnackBar.cpp src/ui/TextField.cpp src/ui/TextLabel.cpp - src/ui/ToggleButton.cpp src/ui/Theme.cpp src/ui/ThemeManager.cpp + src/ui/ToggleButton.cpp src/ui/UserProfile.cpp src/AvatarProvider.cpp @@ -471,6 +472,7 @@ qt5_wrap_cpp(MOC_HEADERS src/ui/Label.h src/ui/FloatingButton.h src/ui/Menu.h + src/ui/NhekoDropArea.h src/ui/OverlayWidget.h src/ui/SnackBar.h src/ui/RaisedButton.h diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index 76eac5b3..812c450e 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -178,6 +178,11 @@ Rectangle { onClicked: TimelineManager.timeline.input.paste(true) } + NhekoDropArea { + anchors.fill: parent + roomid: TimelineManager.timeline.roomId() + } + background: Rectangle { color: colors.window } diff --git a/src/ChatPage.h b/src/ChatPage.h index 273ba4af..5b336cbb 100644 --- a/src/ChatPage.h +++ b/src/ChatPage.h @@ -88,6 +88,7 @@ public: QSharedPointer userSettings() { return userSettings_; } CallManager *callManager() { return callManager_; } + TimelineViewManager *timelineManager() { return view_manager_; } void deleteConfigs(); CommunitiesList *communitiesList() { return communitiesList_; } diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp index b0d555b7..46bbd9a2 100644 --- a/src/timeline/InputBar.cpp +++ b/src/timeline/InputBar.cpp @@ -1,6 +1,7 @@ #include "InputBar.h" #include +#include #include #include #include @@ -44,6 +45,13 @@ InputBar::paste(bool fromMouse) md = QGuiApplication::clipboard()->mimeData(QClipboard::Clipboard); } + if (md) + insertMimeData(md); +} + +void +InputBar::insertMimeData(const QMimeData *md) +{ if (!md) return; diff --git a/src/timeline/InputBar.h b/src/timeline/InputBar.h index 939e8dad..27aa4bc3 100644 --- a/src/timeline/InputBar.h +++ b/src/timeline/InputBar.h @@ -9,6 +9,7 @@ class TimelineModel; class QMimeData; +class QDropEvent; class QStringList; class InputBar : public QObject @@ -36,6 +37,7 @@ public slots: void send(); void paste(bool fromMouse); + void insertMimeData(const QMimeData *data); void updateState(int selectionStart, int selectionEnd, int cursorPosition, QString text); void openFileSelection(); bool uploading() const { return uploading_; } diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index 1392c505..866e7c51 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -1,6 +1,7 @@ #include "TimelineViewManager.h" #include +#include #include #include #include @@ -20,6 +21,7 @@ #include "dialogs/ImageOverlay.h" #include "emoji/EmojiModel.h" #include "emoji/Provider.h" +#include "ui/NhekoDropArea.h" #include //only for debugging @@ -115,6 +117,7 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par qmlRegisterType("im.nheko", 1, 0, "DelegateChoice"); qmlRegisterType("im.nheko", 1, 0, "DelegateChooser"); + qmlRegisterType("im.nheko", 1, 0, "NhekoDropArea"); qmlRegisterUncreatableType( "im.nheko", 1, 0, "DeviceVerificationFlow", "Can't create verification flow from QML!"); qmlRegisterUncreatableType( diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 371e9af2..b9febf75 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -105,6 +105,15 @@ public slots: void initWithMessages(const std::vector &roomIds); void setHistoryView(const QString &room_id); + TimelineModel *getHistoryView(const QString &room_id) + { + auto room = models.find(room_id); + if (room != models.end()) + return room.value().data(); + else + return nullptr; + } + void updateColorPalette(); void queueReactionMessage(const QString &reactedEvent, const QString &reactionKey); void queueCallMessage(const QString &roomid, const mtx::events::msg::CallInvite &); diff --git a/src/ui/NhekoDropArea.cpp b/src/ui/NhekoDropArea.cpp new file mode 100644 index 00000000..14b71524 --- /dev/null +++ b/src/ui/NhekoDropArea.cpp @@ -0,0 +1,39 @@ +#include "NhekoDropArea.h" + +#include + +#include "ChatPage.h" +#include "timeline/InputBar.h" +#include "timeline/TimelineModel.h" +#include "timeline/TimelineViewManager.h" + +#include "Logging.h" + +NhekoDropArea::NhekoDropArea(QQuickItem *parent) + : QQuickItem(parent) +{ + setFlags(ItemAcceptsDrops); +} + +void +NhekoDropArea::dragEnterEvent(QDragEnterEvent *event) +{ + event->acceptProposedAction(); +} + +void +NhekoDropArea::dragMoveEvent(QDragMoveEvent *event) +{ + event->acceptProposedAction(); +} + +void +NhekoDropArea::dropEvent(QDropEvent *event) +{ + if (event) { + auto model = ChatPage::instance()->timelineManager()->getHistoryView(roomid_); + if (model) { + model->input()->insertMimeData(event->mimeData()); + } + } +} diff --git a/src/ui/NhekoDropArea.h b/src/ui/NhekoDropArea.h new file mode 100644 index 00000000..b03620f2 --- /dev/null +++ b/src/ui/NhekoDropArea.h @@ -0,0 +1,30 @@ +#include + +class NhekoDropArea : public QQuickItem +{ + Q_OBJECT + Q_PROPERTY(QString roomid READ roomid WRITE setRoomid NOTIFY roomidChanged) +public: + NhekoDropArea(QQuickItem *parent = nullptr); + +signals: + void roomidChanged(QString roomid); + +public slots: + void setRoomid(QString roomid) + { + if (roomid_ != roomid) { + roomid_ = roomid; + emit roomidChanged(roomid); + } + } + QString roomid() const { return roomid_; } + +protected: + void dragEnterEvent(QDragEnterEvent *event) override; + void dragMoveEvent(QDragMoveEvent *event) override; + void dropEvent(QDropEvent *event) override; + +private: + QString roomid_; +}; -- cgit 1.5.1 From 08e94616113921dbbbf3bcfe2ec4cee7e28eaf1b Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Wed, 25 Nov 2020 17:38:06 +0100 Subject: Fix input focus when pressing reply button --- resources/qml/ImageButton.qml | 1 + resources/qml/MatrixText.qml | 1 + resources/qml/MessageInput.qml | 1 + resources/qml/TimelineView.qml | 1 + src/timeline/TimelineViewManager.cpp | 1 + 5 files changed, 5 insertions(+) (limited to 'src/timeline/TimelineViewManager.cpp') diff --git a/resources/qml/ImageButton.qml b/resources/qml/ImageButton.qml index 49ddf671..4ebda680 100644 --- a/resources/qml/ImageButton.qml +++ b/resources/qml/ImageButton.qml @@ -8,6 +8,7 @@ AbstractButton { property color highlightColor: colors.highlight property color buttonTextColor: colors.buttonText + focusPolicy: Qt.NoFocus width: 16 height: 16 diff --git a/resources/qml/MatrixText.qml b/resources/qml/MatrixText.qml index a5781c73..bb3b4296 100644 --- a/resources/qml/MatrixText.qml +++ b/resources/qml/MatrixText.qml @@ -5,6 +5,7 @@ import im.nheko 1.0 TextEdit { textFormat: TextEdit.RichText readOnly: true + focus: false wrapMode: Text.Wrap selectByMouse: !Settings.mobileMode color: colors.text diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index 812c450e..c221cf3e 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -79,6 +79,7 @@ Rectangle { placeholderTextColor: colors.buttonText color: colors.text wrapMode: TextEdit.Wrap + focus: true onTextChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text) onCursorPositionChanged: { TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text); diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index ac998a81..4234bb6d 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -97,6 +97,7 @@ Page { } MenuItem { + // TODO(Nico): Fix this still being iterated over, when using keyboard to select options visible: messageContextMenu.isEncrypted height: visible ? implicitHeight : 0 text: qsTr("View decrypted raw message") diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index 866e7c51..d0356e15 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -336,6 +336,7 @@ TimelineViewManager::setHistoryView(const QString &room_id) if (room != models.end()) { timeline_ = room.value().data(); emit activeTimelineChanged(timeline_); + container->setFocus(); nhlog::ui()->info("Activated room {}", room_id.toStdString()); } } -- cgit 1.5.1