From 07ac7b7e85b504953b0a751a3f56b60ce0a6fb37 Mon Sep 17 00:00:00 2001 From: trilene Date: Fri, 18 Dec 2020 12:49:24 -0500 Subject: [PATCH] Port PlaceCall dialog to Qml --- CMakeLists.txt | 2 - resources/qml/MessageInput.qml | 23 +++++- resources/qml/voip/PlaceCall.qml | 107 +++++++++++++++++++++++++ resources/res.qrc | 1 + src/CallManager.h | 2 +- src/ChatPage.cpp | 1 - src/dialogs/PlaceCall.cpp | 131 ------------------------------- src/dialogs/PlaceCall.h | 44 ----------- src/timeline/InputBar.cpp | 46 ----------- src/timeline/InputBar.h | 1 - 10 files changed, 131 insertions(+), 227 deletions(-) create mode 100644 resources/qml/voip/PlaceCall.qml delete mode 100644 src/dialogs/PlaceCall.cpp delete mode 100644 src/dialogs/PlaceCall.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c674053f..2365ac09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -253,7 +253,6 @@ set(SRC_FILES src/dialogs/LeaveRoom.cpp src/dialogs/Logout.cpp src/dialogs/MemberList.cpp - src/dialogs/PlaceCall.cpp src/dialogs/PreviewUploadOverlay.cpp src/dialogs/ReCaptcha.cpp src/dialogs/ReadReceipts.cpp @@ -471,7 +470,6 @@ qt5_wrap_cpp(MOC_HEADERS src/dialogs/LeaveRoom.h src/dialogs/Logout.h src/dialogs/MemberList.h - src/dialogs/PlaceCall.h src/dialogs/PreviewUploadOverlay.h src/dialogs/RawMessage.h src/dialogs/ReCaptcha.h diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index 2847d51d..ecacedba 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -3,6 +3,7 @@ import QtQuick.Controls 2.3 import QtQuick.Layouts 1.2 import QtQuick.Window 2.2 import im.nheko 1.0 +import "./voip" Rectangle { color: colors.window @@ -10,6 +11,13 @@ Rectangle { Layout.preferredHeight: textInput.height Layout.minimumHeight: 40 + Component { + id: placeCallDialog + + PlaceCall { + } + } + RowLayout { id: inputBar @@ -28,7 +36,20 @@ Rectangle { Layout.topMargin: 8 Layout.bottomMargin: 8 Layout.leftMargin: 16 - onClicked: TimelineManager.timeline.input.callButton() + onClicked: { + if (TimelineManager.timeline) { + if (CallManager.haveCallInvite) { + return; + } + else if (CallManager.isOnCall) { + CallManager.hangUp(); + } + else { + var dialog = placeCallDialog.createObject(timelineRoot); + dialog.show(); + } + } + } } ImageButton { diff --git a/resources/qml/voip/PlaceCall.qml b/resources/qml/voip/PlaceCall.qml new file mode 100644 index 00000000..7bf76ca6 --- /dev/null +++ b/resources/qml/voip/PlaceCall.qml @@ -0,0 +1,107 @@ +import QtQuick 2.3 +import QtQuick.Controls 2.3 +import QtQuick.Dialogs 1.3 +import QtQuick.Layouts 1.2 +import im.nheko 1.0 +import "../" + +ApplicationWindow { + + flags: Qt.Dialog + modality: Qt.ApplicationModal + palette: colors + width: columnLayout.implicitWidth + height: columnLayout.implicitHeight + + MessageDialog { + id: warningDialog + icon: StandardIcon.Warning + } + + ColumnLayout { + + id: columnLayout + spacing: 16 + + RowLayout { + + Layout.topMargin: 16 + Layout.leftMargin: 8 + + Label { + font.pointSize: fontMetrics.font.pointSize * 1.1 + text: "Place a call to " + TimelineManager.timeline.roomName + "?" + } + + Item { + Layout.fillWidth: true + } + } + + RowLayout { + + id: rowLayout + Layout.leftMargin: 8 + Layout.rightMargin: 8 + Layout.bottomMargin: 16 + spacing: 16 + + function validateMic() { + if (CallManager.mics.length == 0) { + warningDialog.text = "No microphone found."; + warningDialog.open(); + return false; + } + else if (!CallManager.mics.includes(Settings.microphone)) { + warningDialog.text = "Unknown microphone: " + Settings.microphone; + warningDialog.open(); + return false; + } + return true; + } + + Avatar { + width: avatarSize + height: avatarSize + url: TimelineManager.timeline.roomAvatarUrl.replace("mxc://", "image://MxcImage/") + displayName: TimelineManager.timeline.roomName + } + + Button { + text: qsTr("Voice") + icon.source: "qrc:/icons/icons/ui/place-call.png" + onClicked: { + if (rowLayout.validateMic()) { + CallManager.sendInvite(TimelineManager.timeline.roomId(), false); + close(); + } + } + } + + Button { + visible: CallManager.cameras.length > 0 + text: qsTr("Video") + icon.source: "qrc:/icons/icons/ui/video-call.png" + onClicked: { + if (rowLayout.validateMic()) { + if (!CallManager.cameras.includes(Settings.camera)) { + warningDialog.text = "Unknown camera: " + Settings.camera; + warningDialog.open(); + return; + } + CallManager.sendInvite(TimelineManager.timeline.roomId(), true); + close(); + } + } + } + + Button { + palette: colors + text: qsTr("Cancel") + onClicked: { + close(); + } + } + } + } +} diff --git a/resources/res.qrc b/resources/res.qrc index 321fe12e..52157df0 100644 --- a/resources/res.qrc +++ b/resources/res.qrc @@ -159,6 +159,7 @@ qml/device-verification/Success.qml qml/voip/ActiveCallBar.qml qml/voip/CallInviteBar.qml + qml/voip/PlaceCall.qml qml/voip/VideoCall.qml diff --git a/src/CallManager.h b/src/CallManager.h index ad25fbd1..75768ee1 100644 --- a/src/CallManager.h +++ b/src/CallManager.h @@ -37,7 +37,6 @@ class CallManager : public QObject public: CallManager(QObject *); - void sendInvite(const QString &roomid, bool isVideo); bool haveCallInvite() const { return haveCallInvite_; } bool isOnCall() const { return session_.state() != webrtc::State::DISCONNECTED; } bool isVideo() const { return isVideo_; } @@ -52,6 +51,7 @@ public: void refreshTurnServer(); public slots: + void sendInvite(const QString &roomid, bool isVideo); void syncEvent(const mtx::events::collections::TimelineEvents &event); void toggleMicMute(); void toggleCameraView() { session_.toggleCameraView(); } diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp index 4e87349a..238c9362 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp @@ -47,7 +47,6 @@ #include "notifications/Manager.h" -#include "dialogs/PlaceCall.h" #include "dialogs/ReadReceipts.h" #include "popups/UserMentions.h" #include "timeline/TimelineViewManager.h" diff --git a/src/dialogs/PlaceCall.cpp b/src/dialogs/PlaceCall.cpp deleted file mode 100644 index 85a398a2..00000000 --- a/src/dialogs/PlaceCall.cpp +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include -#include -#include -#include - -#include "ChatPage.h" -#include "Config.h" -#include "UserSettingsPage.h" -#include "Utils.h" -#include "WebRTCSession.h" -#include "dialogs/PlaceCall.h" -#include "ui/Avatar.h" - -namespace dialogs { - -PlaceCall::PlaceCall(const QString &callee, - const QString &displayName, - const QString &roomName, - const QString &avatarUrl, - QSharedPointer settings, - QWidget *parent) - : QWidget(parent) -{ - std::string errorMessage; - WebRTCSession *session = &WebRTCSession::instance(); - if (!session->havePlugins(false, &errorMessage)) { - emit ChatPage::instance()->showNotification(QString::fromStdString(errorMessage)); - emit close(); - return; - } - session->refreshDevices(); - microphones_ = session->getDeviceNames(false, settings->microphone().toStdString()); - if (microphones_.empty()) { - emit ChatPage::instance()->showNotification(tr("No microphone found.")); - emit close(); - return; - } - cameras_ = session->getDeviceNames(true, settings->camera().toStdString()); - - setAutoFillBackground(true); - setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); - setWindowModality(Qt::WindowModal); - setAttribute(Qt::WA_DeleteOnClose, true); - - auto layout = new QVBoxLayout(this); - layout->setSpacing(conf::modals::WIDGET_SPACING); - layout->setMargin(conf::modals::WIDGET_MARGIN); - - auto buttonLayout = new QHBoxLayout; - buttonLayout->setSpacing(15); - buttonLayout->setMargin(0); - - QFont f; - f.setPointSizeF(f.pointSizeF()); - auto avatar = new Avatar(this, QFontMetrics(f).height() * 3); - if (!avatarUrl.isEmpty()) - avatar->setImage(avatarUrl); - else - avatar->setLetter(utils::firstChar(roomName)); - - voiceBtn_ = new QPushButton(tr("Voice"), this); - voiceBtn_->setIcon(QIcon(":/icons/icons/ui/place-call.png")); - voiceBtn_->setIconSize(QSize(iconSize_, iconSize_)); - voiceBtn_->setDefault(true); - - if (!cameras_.empty()) { - videoBtn_ = new QPushButton(tr("Video"), this); - videoBtn_->setIcon(QIcon(":/icons/icons/ui/video-call.png")); - videoBtn_->setIconSize(QSize(iconSize_, iconSize_)); - } - cancelBtn_ = new QPushButton(tr("Cancel"), this); - - buttonLayout->addWidget(avatar); - buttonLayout->addStretch(); - buttonLayout->addWidget(voiceBtn_); - if (videoBtn_) - buttonLayout->addWidget(videoBtn_); - buttonLayout->addWidget(cancelBtn_); - - QString name = displayName.isEmpty() ? callee : displayName; - QLabel *label = new QLabel(tr("Place a call to ") + name + "?", this); - - microphoneCombo_ = new QComboBox(this); - for (const auto &m : microphones_) - microphoneCombo_->addItem(QIcon(":/icons/icons/ui/microphone-unmute.png"), - QString::fromStdString(m)); - - if (videoBtn_) { - cameraCombo_ = new QComboBox(this); - for (const auto &c : cameras_) - cameraCombo_->addItem(QIcon(":/icons/icons/ui/video-call.png"), - QString::fromStdString(c)); - } - - layout->addWidget(label); - layout->addLayout(buttonLayout); - layout->addStretch(); - layout->addWidget(microphoneCombo_); - if (videoBtn_) - layout->addWidget(cameraCombo_); - - connect(voiceBtn_, &QPushButton::clicked, this, [this, settings]() { - settings->setMicrophone( - QString::fromStdString(microphones_[microphoneCombo_->currentIndex()])); - emit voice(); - emit close(); - }); - if (videoBtn_) - connect(videoBtn_, &QPushButton::clicked, this, [this, settings, session]() { - std::string error; - if (!session->havePlugins(true, &error)) { - emit ChatPage::instance()->showNotification( - QString::fromStdString(error)); - emit close(); - return; - } - settings->setMicrophone( - QString::fromStdString(microphones_[microphoneCombo_->currentIndex()])); - settings->setCamera( - QString::fromStdString(cameras_[cameraCombo_->currentIndex()])); - emit video(); - emit close(); - }); - connect(cancelBtn_, &QPushButton::clicked, this, [this]() { - emit cancel(); - emit close(); - }); -} - -} diff --git a/src/dialogs/PlaceCall.h b/src/dialogs/PlaceCall.h deleted file mode 100644 index e042258f..00000000 --- a/src/dialogs/PlaceCall.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include -#include - -#include -#include - -class QComboBox; -class QPushButton; -class QString; -class UserSettings; - -namespace dialogs { - -class PlaceCall : public QWidget -{ - Q_OBJECT - -public: - PlaceCall(const QString &callee, - const QString &displayName, - const QString &roomName, - const QString &avatarUrl, - QSharedPointer settings, - QWidget *parent = nullptr); - -signals: - void voice(); - void video(); - void cancel(); - -private: - const int iconSize_ = 18; - QPushButton *voiceBtn_ = nullptr; - QPushButton *videoBtn_ = nullptr; - QPushButton *cancelBtn_ = nullptr; - QComboBox *microphoneCombo_ = nullptr; - QComboBox *cameraCombo_ = nullptr; - std::vector microphones_; - std::vector cameras_; -}; - -} diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp index 78c8c6a3..3cddd613 100644 --- a/src/timeline/InputBar.cpp +++ b/src/timeline/InputBar.cpp @@ -13,7 +13,6 @@ #include #include "Cache.h" -#include "CallManager.h" #include "ChatPage.h" #include "CompletionProxyModel.h" #include "Logging.h" @@ -25,7 +24,6 @@ #include "UserSettingsPage.h" #include "UsersModel.h" #include "Utils.h" -#include "dialogs/PlaceCall.h" #include "dialogs/PreviewUploadOverlay.h" #include "emoji/EmojiModel.h" @@ -593,50 +591,6 @@ InputBar::showPreview(const QMimeData &source, QString path, const QStringList & }); } -void -InputBar::callButton() -{ - auto callManager_ = ChatPage::instance()->callManager(); - if (callManager_->haveCallInvite()) { - return; - } else if (callManager_->isOnCall()) { - 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(); - } - } -} - void InputBar::startTyping() { diff --git a/src/timeline/InputBar.h b/src/timeline/InputBar.h index 89ca34fe..c729a6fc 100644 --- a/src/timeline/InputBar.h +++ b/src/timeline/InputBar.h @@ -41,7 +41,6 @@ public slots: void updateState(int selectionStart, int selectionEnd, int cursorPosition, QString text); void openFileSelection(); bool uploading() const { return uploading_; } - void callButton(); void message(QString body); QObject *completerFor(QString completerName);