mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-07-29 20:05:36 +02:00
feature: improve advanced call information overlay
GitLab: #925 Change-Id: Id75b14bf431ac421b135beb75918dbf37a81d53c
This commit is contained in:
parent
a28d5c5c55
commit
c977c732f2
24 changed files with 853 additions and 252 deletions
0
build.py
Normal file → Executable file
0
build.py
Normal file → Executable file
2
daemon
2
daemon
|
@ -1 +1 @@
|
|||
Subproject commit 9d76cf5cc767e33ab06054bfa40ee45f671002bd
|
||||
Subproject commit eb9c52cee45660f68334adb32a23d6f743d6bcf4
|
|
@ -37,19 +37,27 @@
|
|||
|
||||
AvAdapter::AvAdapter(LRCInstance* instance, QObject* parent)
|
||||
: QmlAdapterBase(instance, parent)
|
||||
, rendererInformationListModel_(std::make_unique<RendererInformationListModel>())
|
||||
{
|
||||
set_renderersInfoList(QVariant::fromValue(rendererInformationListModel_.get()));
|
||||
connect(&lrcInstance_->avModel(),
|
||||
&lrc::api::AVModel::audioDeviceEvent,
|
||||
this,
|
||||
&AvAdapter::onAudioDeviceEvent);
|
||||
// QueuedConnection mandatory to avoid deadlock
|
||||
connect(&lrcInstance_->avModel(),
|
||||
&lrc::api::AVModel::rendererStarted,
|
||||
this,
|
||||
&AvAdapter::onRendererStarted);
|
||||
&AvAdapter::onRendererStarted,
|
||||
Qt::QueuedConnection);
|
||||
connect(&lrcInstance_->avModel(),
|
||||
&lrc::api::AVModel::onRendererInfosUpdated,
|
||||
&lrc::api::AVModel::rendererStopped,
|
||||
this,
|
||||
&AvAdapter::setRenderersInfoList);
|
||||
&AvAdapter::onRendererStopped);
|
||||
connect(&lrcInstance_->avModel(),
|
||||
&lrc::api::AVModel::onRendererFpsChange,
|
||||
this,
|
||||
&AvAdapter::updateRenderersFPSInfo);
|
||||
}
|
||||
|
||||
// The top left corner of primary screen is (0, 0).
|
||||
|
@ -323,6 +331,12 @@ AvAdapter::onRendererStarted(const QString& id, const QSize& size)
|
|||
if (callId.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// update renderer Information list
|
||||
auto& avModel = lrcInstance_->avModel();
|
||||
auto rendererInfo = avModel.getRenderersInfo(id)[0];
|
||||
rendererInformationListModel_->addElement(qMakePair(id, rendererInfo));
|
||||
|
||||
auto callModel = lrcInstance_->getCurrentCallModel();
|
||||
auto renderDevice = callModel->getCurrentRenderedDevice(callId);
|
||||
if (!id.contains("://"))
|
||||
|
@ -331,6 +345,12 @@ AvAdapter::onRendererStarted(const QString& id, const QSize& size)
|
|||
set_currentRenderingDeviceType(renderDevice.type);
|
||||
}
|
||||
|
||||
void
|
||||
AvAdapter::onRendererStopped(const QString& id)
|
||||
{
|
||||
rendererInformationListModel_->removeElement(id);
|
||||
}
|
||||
|
||||
bool
|
||||
AvAdapter::isSharing() const
|
||||
{
|
||||
|
@ -448,7 +468,23 @@ AvAdapter::setHardwareAcceleration(bool accelerate)
|
|||
}
|
||||
|
||||
void
|
||||
AvAdapter::setRenderersInfoList(QVariantList renderersInfo)
|
||||
AvAdapter::resetRendererInfo()
|
||||
{
|
||||
set_renderersInfoList(renderersInfo);
|
||||
rendererInformationListModel_->reset();
|
||||
}
|
||||
|
||||
void
|
||||
AvAdapter::setRendererInfo()
|
||||
{
|
||||
auto& avModel = lrcInstance_->avModel();
|
||||
for (auto rendererInfo : avModel.getRenderersInfo()) {
|
||||
rendererInformationListModel_->addElement(
|
||||
qMakePair(rendererInfo["RENDERER_ID"], rendererInfo));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AvAdapter::updateRenderersFPSInfo(QPair<QString, QString> fpsInfo)
|
||||
{
|
||||
rendererInformationListModel_->updateFps(fpsInfo.first, fpsInfo.second);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include <QString>
|
||||
#include <qtutils.h>
|
||||
|
||||
#include "rendererinformationlistmodel.h"
|
||||
|
||||
class AvAdapter final : public QmlAdapterBase
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -36,7 +38,7 @@ class AvAdapter final : public QmlAdapterBase
|
|||
QML_PROPERTY(bool, muteCamera)
|
||||
QML_RO_PROPERTY(QStringList, windowsNames)
|
||||
QML_RO_PROPERTY(QList<QVariant>, windowsIds)
|
||||
QML_RO_PROPERTY(QVariantList, renderersInfoList)
|
||||
QML_RO_PROPERTY(QVariant, renderersInfoList)
|
||||
|
||||
public:
|
||||
explicit AvAdapter(LRCInstance* instance, QObject* parent = nullptr);
|
||||
|
@ -103,14 +105,18 @@ protected:
|
|||
Q_INVOKABLE void increaseCodecPriority(unsigned int id, bool isVideo);
|
||||
Q_INVOKABLE void decreaseCodecPriority(unsigned int id, bool isVideo);
|
||||
|
||||
Q_INVOKABLE void resetRendererInfo();
|
||||
Q_INVOKABLE void setRendererInfo();
|
||||
|
||||
// TODO: to be removed
|
||||
Q_INVOKABLE bool getHardwareAcceleration();
|
||||
Q_INVOKABLE void setHardwareAcceleration(bool accelerate);
|
||||
|
||||
private Q_SLOTS:
|
||||
void setRenderersInfoList(QVariantList renderersInfo);
|
||||
void updateRenderersFPSInfo(QPair<QString, QString> fpsInfo);
|
||||
void onAudioDeviceEvent();
|
||||
void onRendererStarted(const QString& id, const QSize& size);
|
||||
void onRendererStopped(const QString& id);
|
||||
|
||||
private:
|
||||
// Get screens arrangement rect relative to primary screen.
|
||||
|
@ -118,4 +124,6 @@ private:
|
|||
|
||||
// Get the screen number
|
||||
int getScreenNumber(int screenId = 0) const;
|
||||
|
||||
std::unique_ptr<RendererInformationListModel> rendererInformationListModel_;
|
||||
};
|
||||
|
|
|
@ -40,7 +40,10 @@
|
|||
CallAdapter::CallAdapter(SystemTray* systemTray, LRCInstance* instance, QObject* parent)
|
||||
: QmlAdapterBase(instance, parent)
|
||||
, systemTray_(systemTray)
|
||||
, callInformationListModel_(std::make_unique<CallInformationListModel>())
|
||||
{
|
||||
set_callInformationList(QVariant::fromValue(callInformationListModel_.get()));
|
||||
|
||||
timer = new QTimer(this);
|
||||
connect(timer, &QTimer::timeout, this, &CallAdapter::updateAdvancedInformation);
|
||||
|
||||
|
@ -127,7 +130,6 @@ CallAdapter::onCallStatusChanged(const QString& accountId, const QString& callId
|
|||
auto& accInfo = lrcInstance_->accountModel().getAccountInfo(accountId);
|
||||
auto& callModel = accInfo.callModel;
|
||||
const auto call = callModel->getCall(callId);
|
||||
auto to = lrcInstance_->accountModel().bestNameForAccount(accountId);
|
||||
|
||||
const auto& convInfo = lrcInstance_->getConversationFromCallId(callId, accountId);
|
||||
if (convInfo.uid.isEmpty() || call.isOutgoing)
|
||||
|
@ -150,7 +152,7 @@ CallAdapter::onCallStatusChanged(const QString& accountId, const QString& callId
|
|||
auto from = accInfo.conversationModel->title(convInfo.uid);
|
||||
auto notifId = QString("%1;%2").arg(accountId).arg(convInfo.uid);
|
||||
systemTray_->showNotification(notifId,
|
||||
tr("%1 missed call").arg(to),
|
||||
tr("Missed call"),
|
||||
tr("Missed call with %1").arg(from),
|
||||
NotificationType::CHAT,
|
||||
Utils::QImageToByteArray(convAvatar));
|
||||
|
@ -170,6 +172,7 @@ CallAdapter::onParticipantAdded(const QString& callId, int index)
|
|||
try {
|
||||
if (lrcInstance_->get_selectedConvUid().isEmpty())
|
||||
return;
|
||||
|
||||
const auto& currentConvInfo = accInfo.conversationModel.get()->getConversationForUid(
|
||||
lrcInstance_->get_selectedConvUid());
|
||||
if (callId != currentConvInfo->get().callId && callId != currentConvInfo->get().confId) {
|
||||
|
@ -191,6 +194,7 @@ CallAdapter::onParticipantRemoved(const QString& callId, int index)
|
|||
try {
|
||||
if (lrcInstance_->get_selectedConvUid().isEmpty())
|
||||
return;
|
||||
|
||||
const auto& currentConvInfo = accInfo.conversationModel.get()->getConversationForUid(
|
||||
lrcInstance_->get_selectedConvUid());
|
||||
if (callId != currentConvInfo->get().callId && callId != currentConvInfo->get().confId) {
|
||||
|
@ -223,6 +227,27 @@ CallAdapter::onParticipantUpdated(const QString& callId, int index)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
CallAdapter::onCallStarted(const QString& callId)
|
||||
{
|
||||
if (lrcInstance_->get_selectedConvUid().isEmpty())
|
||||
return;
|
||||
auto& accInfo = lrcInstance_->accountModel().getAccountInfo(accountId_);
|
||||
auto& callModel = accInfo.callModel;
|
||||
// update call Information list by adding the new information related to the callId
|
||||
callInformationListModel_->addElement(
|
||||
qMakePair(callId, callModel->advancedInformationForCallId(callId)));
|
||||
}
|
||||
|
||||
void
|
||||
CallAdapter::onCallEnded(const QString& callId)
|
||||
{
|
||||
if (lrcInstance_->get_selectedConvUid().isEmpty())
|
||||
return;
|
||||
// update call Information list by removing information related to the callId
|
||||
callInformationListModel_->removeElement(callId);
|
||||
}
|
||||
|
||||
void
|
||||
CallAdapter::onCallStatusChanged(const QString& callId, int code)
|
||||
{
|
||||
|
@ -570,7 +595,6 @@ CallAdapter::showNotification(const QString& accountId, const QString& convUid)
|
|||
{
|
||||
auto& accInfo = lrcInstance_->getAccountInfo(accountId);
|
||||
auto title = accInfo.conversationModel->title(convUid);
|
||||
auto to = lrcInstance_->accountModel().bestNameForAccount(accountId);
|
||||
|
||||
auto preferences = accInfo.conversationModel->getConversationPreferences(convUid);
|
||||
// Ignore notifications for this conversation
|
||||
|
@ -581,7 +605,7 @@ CallAdapter::showNotification(const QString& accountId, const QString& convUid)
|
|||
auto convAvatar = Utils::conversationAvatar(lrcInstance_, convUid, QSize(50, 50), accountId);
|
||||
auto notifId = QString("%1;%2").arg(accountId).arg(convUid);
|
||||
systemTray_->showNotification(notifId,
|
||||
tr("%1 incoming call").arg(to),
|
||||
tr("Incoming call"),
|
||||
tr("%1 is calling you").arg(title),
|
||||
NotificationType::CALL,
|
||||
Utils::QImageToByteArray(convAvatar));
|
||||
|
@ -620,6 +644,18 @@ CallAdapter::connectCallModel(const QString& accountId)
|
|||
&CallAdapter::onParticipantUpdated,
|
||||
Qt::UniqueConnection);
|
||||
|
||||
connect(accInfo.callModel.get(),
|
||||
&CallModel::callStarted,
|
||||
this,
|
||||
&CallAdapter::onCallStarted,
|
||||
Qt::UniqueConnection);
|
||||
|
||||
connect(accInfo.callModel.get(),
|
||||
&CallModel::callEnded,
|
||||
this,
|
||||
&CallAdapter::onCallEnded,
|
||||
Qt::UniqueConnection);
|
||||
|
||||
connect(accInfo.callModel.get(),
|
||||
&CallModel::callStatusChanged,
|
||||
this,
|
||||
|
@ -1071,13 +1107,39 @@ CallAdapter::getCallDurationTime(const QString& accountId, const QString& convUi
|
|||
return QString();
|
||||
}
|
||||
|
||||
void
|
||||
CallAdapter::resetCallInfo()
|
||||
{
|
||||
callInformationListModel_->reset();
|
||||
}
|
||||
|
||||
void
|
||||
CallAdapter::setCallInfo()
|
||||
{
|
||||
try {
|
||||
auto& callModel = lrcInstance_->accountModel().getAccountInfo(accountId_).callModel;
|
||||
for (auto callId : callModel->getCallIds()) {
|
||||
callInformationListModel_->addElement(
|
||||
qMakePair(callId, callModel->advancedInformationForCallId(callId)));
|
||||
}
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
qWarning() << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CallAdapter::updateAdvancedInformation()
|
||||
{
|
||||
try {
|
||||
auto& callModel = lrcInstance_->accountModel().getAccountInfo(accountId_).callModel;
|
||||
if (callModel)
|
||||
set_callInformation(QVariantList::fromList(callModel->getAdvancedInformation()));
|
||||
for (auto callId : callModel->getCallIds()) {
|
||||
if (!callInformationListModel_->addElement(
|
||||
qMakePair(callId, callModel->advancedInformationForCallId(callId)))) {
|
||||
callInformationListModel_->editElement(
|
||||
qMakePair(callId, callModel->advancedInformationForCallId(callId)));
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
qWarning() << e.what();
|
||||
}
|
||||
|
|
|
@ -31,13 +31,15 @@
|
|||
#include <QVariant>
|
||||
#include <QSystemTrayIcon>
|
||||
|
||||
#include "callInformationListModel.h"
|
||||
|
||||
class SystemTray;
|
||||
|
||||
class CallAdapter final : public QmlAdapterBase
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_PROPERTY(bool, hasCall)
|
||||
QML_RO_PROPERTY(QVariantList, callInformation)
|
||||
QML_RO_PROPERTY(QVariant, callInformationList)
|
||||
|
||||
public:
|
||||
QTimer* timer;
|
||||
|
@ -92,6 +94,8 @@ public:
|
|||
const QString& accountId = {},
|
||||
bool forceCallOnly = false);
|
||||
Q_INVOKABLE QString getCallDurationTime(const QString& accountId, const QString& convUid);
|
||||
Q_INVOKABLE void resetCallInfo();
|
||||
Q_INVOKABLE void setCallInfo();
|
||||
Q_INVOKABLE void updateAdvancedInformation();
|
||||
|
||||
Q_SIGNALS:
|
||||
|
@ -112,6 +116,8 @@ public Q_SLOTS:
|
|||
void onParticipantAdded(const QString& callId, int index);
|
||||
void onParticipantRemoved(const QString& callId, int index);
|
||||
void onParticipantUpdated(const QString& callId, int index);
|
||||
void onCallStarted(const QString& callId);
|
||||
void onCallEnded(const QString& callId);
|
||||
|
||||
private:
|
||||
void showNotification(const QString& accountId, const QString& convUid);
|
||||
|
@ -126,4 +132,6 @@ private:
|
|||
QScopedPointer<CallOverlayModel> overlayModel_;
|
||||
QScopedPointer<CallParticipantsModel> participantsModel_;
|
||||
VectorString currentConfSubcalls_;
|
||||
|
||||
std::unique_ptr<CallInformationListModel> callInformationListModel_;
|
||||
};
|
||||
|
|
|
@ -299,6 +299,19 @@ Item {
|
|||
property string raiseHand: qsTr("Raise hand")
|
||||
property string layoutSettings: qsTr("Layout settings")
|
||||
|
||||
//advanced information
|
||||
property string renderersInformation: qsTr("Renderers information")
|
||||
property string callInformation: qsTr("Call information")
|
||||
property string peerNumber: qsTr("Peer number")
|
||||
property string callId: qsTr("Call id")
|
||||
property string sockets: qsTr("Sockets")
|
||||
property string videoCodec: qsTr("Video codec")
|
||||
property string hardwareAcceleration: qsTr("Hardware acceleration")
|
||||
property string videoBitrate: qsTr("Video bitrate")
|
||||
property string audioCodec: qsTr("Audio codec")
|
||||
property string rendererId: qsTr("Renderer id")
|
||||
property string fps_short: qsTr("Fps")
|
||||
|
||||
// Share location/position
|
||||
property string shareLocation: qsTr("Share location")
|
||||
property string stopSharingLocation: qsTr("Stop sharing")
|
||||
|
|
|
@ -376,9 +376,11 @@ Item {
|
|||
//Call information
|
||||
property real textFontPointSize: calcSize(10)
|
||||
property real titleFontPointSize: calcSize(13)
|
||||
property color callInfoColor: chatviewTextColor
|
||||
property color callInfoColor: whiteColor
|
||||
property int callInformationElementsSpacing: 5
|
||||
property int callInformationBlockSpacing: 25
|
||||
property int callInformationlayoutMargins: 10
|
||||
|
||||
|
||||
// Jami switch
|
||||
property real switchIndicatorRadius: 30
|
||||
|
|
255
src/app/mainview/components/CallInformationOverlay.qml
Normal file
255
src/app/mainview/components/CallInformationOverlay.qml
Normal file
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
* Copyright (C) 2022 Savoir-faire Linux Inc.
|
||||
* Author: Nicolas Vengeon <nicolas.vengeon@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls
|
||||
|
||||
import net.jami.Models 1.1
|
||||
import net.jami.Adapters 1.1
|
||||
import net.jami.Constants 1.1
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
import "../../commoncomponents"
|
||||
|
||||
Popup {
|
||||
id: root
|
||||
|
||||
property real maxHeight: parent.height * 40 / 100
|
||||
property real maxTextWidth: parent.width * 30 / 100
|
||||
|
||||
property var advancedList
|
||||
property var fps
|
||||
|
||||
width: container.width
|
||||
height: container.height
|
||||
closePolicy: Popup.NoAutoClosed
|
||||
|
||||
onClosed: {
|
||||
CallAdapter.stopTimerInformation()
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
AvAdapter.resetRendererInfo()
|
||||
CallAdapter.resetCallInfo()
|
||||
CallAdapter.setCallInfo()
|
||||
AvAdapter.setRendererInfo()
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: JamiTheme.transparentColor
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: container
|
||||
|
||||
color: JamiTheme.blackColor
|
||||
opacity: 0.85
|
||||
radius: 10
|
||||
width: windowContent.width
|
||||
height: windowContent.height
|
||||
|
||||
PushButton {
|
||||
id: closeButton
|
||||
|
||||
anchors.top: container.top
|
||||
anchors.topMargin: 5
|
||||
anchors.right: container.right
|
||||
anchors.rightMargin: 5
|
||||
normalColor: JamiTheme.transparentColor
|
||||
imageColor: JamiTheme.callInfoColor
|
||||
source: JamiResources.round_close_24dp_svg
|
||||
circled: false
|
||||
toolTipText: JamiStrings.close
|
||||
|
||||
onClicked: {
|
||||
root.close()
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: windowContent
|
||||
|
||||
ColumnLayout {
|
||||
spacing: JamiTheme.callInformationBlockSpacing
|
||||
Layout.margins: JamiTheme.callInformationlayoutMargins
|
||||
Layout.preferredWidth: callInfoListview.width
|
||||
Layout.alignment: Qt.AlignTop
|
||||
|
||||
Text{
|
||||
id: textTest
|
||||
color: JamiTheme.callInfoColor
|
||||
text: JamiStrings.callInformation
|
||||
font.pointSize: JamiTheme.titleFontPointSize
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: callInfoListview
|
||||
|
||||
model: advancedList
|
||||
Layout.preferredWidth: root.maxTextWidth
|
||||
Layout.preferredHeight: contentItem.childrenRect.height < root.maxHeight ? contentItem.childrenRect.height : root.maxHeight
|
||||
spacing: JamiTheme.callInformationBlockSpacing
|
||||
clip: true
|
||||
|
||||
delegate: Column {
|
||||
spacing: JamiTheme.callInformationElementsSpacing
|
||||
|
||||
Text {
|
||||
color: JamiTheme.callInfoColor
|
||||
text: JamiStrings.callId + ": " + CALL_ID
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: callInfoListview.width
|
||||
}
|
||||
|
||||
Text {
|
||||
function stringWithoutRing(peerNumber){
|
||||
return peerNumber.replace("@ring.dht","") ;
|
||||
}
|
||||
color: JamiTheme.callInfoColor
|
||||
text: JamiStrings.peerNumber + ": " + stringWithoutRing(PEER_NUMBER)
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: callInfoListview.width
|
||||
}
|
||||
Column {
|
||||
id: socketLayout
|
||||
|
||||
property bool showAll: false
|
||||
width: callInfoListview.width
|
||||
|
||||
RowLayout {
|
||||
Text {
|
||||
color: JamiTheme.callInfoColor
|
||||
text: JamiStrings.sockets
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: socketLayout.width
|
||||
}
|
||||
|
||||
PushButton {
|
||||
source: socketLayout.showAll ? JamiResources.expand_less_24dp_svg : JamiResources.expand_more_24dp_svg
|
||||
normalColor: JamiTheme.transparentColor
|
||||
Layout.preferredWidth: 20
|
||||
Layout.preferredHeight: 20
|
||||
imageColor: JamiTheme.callInfoColor
|
||||
onClicked: {
|
||||
socketLayout.showAll = !socketLayout.showAll
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
color: JamiTheme.callInfoColor
|
||||
text: SOCKETS
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
visible: socketLayout.showAll
|
||||
width: socketLayout.width
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
color: JamiTheme.callInfoColor
|
||||
text: JamiStrings.videoCodec + ": " + VIDEO_CODEC
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: callInfoListview.width
|
||||
}
|
||||
|
||||
Text {
|
||||
color: JamiTheme.callInfoColor
|
||||
text: JamiStrings.audioCodec + ": " + AUDIO_CODEC + " " + AUDIO_SAMPLE_RATE + " Hz"
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: callInfoListview.width
|
||||
}
|
||||
|
||||
Text {
|
||||
color: JamiTheme.callInfoColor
|
||||
text: JamiStrings.hardwareAcceleration + ": " + HARDWARE_ACCELERATION
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: callInfoListview.width
|
||||
}
|
||||
|
||||
Text {
|
||||
color: JamiTheme.callInfoColor
|
||||
text: JamiStrings.videoBitrate + ": " + VIDEO_BITRATE + " bps"
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: callInfoListview.width
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
spacing: JamiTheme.callInformationBlockSpacing
|
||||
Layout.margins: JamiTheme.callInformationlayoutMargins
|
||||
Layout.preferredWidth: renderersInfoListview.width
|
||||
Layout.alignment: Qt.AlignTop
|
||||
|
||||
Text {
|
||||
color: JamiTheme.callInfoColor
|
||||
text: JamiStrings.renderersInformation
|
||||
font.pointSize: JamiTheme.titleFontPointSize
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: renderersInfoListview
|
||||
|
||||
Layout.preferredWidth: root.maxTextWidth
|
||||
Layout.preferredHeight: contentItem.childrenRect.height < root.maxHeight ? contentItem.childrenRect.height : root.maxHeight
|
||||
spacing: JamiTheme.callInformationBlockSpacing
|
||||
model: fps
|
||||
clip: true
|
||||
|
||||
delegate: Column {
|
||||
spacing: JamiTheme.callInformationElementsSpacing
|
||||
|
||||
Text{
|
||||
color: JamiTheme.callInfoColor
|
||||
text: JamiStrings.rendererId + ": " + RENDERER_ID
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: renderersInfoListview.width
|
||||
}
|
||||
|
||||
Text {
|
||||
id: testText
|
||||
color: JamiTheme.callInfoColor
|
||||
text: JamiStrings.fps_short + ": " + FPS
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: renderersInfoListview.width
|
||||
}
|
||||
|
||||
Text {
|
||||
color: JamiTheme.callInfoColor
|
||||
text: JamiStrings.resolution + ": " + RES
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: renderersInfoListview.width
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,213 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2022 Savoir-faire Linux Inc.
|
||||
* Author: Nicolas Vengeon <nicolas.vengeon@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Controls
|
||||
|
||||
import net.jami.Models 1.1
|
||||
import net.jami.Adapters 1.1
|
||||
import net.jami.Constants 1.1
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
import "../../commoncomponents"
|
||||
|
||||
Window {
|
||||
id: root
|
||||
|
||||
width: parent.width * 2 / 3
|
||||
height: parent.height * 2 / 3
|
||||
property var advancedList
|
||||
property var fps
|
||||
|
||||
onClosing: {
|
||||
CallAdapter.stopTimerInformation()
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: container
|
||||
|
||||
anchors.fill: parent
|
||||
color: JamiTheme.secondaryBackgroundColor
|
||||
|
||||
RowLayout {
|
||||
id: windowContent
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
ColumnLayout {
|
||||
spacing: JamiTheme.callInformationBlockSpacing
|
||||
|
||||
Text{
|
||||
color: JamiTheme.callInfoColor
|
||||
text: "Call information"
|
||||
font.pointSize: JamiTheme.titleFontPointSize
|
||||
}
|
||||
|
||||
Item {
|
||||
id: itemCallInformation
|
||||
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
clip: true
|
||||
|
||||
ListView {
|
||||
model: advancedList
|
||||
width: parent.width
|
||||
height: root.height
|
||||
spacing: JamiTheme.callInformationBlockSpacing
|
||||
|
||||
delegate: Column {
|
||||
spacing: JamiTheme.callInformationElementsSpacing
|
||||
|
||||
Text {
|
||||
color: JamiTheme.callInfoColor
|
||||
text: "Call id: " + modelData.CALL_ID
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: itemCallInformation.width
|
||||
}
|
||||
|
||||
Text {
|
||||
color: JamiTheme.callInfoColor
|
||||
text: "Video codec: " + modelData.VIDEO_CODEC
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: itemCallInformation.width
|
||||
}
|
||||
|
||||
Text {
|
||||
color: JamiTheme.callInfoColor
|
||||
text: "Audio codec: " + modelData.AUDIO_CODEC
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: itemCallInformation.width
|
||||
}
|
||||
|
||||
Text {
|
||||
function stringWithoutRing(peerNumber){
|
||||
return peerNumber.replace("@ring.dht","") ;
|
||||
}
|
||||
color: JamiTheme.callInfoColor
|
||||
text: "PEER_NUMBER: " + stringWithoutRing(modelData.PEER_NUMBER)
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: itemCallInformation.width
|
||||
}
|
||||
|
||||
Text {
|
||||
color: JamiTheme.callInfoColor
|
||||
text: "Hardware acceleration: " + modelData.HARDWARE_ACCELERATION
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: itemCallInformation.width
|
||||
}
|
||||
|
||||
Text {
|
||||
color: JamiTheme.callInfoColor
|
||||
text: "Video min bitrate: " + modelData.VIDEO_MIN_BITRATE
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: itemCallInformation.width
|
||||
}
|
||||
|
||||
Text {
|
||||
color: JamiTheme.callInfoColor
|
||||
text: "Video max bitrate: " + modelData.VIDEO_MAX_BITRATE
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: itemCallInformation.width
|
||||
}
|
||||
|
||||
Text {
|
||||
color: JamiTheme.callInfoColor
|
||||
text: "Video bitrate: " + modelData.VIDEO_BITRATE
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: itemCallInformation.width
|
||||
}
|
||||
|
||||
Text {
|
||||
color: JamiTheme.callInfoColor
|
||||
text: "Sockets: " + modelData.SOCKETS
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: itemCallInformation.width
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
spacing: JamiTheme.callInformationBlockSpacing
|
||||
|
||||
Text {
|
||||
color: JamiTheme.callInfoColor
|
||||
text: "Renderers information"
|
||||
font.pointSize: JamiTheme.titleFontPointSize
|
||||
}
|
||||
|
||||
Item {
|
||||
id: itemParticipantInformation
|
||||
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
clip: true
|
||||
|
||||
|
||||
ListView {
|
||||
width: parent.width
|
||||
height: root.height
|
||||
spacing: JamiTheme.callInformationBlockSpacing
|
||||
model: fps
|
||||
|
||||
delegate: Column {
|
||||
spacing: JamiTheme.callInformationElementsSpacing
|
||||
|
||||
Text{
|
||||
color: JamiTheme.callInfoColor
|
||||
text: "Renderer id: " + modelData.ID
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: itemParticipantInformation.width
|
||||
}
|
||||
|
||||
Text {
|
||||
color: JamiTheme.callInfoColor
|
||||
text: "Fps: " + modelData.FPS
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: itemParticipantInformation.width
|
||||
}
|
||||
|
||||
Text {
|
||||
color: JamiTheme.callInfoColor
|
||||
text: "Resolution: " + modelData.RES
|
||||
font.pointSize: JamiTheme.textFontPointSize
|
||||
wrapMode: Text.WrapAnywhere
|
||||
width: itemParticipantInformation.width
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -46,7 +46,7 @@ Item {
|
|||
SelectScreenWindowCreation.destroySelectScreenWindow()
|
||||
ScreenRubberBandCreation.destroyScreenRubberBandWindow()
|
||||
PluginHandlerPickerCreation.closePluginHandlerPicker()
|
||||
callInformationWindow.close()
|
||||
callInformationOverlay.close()
|
||||
}
|
||||
|
||||
// x, y position does not need to be translated
|
||||
|
@ -71,12 +71,16 @@ Item {
|
|||
y: root.height / 2 - sipInputPanel.height / 2
|
||||
}
|
||||
|
||||
CallInformationWindow {
|
||||
id: callInformationWindow
|
||||
CallInformationOverlay {
|
||||
id: callInformationOverlay
|
||||
|
||||
visible: false
|
||||
advancedList: CallAdapter.callInformation
|
||||
advancedList: CallAdapter.callInformationList
|
||||
fps: AvAdapter.renderersInfoList
|
||||
|
||||
Component.onDestruction: {
|
||||
CallAdapter.stopTimerInformation();
|
||||
}
|
||||
}
|
||||
|
||||
JamiFileDialog {
|
||||
|
|
|
@ -192,7 +192,7 @@ ContextMenuAutoLoader {
|
|||
|
||||
onClicked: {
|
||||
CallAdapter.startTimerInformation();
|
||||
callInformationWindow.show()
|
||||
callInformationOverlay.open()
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
#include "smartlistmodel.h"
|
||||
#include "conversationlistmodelbase.h"
|
||||
#include "filestosendlistmodel.h"
|
||||
#include "callInformationListModel.h"
|
||||
#include "rendererinformationlistmodel.h"
|
||||
|
||||
#include "qrimageprovider.h"
|
||||
#include "avatarimageprovider.h"
|
||||
|
@ -170,6 +172,9 @@ registerTypes(QQmlEngine* engine,
|
|||
QML_REGISTERTYPE(NS_MODELS, FilesToSendListModel);
|
||||
QML_REGISTERTYPE(NS_MODELS, SmartListModel);
|
||||
QML_REGISTERTYPE(NS_MODELS, MessageListModel);
|
||||
QML_REGISTERTYPE(NS_MODELS, CallInformationListModel);
|
||||
QML_REGISTERTYPE(NS_MODELS, RendererInformationListModel);
|
||||
|
||||
|
||||
// Roles & type enums for models
|
||||
QML_REGISTERNAMESPACE(NS_MODELS, AccountList::staticMetaObject, "AccountList");
|
||||
|
|
|
@ -261,6 +261,8 @@ set(LIBCLIENT_SOURCES
|
|||
behaviorcontroller.cpp
|
||||
datatransfermodel.cpp
|
||||
messagelistmodel.cpp
|
||||
callInformationListModel.cpp
|
||||
rendererinformationlistmodel.cpp
|
||||
|
||||
# communication
|
||||
dbus/configurationmanager.cpp
|
||||
|
@ -289,6 +291,8 @@ set(LIBCLIENT_HEADERS
|
|||
vcard.h
|
||||
namedirectory.h
|
||||
messagelistmodel.h
|
||||
callInformationListModel.h
|
||||
rendererinformationlistmodel.h
|
||||
|
||||
# interfaces
|
||||
interfaces/pixmapmanipulatori.h
|
||||
|
|
|
@ -276,17 +276,22 @@ public:
|
|||
QSize getRendererSize(const QString& id);
|
||||
video::Frame getRendererFrame(const QString& id);
|
||||
bool useDirectRenderer() const;
|
||||
/**
|
||||
* Get Renderers information
|
||||
* @param id (optional) : for a specific renderer or for all renderers
|
||||
*/
|
||||
QList<MapStringString> getRenderersInfo(QString id = {});
|
||||
/**
|
||||
* Update renderers information list
|
||||
*/
|
||||
Q_SLOT void updateRenderersInfo();
|
||||
Q_SLOT void updateRenderersFPSInfo(QString rendererId);
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* Emitted after an update of renderers information
|
||||
* @param renderersInfoList Information on all renderers (RES, ID, FPS)
|
||||
* Emitted after an update of renderer's fps
|
||||
* @param pair of renderer id and its fps value
|
||||
*/
|
||||
void onRendererInfosUpdated(QVariantList renderersInfoList);
|
||||
void onRendererFpsChange(QPair<QString, QString> fpsInfo);
|
||||
/**
|
||||
* Emitted when a renderer is started
|
||||
* @param id of the renderer
|
||||
|
|
|
@ -397,6 +397,10 @@ public:
|
|||
*/
|
||||
QList<QVariant> getAdvancedInformation() const;
|
||||
|
||||
MapStringString advancedInformationForCallId(QString callId) const;
|
||||
|
||||
QStringList getCallIds() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
/**
|
||||
|
|
|
@ -173,21 +173,36 @@ AVModel::~AVModel()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
AVModel::updateRenderersInfo()
|
||||
QList<MapStringString>
|
||||
AVModel::getRenderersInfo(QString id)
|
||||
{
|
||||
QVariantList renderersInfoList;
|
||||
|
||||
QList<MapStringString> infoList;
|
||||
std::lock_guard<std::mutex> lk(pimpl_->renderers_mtx_);
|
||||
for (auto r = pimpl_->renderers_.begin(); r != pimpl_->renderers_.end(); r++) {
|
||||
QVariantMap qmap;
|
||||
MapStringString qmap;
|
||||
auto& rend = r->second;
|
||||
MapStringString mapInfo = rend->getInfos();
|
||||
qmap.insert(rend->RES, mapInfo["RES"]);
|
||||
qmap.insert(rend->ID, mapInfo["ID"]);
|
||||
qmap.insert(rend->FPS, mapInfo["FPS"]);
|
||||
renderersInfoList.append(qmap);
|
||||
if (id.isEmpty() || mapInfo["RENDERER_ID"] == id) {
|
||||
qmap.insert(rend->RES, mapInfo["RES"]);
|
||||
qmap.insert(rend->RENDERER_ID, mapInfo["RENDERER_ID"]);
|
||||
qmap.insert(rend->FPS, mapInfo["FPS"]);
|
||||
infoList.append(qmap);
|
||||
}
|
||||
}
|
||||
Q_EMIT onRendererInfosUpdated(renderersInfoList);
|
||||
return infoList;
|
||||
return {};
|
||||
}
|
||||
|
||||
void
|
||||
AVModel::updateRenderersFPSInfo(QString rendererId)
|
||||
{
|
||||
auto it = std::find_if(pimpl_->renderers_.begin(),
|
||||
pimpl_->renderers_.end(),
|
||||
[&rendererId](const auto& c) {
|
||||
return rendererId == c.second->getInfos()["RENDERER_ID"];
|
||||
});
|
||||
if (it != pimpl_->renderers_.end())
|
||||
Q_EMIT onRendererFpsChange(qMakePair(rendererId, it->second->getInfos()["FPS"]));
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -925,7 +940,7 @@ AVModelPimpl::addRenderer(const QString& id, const QSize& res, const QString& sh
|
|||
renderer,
|
||||
&Renderer::fpsChanged,
|
||||
this,
|
||||
[this, id](void) { Q_EMIT linked_.updateRenderersInfo(); },
|
||||
[this, id](void) { Q_EMIT linked_.updateRenderersFPSInfo(id); },
|
||||
Qt::DirectConnection);
|
||||
connect(
|
||||
renderer,
|
||||
|
|
114
src/libclient/callInformationListModel.cpp
Normal file
114
src/libclient/callInformationListModel.cpp
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright (C) 2023 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Nicolas Vengeon <nicolas.vengeon@savoirfairelinux.com>
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "callInformationListModel.h"
|
||||
|
||||
CallInformationListModel::CallInformationListModel(QObject* parent)
|
||||
: QAbstractListModel(parent)
|
||||
{}
|
||||
|
||||
int
|
||||
CallInformationListModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return callsInfolist_.size();
|
||||
}
|
||||
|
||||
QVariant
|
||||
CallInformationListModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
using namespace InfoList;
|
||||
if (role == Role::CALL_ID)
|
||||
return callsInfolist_[index.row()].first;
|
||||
switch (role) {
|
||||
#define X(var) \
|
||||
case Role::var: \
|
||||
return callsInfolist_[index.row()].second[#var];
|
||||
CALLINFO_ROLES
|
||||
#undef X
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool
|
||||
CallInformationListModel::addElement(QPair<QString, MapStringString> callInfo)
|
||||
{
|
||||
// check element existence
|
||||
auto callId = callInfo.first;
|
||||
auto it = std::find_if(callsInfolist_.begin(), callsInfolist_.end(), [&callId](const auto& c) {
|
||||
return callId == c.first;
|
||||
});
|
||||
// if element doesn't exist
|
||||
if (it == callsInfolist_.end()) {
|
||||
beginInsertRows(QModelIndex(), rowCount(), rowCount());
|
||||
callsInfolist_.append(callInfo);
|
||||
endInsertRows();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
CallInformationListModel::editElement(QPair<QString, MapStringString> callInfo)
|
||||
{
|
||||
auto it = std::find_if(callsInfolist_.begin(),
|
||||
callsInfolist_.end(),
|
||||
[&callInfo](const auto& c) { return callInfo.first == c.first; });
|
||||
if (it != callsInfolist_.end()) {
|
||||
// update infos
|
||||
auto index = std::distance(callsInfolist_.begin(), it);
|
||||
QModelIndex modelIndex = QAbstractListModel::index(index, 0);
|
||||
it->second = callInfo.second;
|
||||
Q_EMIT dataChanged(modelIndex, modelIndex);
|
||||
}
|
||||
}
|
||||
|
||||
QHash<int, QByteArray>
|
||||
CallInformationListModel::roleNames() const
|
||||
{
|
||||
using namespace InfoList;
|
||||
QHash<int, QByteArray> roles;
|
||||
#define X(var) roles[var] = #var;
|
||||
CALLINFO_ROLES
|
||||
#undef X
|
||||
return roles;
|
||||
}
|
||||
|
||||
void
|
||||
CallInformationListModel::reset()
|
||||
{
|
||||
beginResetModel();
|
||||
callsInfolist_.clear();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void
|
||||
CallInformationListModel::removeElement(QString callId)
|
||||
{
|
||||
auto it = std::find_if(callsInfolist_.begin(), callsInfolist_.end(), [&callId](const auto& c) {
|
||||
return callId == c.first;
|
||||
});
|
||||
if (it != callsInfolist_.end()) {
|
||||
auto elementIndex = std::distance(callsInfolist_.begin(), it);
|
||||
beginRemoveRows(QModelIndex(), elementIndex, elementIndex);
|
||||
callsInfolist_.remove(elementIndex);
|
||||
endRemoveRows();
|
||||
}
|
||||
}
|
68
src/libclient/callInformationListModel.h
Normal file
68
src/libclient/callInformationListModel.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (C) 2023 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Nicolas Vengeon <nicolas.vengeon@savoirfairelinux.com>
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "api/interaction.h"
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
#define CALLINFO_ROLES \
|
||||
X(CALL_ID) \
|
||||
X(PEER_NUMBER) \
|
||||
X(SOCKETS) \
|
||||
X(VIDEO_CODEC) \
|
||||
X(AUDIO_CODEC) \
|
||||
X(AUDIO_SAMPLE_RATE) \
|
||||
X(HARDWARE_ACCELERATION) \
|
||||
X(VIDEO_BITRATE)
|
||||
|
||||
namespace InfoList {
|
||||
|
||||
Q_NAMESPACE
|
||||
enum Role {
|
||||
DummyRole = Qt::UserRole + 1,
|
||||
#define X(role) role,
|
||||
CALLINFO_ROLES
|
||||
#undef X
|
||||
};
|
||||
Q_ENUM_NS(Role)
|
||||
} // namespace InfoList
|
||||
|
||||
class CallInformationListModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CallInformationListModel(QObject* parent = 0);
|
||||
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
Q_INVOKABLE QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
bool addElement(QPair<QString, MapStringString> callInfo);
|
||||
void editElement(QPair<QString, MapStringString> callInfo);
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
void reset();
|
||||
void removeElement(QString callId);
|
||||
|
||||
protected:
|
||||
using Role = InfoList::Role;
|
||||
|
||||
private:
|
||||
QList<QPair<QString, MapStringString>> callsInfolist_;
|
||||
};
|
|
@ -24,6 +24,8 @@
|
|||
#include "api/avmodel.h"
|
||||
#include "api/behaviorcontroller.h"
|
||||
#include "api/conversationmodel.h"
|
||||
#include "api/codecmodel.h"
|
||||
|
||||
#include "api/contact.h"
|
||||
#include "api/contactmodel.h"
|
||||
#include "api/pluginmodel.h"
|
||||
|
@ -56,6 +58,7 @@
|
|||
using namespace libjami::Media;
|
||||
|
||||
constexpr static const char HARDWARE_ACCELERATION[] = "HARDWARE_ACCELERATION";
|
||||
constexpr static const char AUDIO_CODEC[] = "AUDIO_CODEC";
|
||||
constexpr static const char CALL_ID[] = "CALL_ID";
|
||||
|
||||
static std::uniform_int_distribution<int> dis {0, std::numeric_limits<int>::max()};
|
||||
|
@ -133,6 +136,9 @@ public:
|
|||
~CallModelPimpl();
|
||||
|
||||
QVariantList callAdvancedInformation();
|
||||
MapStringString advancedInformationForCallId(QString callId);
|
||||
|
||||
QStringList getCallIds();
|
||||
|
||||
/**
|
||||
* Send the profile VCard into a call
|
||||
|
@ -389,7 +395,7 @@ CallModel::createCall(const QString& uri, bool isAudioOnly, VectorMapStringStrin
|
|||
}
|
||||
#ifdef ENABLE_LIBWRAP
|
||||
auto callId = CallManager::instance().placeCallWithMedia(owner.id, uri, mediaList);
|
||||
#else // dbus
|
||||
#else // dbus
|
||||
// do not use auto here (QDBusPendingReply<QString>)
|
||||
QString callId = CallManager::instance().placeCallWithMedia(owner.id, uri, mediaList);
|
||||
#endif // ENABLE_LIBWRAP
|
||||
|
@ -419,6 +425,18 @@ CallModel::getAdvancedInformation() const
|
|||
return pimpl_->callAdvancedInformation();
|
||||
}
|
||||
|
||||
MapStringString
|
||||
CallModel::advancedInformationForCallId(QString callId) const
|
||||
{
|
||||
return pimpl_->advancedInformationForCallId(callId);
|
||||
}
|
||||
|
||||
QStringList
|
||||
CallModel::getCallIds() const
|
||||
{
|
||||
return pimpl_->getCallIds();
|
||||
}
|
||||
|
||||
void
|
||||
CallModel::emplaceConversationConference(const QString& confId)
|
||||
{
|
||||
|
@ -1026,6 +1044,23 @@ CallModelPimpl::callAdvancedInformation()
|
|||
return advancedInformationList;
|
||||
}
|
||||
|
||||
MapStringString
|
||||
CallModelPimpl::advancedInformationForCallId(QString callId)
|
||||
{
|
||||
MapStringString infoMap = CallManager::instance().getCallDetails(linked.owner.id, callId);
|
||||
if (lrc.getAVModel().getHardwareAcceleration())
|
||||
infoMap[HARDWARE_ACCELERATION] = "True";
|
||||
else
|
||||
infoMap[HARDWARE_ACCELERATION] = "False";
|
||||
return infoMap;
|
||||
}
|
||||
|
||||
QStringList
|
||||
CallModelPimpl::getCallIds()
|
||||
{
|
||||
return CallManager::instance().getCallList(linked.owner.id);
|
||||
}
|
||||
|
||||
void
|
||||
CallModelPimpl::initCallFromDaemon()
|
||||
{
|
||||
|
|
|
@ -62,7 +62,7 @@ MapStringString
|
|||
Renderer::getInfos() const
|
||||
{
|
||||
MapStringString map;
|
||||
map[ID] = id();
|
||||
map[RENDERER_ID] = id();
|
||||
map[FPS] = QString::number(fps());
|
||||
map[RES] = QString::number(size().width()) + " * " + QString::number(size().height());
|
||||
return map;
|
||||
|
|
|
@ -36,7 +36,7 @@ class Renderer : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
constexpr static const char ID[] = "ID";
|
||||
constexpr static const char RENDERER_ID[] = "RENDERER_ID";
|
||||
constexpr static const char FPS[] = "FPS";
|
||||
constexpr static const char RES[] = "RES";
|
||||
constexpr static const int FPS_RATE_SEC = 1;
|
||||
|
|
114
src/libclient/rendererinformationlistmodel.cpp
Normal file
114
src/libclient/rendererinformationlistmodel.cpp
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright (C) 2023 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Nicolas Vengeon <nicolas.vengeon@savoirfairelinux.com>
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "rendererinformationlistmodel.h"
|
||||
|
||||
RendererInformationListModel::RendererInformationListModel(QObject* parent)
|
||||
: QAbstractListModel(parent)
|
||||
{}
|
||||
|
||||
int
|
||||
RendererInformationListModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return renderersInfoList_.size();
|
||||
}
|
||||
|
||||
QVariant
|
||||
RendererInformationListModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
using namespace RendererInfoList;
|
||||
|
||||
if (role == Role::RENDERER_ID)
|
||||
return renderersInfoList_[index.row()].first;
|
||||
|
||||
switch (role) {
|
||||
#define X(var) \
|
||||
case Role::var: \
|
||||
return renderersInfoList_[index.row()].second[#var];
|
||||
RENDERERINFO_ROLES
|
||||
#undef X
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void
|
||||
RendererInformationListModel::updateFps(QString rendererId, QString fps)
|
||||
{
|
||||
auto it = std::find_if(renderersInfoList_.begin(),
|
||||
renderersInfoList_.end(),
|
||||
[&rendererId](const auto& c) { return rendererId == c.first; });
|
||||
if (it != renderersInfoList_.end()) {
|
||||
// update fps
|
||||
auto index = std::distance(renderersInfoList_.begin(), it);
|
||||
QModelIndex modelIndex = QAbstractListModel::index(index, 0);
|
||||
it->second["FPS"] = fps;
|
||||
Q_EMIT dataChanged(modelIndex, modelIndex, {Role::FPS});
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RendererInformationListModel::addElement(QPair<QString, MapStringString> rendererInfo)
|
||||
{
|
||||
// check element existence
|
||||
auto rendererId = rendererInfo.first;
|
||||
auto it = std::find_if(renderersInfoList_.begin(),
|
||||
renderersInfoList_.end(),
|
||||
[&rendererId](const auto& c) { return rendererId == c.first; });
|
||||
// if element doesn't exist
|
||||
if (it == renderersInfoList_.end()) {
|
||||
beginInsertRows(QModelIndex(), rowCount(), rowCount());
|
||||
renderersInfoList_.append(rendererInfo);
|
||||
endInsertRows();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RendererInformationListModel::removeElement(QString rendererId)
|
||||
{
|
||||
auto it = std::find_if(renderersInfoList_.begin(),
|
||||
renderersInfoList_.end(),
|
||||
[&rendererId](const auto& c) { return rendererId == c.first; });
|
||||
if (it != renderersInfoList_.end()) {
|
||||
auto elementIndex = std::distance(renderersInfoList_.begin(), it);
|
||||
beginRemoveRows(QModelIndex(), elementIndex, elementIndex);
|
||||
renderersInfoList_.remove(elementIndex);
|
||||
endRemoveRows();
|
||||
}
|
||||
}
|
||||
|
||||
QHash<int, QByteArray>
|
||||
RendererInformationListModel::roleNames() const
|
||||
{
|
||||
using namespace RendererInfoList;
|
||||
QHash<int, QByteArray> roles;
|
||||
#define X(var) roles[var] = #var;
|
||||
RENDERERINFO_ROLES
|
||||
#undef X
|
||||
return roles;
|
||||
}
|
||||
|
||||
void
|
||||
RendererInformationListModel::reset()
|
||||
{
|
||||
beginResetModel();
|
||||
renderersInfoList_.clear();
|
||||
endResetModel();
|
||||
}
|
62
src/libclient/rendererinformationlistmodel.h
Normal file
62
src/libclient/rendererinformationlistmodel.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (C) 2023 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Nicolas Vengeon <nicolas.vengeon@savoirfairelinux.com>
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "api/interaction.h"
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
#define RENDERERINFO_ROLES \
|
||||
X(RENDERER_ID) \
|
||||
X(RES) \
|
||||
X(FPS)
|
||||
|
||||
namespace RendererInfoList {
|
||||
Q_NAMESPACE
|
||||
enum Role {
|
||||
DummyRole = Qt::UserRole + 1,
|
||||
#define X(role) role,
|
||||
RENDERERINFO_ROLES
|
||||
#undef X
|
||||
};
|
||||
Q_ENUM_NS(Role)
|
||||
} // namespace RendererInfoList
|
||||
|
||||
class RendererInformationListModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RendererInformationListModel(QObject* parent = 0);
|
||||
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
Q_INVOKABLE QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
void updateFps(QString rendererId, QString fps);
|
||||
void addElement(QPair<QString, MapStringString> rendererInfo);
|
||||
void removeElement(QString rendererId);
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
void reset();
|
||||
|
||||
protected:
|
||||
using Role = RendererInfoList::Role;
|
||||
|
||||
private:
|
||||
QList<QPair<QString, MapStringString>> renderersInfoList_;
|
||||
};
|
Loading…
Add table
Reference in a new issue