From 085b71bd76209e6ae5cc6ee305783187f48fbd6f Mon Sep 17 00:00:00 2001 From: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> Date: Thu, 4 Aug 2022 17:31:21 -0400 Subject: [PATCH] videodevices: replace C++ filter proxy model with QML-SFPM Change-Id: I348cd7acc4cccee4b5a6784cc2430156bb73667b --- .../commoncomponents/SettingParaCombobox.qml | 11 +- src/app/mainview/components/CallActionBar.qml | 9 +- .../settingsview/components/VideoSettings.qml | 57 ++++++- src/app/videodevices.cpp | 145 ++++-------------- src/app/videodevices.h | 64 ++------ 5 files changed, 99 insertions(+), 187 deletions(-) diff --git a/src/app/commoncomponents/SettingParaCombobox.qml b/src/app/commoncomponents/SettingParaCombobox.qml index 50215e63e..64e8eaac9 100644 --- a/src/app/commoncomponents/SettingParaCombobox.qml +++ b/src/app/commoncomponents/SettingParaCombobox.qml @@ -46,19 +46,16 @@ ComboBox { width: root.width contentItem: Text { - text: { - if (index >= 0) { - var currentItem = root.delegateModel.items.get(index) - return currentItem.model[root.textRole].toString() - } - return "" + if (index < 0) return '' + var currentItem = root.delegateModel.items.get(index) + const value = currentItem.model[root.textRole] + return value === undefined ? '' : value.toString() } color: hovered ? JamiTheme.comboboxTextColorHovered : JamiTheme.textColor elide: Text.ElideRight verticalAlignment: Text.AlignVCenter - } background: Rectangle { diff --git a/src/app/mainview/components/CallActionBar.qml b/src/app/mainview/components/CallActionBar.qml index f70faf8c9..6eecc9638 100644 --- a/src/app/mainview/components/CallActionBar.qml +++ b/src/app/mainview/components/CallActionBar.qml @@ -236,14 +236,9 @@ Control { id: videoInputMenuAction enabled: VideoDevices.listSize !== 0 text: JamiStrings.selectVideoDevice - property var listModel: VideoDevices.devicesSourceModel() + property var listModel: VideoDevices.deviceSourceModel function accept(index) { - if (VideoDevices.listSize < 1) - return - // TODO: change it when we can suppot showing default and - // current rendering device at the same time and - // start and stop preview logic in here should be in LRC - VideoDevices.setDefaultDevice(index, true) + VideoDevices.setDefaultDevice(index) } } ] diff --git a/src/app/settingsview/components/VideoSettings.qml b/src/app/settingsview/components/VideoSettings.qml index f03cfb257..2a8593986 100644 --- a/src/app/settingsview/components/VideoSettings.qml +++ b/src/app/settingsview/components/VideoSettings.qml @@ -21,6 +21,8 @@ import QtQuick.Controls import QtQuick.Layouts import Qt5Compat.GraphicalEffects +import SortFilterProxyModel 0.2 + import net.jami.Models 1.1 import net.jami.Adapters 1.1 import net.jami.Enums 1.1 @@ -118,13 +120,27 @@ ColumnLayout { tipText: JamiStrings.selectVideoDevice placeholderText: JamiStrings.noVideoDevice currentSelectionText: VideoDevices.defaultName - comboModel: VideoDevices.devicesFilterModel() + + comboModel: SortFilterProxyModel { + id: filteredDevicesModel + sourceModel: SortFilterProxyModel { + id: deviceSourceModel + sourceModel: VideoDevices.deviceSourceModel + } + filters: ValueFilter { + roleName: "DeviceName" + value: VideoDevices.defaultName + inverted: true + enabled: deviceSourceModel.count > 1 + } + } role: "DeviceName" onActivated: { // TODO: start and stop preview logic in here should be in LRC VideoDevices.stopDevice(previewWidget.deviceId) - VideoDevices.setDefaultDevice(modelIndex) + VideoDevices.setDefaultDevice( + filteredDevicesModel.mapToSource(modelIndex)) startPreviewing() } } @@ -145,10 +161,24 @@ ColumnLayout { labelText: JamiStrings.resolution currentSelectionText: VideoDevices.defaultRes tipText: JamiStrings.selectVideoResolution - comboModel: VideoDevices.resFilterModel() + + comboModel: SortFilterProxyModel { + id: filteredResModel + sourceModel: SortFilterProxyModel { + id: resSourceModel + sourceModel: VideoDevices.resSourceModel + } + filters: ValueFilter { + roleName: "Resolution" + value: VideoDevices.defaultRes + inverted: true + enabled: resSourceModel.count > 1 + } + } role: "Resolution" - onActivated: VideoDevices.setDefaultDeviceRes(modelIndex) + onActivated: VideoDevices.setDefaultDeviceRes( + filteredResModel.mapToSource(modelIndex)) } SettingsComboBox { @@ -167,10 +197,23 @@ ColumnLayout { tipText: JamiStrings.selectFPS labelText: JamiStrings.fps currentSelectionText: VideoDevices.defaultFps.toString() - comboModel: VideoDevices.fpsFilterModel() + comboModel: SortFilterProxyModel { + id: filteredFpsModel + sourceModel: SortFilterProxyModel { + id: fpsSourceModel + sourceModel: VideoDevices.fpsSourceModel + } + filters: ValueFilter { + roleName: "FPS" + value: VideoDevices.defaultFps + inverted: true + enabled: fpsSourceModel.count > 1 + } + } role: "FPS" - onActivated: VideoDevices.setDefaultDeviceFps(modelIndex) + onActivated: VideoDevices.setDefaultDeviceFps( + filteredFpsModel.mapToSource(modelIndex)) } ToggleSwitch { @@ -264,7 +307,7 @@ ColumnLayout { comboModel: ListModel { id: screenSharingFpsModel } role: "FPS" Component.onCompleted: { - var elements = VideoDevices.getScreenSharingFpsModel() + var elements = VideoDevices.sharingFpsSourceModel for (var item in elements) { screenSharingFpsModel.append({"FPS": elements[item]}) } diff --git a/src/app/videodevices.cpp b/src/app/videodevices.cpp index d0ab7cc4e..fe7c1251f 100644 --- a/src/app/videodevices.cpp +++ b/src/app/videodevices.cpp @@ -1,4 +1,4 @@ -/*! +/* * Copyright (C) 2020-2022 Savoir-faire Linux Inc. * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> * @@ -119,10 +119,8 @@ VideoFormatResolutionModel::roleNames() const int VideoFormatResolutionModel::getCurrentIndex() const { - QString currentDeviceId = videoDevices_->get_defaultId(); QString currentResolution = videoDevices_->get_defaultRes(); auto resultList = match(index(0, 0), Resolution, QVariant(currentResolution)); - return resultList.size() > 0 ? resultList[0].row() : 0; } @@ -183,21 +181,10 @@ VideoFormatFpsModel::getCurrentIndex() const VideoDevices::VideoDevices(LRCInstance* lrcInstance, QObject* parent) : QObject(parent) , lrcInstance_(lrcInstance) - , devicesFilterModel_(new CurrentItemFilterModel(this)) - , resFilterModel_(new CurrentItemFilterModel(this)) - , fpsFilterModel_(new CurrentItemFilterModel(this)) { - devicesSourceModel_ = new VideoInputDeviceModel(lrcInstance, this); - resSourceModel_ = new VideoFormatResolutionModel(lrcInstance, this); - fpsSourceModel_ = new VideoFormatFpsModel(lrcInstance, this); - - devicesFilterModel_->setSourceModel(devicesSourceModel_); - resFilterModel_->setSourceModel(resSourceModel_); - fpsFilterModel_->setSourceModel(fpsSourceModel_); - - devicesFilterModel_->setFilterRole(VideoInputDeviceModel::DeviceName); - resFilterModel_->setFilterRole(VideoFormatResolutionModel::Resolution); - fpsFilterModel_->setFilterRole(VideoFormatFpsModel::FPS); + deviceListModel_ = new VideoInputDeviceModel(lrcInstance, this); + resListModel_ = new VideoFormatResolutionModel(lrcInstance, this); + fpsListModel_ = new VideoFormatFpsModel(lrcInstance, this); connect(&lrcInstance_->avModel(), &lrc::api::AVModel::deviceEvent, @@ -206,67 +193,28 @@ VideoDevices::VideoDevices(LRCInstance* lrcInstance, QObject* parent) auto displaySettings = lrcInstance_->avModel().getDeviceSettings(DEVICE_DESKTOP); - auto desktopfpsSource = lrcInstance_->avModel().getDeviceCapabilities(DEVICE_DESKTOP); - if (desktopfpsSource.contains(CHANNEL_DEFAULT) && !desktopfpsSource[CHANNEL_DEFAULT].empty()) { - desktopfpsSourceModel_ = desktopfpsSource[CHANNEL_DEFAULT][0].second; - if (desktopfpsSourceModel_.indexOf(displaySettings.rate) >= 0) + auto desktopFpsSource = lrcInstance_->avModel().getDeviceCapabilities(DEVICE_DESKTOP); + if (desktopFpsSource.contains(CHANNEL_DEFAULT) && !desktopFpsSource[CHANNEL_DEFAULT].empty()) { + sharingFpsListModel_ = desktopFpsSource[CHANNEL_DEFAULT][0].second; + if (sharingFpsListModel_.indexOf(displaySettings.rate) >= 0) set_screenSharingDefaultFps(displaySettings.rate); } updateData(); } -VideoDevices::~VideoDevices() {} - -QVariant -VideoDevices::devicesFilterModel() -{ - return QVariant::fromValue(devicesFilterModel_); -} - -QVariant -VideoDevices::devicesSourceModel() -{ - return QVariant::fromValue(devicesSourceModel_); -} - -QVariant -VideoDevices::resFilterModel() -{ - return QVariant::fromValue(resFilterModel_); -} - -QVariant -VideoDevices::resSourceModel() -{ - return QVariant::fromValue(resSourceModel_); -} - -QVariant -VideoDevices::fpsFilterModel() -{ - return QVariant::fromValue(fpsFilterModel_); -} - -QVariant -VideoDevices::fpsSourceModel() -{ - return QVariant::fromValue(fpsSourceModel_); -} - void -VideoDevices::setDefaultDevice(int index, bool useSourceModel) +VideoDevices::setDefaultDevice(int index) { + if (!listSize_) { + return; + } + QString deviceId {}; auto callId = lrcInstance_->getCurrentCallId(); - if (useSourceModel) - deviceId = devicesSourceModel_ - ->data(devicesSourceModel_->index(index, 0), VideoInputDeviceModel::DeviceId) - .toString(); - else - deviceId = devicesFilterModel_ - ->data(devicesFilterModel_->index(index, 0), VideoInputDeviceModel::DeviceId) - .toString(); + deviceId = deviceListModel_ + ->data(deviceListModel_->index(index, 0), VideoInputDeviceModel::DeviceId) + .toString(); lrcInstance_->avModel().setDefaultDevice(deviceId); @@ -279,11 +227,10 @@ VideoDevices::setDefaultDevice(int index, bool useSourceModel) const QString VideoDevices::getDefaultDevice() { - auto idx = devicesSourceModel_->getCurrentIndex(); + auto idx = deviceListModel_->getCurrentIndex(); auto rendererId = QString("camera://") - + devicesSourceModel_ - ->data(devicesSourceModel_->index(idx, 0), - VideoInputDeviceModel::DeviceId) + + deviceListModel_ + ->data(deviceListModel_->index(idx, 0), VideoInputDeviceModel::DeviceId) .toString(); return rendererId; } @@ -318,8 +265,8 @@ VideoDevices::setDefaultDeviceRes(int index) { auto& channelCaps = get_defaultResRateList(); auto settings = lrcInstance_->avModel().getDeviceSettings(get_defaultId()); - settings.size = resFilterModel_ - ->data(resFilterModel_->index(index, 0), + settings.size = resListModel_ + ->data(resListModel_->index(index, 0), VideoFormatResolutionModel::Resolution) .toString(); @@ -339,8 +286,8 @@ VideoDevices::setDefaultDeviceFps(int index) { auto settings = lrcInstance_->avModel().getDeviceSettings(get_defaultId()); settings.size = get_defaultRes(); - settings.rate = fpsFilterModel_ - ->data(fpsFilterModel_->index(index, 0), VideoFormatFpsModel::FPS_Float) + settings.rate = fpsListModel_ + ->data(fpsListModel_->index(index, 0), VideoFormatFpsModel::FPS_Float) .toFloat(); lrcInstance_->avModel().setDeviceSettings(settings); @@ -358,12 +305,6 @@ VideoDevices::setDisplayFPS(const QString& fps) set_screenSharingDefaultFps(fps.toInt()); } -QVariant -VideoDevices::getScreenSharingFpsModel() -{ - return QVariant::fromValue(desktopfpsSourceModel_.toList()); -} - void VideoDevices::updateData() { @@ -377,31 +318,12 @@ VideoDevices::updateData() ? CHANNEL_DEFAULT : defaultDeviceSettings.channel]; lrc::api::video::FrameratesList fpsList; - for (int i = 0; i < currentResRateList.size(); i++) { if (currentResRateList[i].first == defaultDeviceSettings.size) { fpsList = currentResRateList[i].second; } } - if (deviceOpen_ && defaultId_ != defaultDeviceSettings.id) { - auto callId = lrcInstance_->getCurrentCallId(); - if (!callId.isEmpty()) { - auto callId = lrcInstance_->getCurrentCallId(); - auto callInfos = lrcInstance_->getCallInfo(callId, - lrcInstance_->get_currentAccountId()); - for (const auto& media : callInfos->mediaList) { - if (media["MUTED"] == "false" && media["ENABLED"] == "true" - && media["SOURCE"] == getDefaultDevice()) { - /*lrcInstance_->avModel().switchInputTo("camera://" + - defaultDeviceSettings.id, callId);*/ - // startDevice("camera://" + defaultDeviceSettings.id); - break; - } - } - } - } - set_defaultChannel(defaultDeviceSettings.channel); set_defaultId(defaultDeviceSettings.id); set_defaultName(defaultDeviceSettings.name); @@ -409,10 +331,6 @@ VideoDevices::updateData() set_defaultFps(defaultDeviceSettings.rate); set_defaultResRateList(currentResRateList); set_defaultFpsList(fpsList); - - devicesFilterModel_->setCurrentItemFilter(defaultDeviceSettings.name); - resFilterModel_->setCurrentItemFilter(defaultDeviceSettings.size); - fpsFilterModel_->setCurrentItemFilter(static_cast<int>(defaultDeviceSettings.rate)); } else { set_defaultChannel(""); set_defaultId(""); @@ -421,23 +339,22 @@ VideoDevices::updateData() set_defaultFps(0); set_defaultResRateList({}); set_defaultFpsList({}); - - devicesFilterModel_->setCurrentItemFilter(""); - resFilterModel_->setCurrentItemFilter(""); - fpsFilterModel_->setCurrentItemFilter(0); } - devicesSourceModel_->reset(); - resSourceModel_->reset(); - fpsSourceModel_->reset(); + deviceListModel_->reset(); + resListModel_->reset(); + fpsListModel_->reset(); + + set_deviceSourceModel(QVariant::fromValue(deviceListModel_)); + set_resSourceModel(QVariant::fromValue(resListModel_)); + set_fpsSourceModel(QVariant::fromValue(fpsListModel_)); + set_sharingFpsSourceModel(QVariant::fromValue(sharingFpsListModel_.toList())); } void VideoDevices::onVideoDeviceEvent() { auto& avModel = lrcInstance_->avModel(); - auto* callModel = lrcInstance_->getCurrentCallModel(); - auto defaultDevice = avModel.getDefaultDevice(); QString callId = lrcInstance_->getCurrentCallId(); // Decide whether a device has plugged, unplugged, or nothing has changed. diff --git a/src/app/videodevices.h b/src/app/videodevices.h index 2dee808dd..aee88af88 100644 --- a/src/app/videodevices.h +++ b/src/app/videodevices.h @@ -1,4 +1,4 @@ -/*! +/* * Copyright (C) 2020-2022 Savoir-faire Linux Inc. * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> * @@ -23,41 +23,10 @@ #include "api/devicemodel.h" -#include <QSortFilterProxyModel> #include <QObject> class VideoDevices; -class CurrentItemFilterModel final : public QSortFilterProxyModel -{ - Q_OBJECT - -public: - explicit CurrentItemFilterModel(QObject* parent = nullptr) - : QSortFilterProxyModel(parent) - - {} - - void setCurrentItemFilter(const QVariant& filter) - { - currentItemFilter_ = filter; - } - - virtual bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override - { - // Do not filter if there is only one item. - if (currentItemFilter_.isNull() || sourceModel()->rowCount() == 1) - return true; - - // Exclude current item filter. - auto index = sourceModel()->index(sourceRow, 0, sourceParent); - return index.data(filterRole()) != currentItemFilter_ && !index.parent().isValid(); - } - -private: - QVariant currentItemFilter_ {}; -}; - class VideoInputDeviceModel : public QAbstractListModel { Q_OBJECT @@ -155,21 +124,16 @@ class VideoDevices : public QObject QML_RO_PROPERTY(int, defaultFps) QML_PROPERTY(int, screenSharingDefaultFps) + QML_RO_PROPERTY(QVariant, deviceSourceModel) + QML_RO_PROPERTY(QVariant, resSourceModel) + QML_RO_PROPERTY(QVariant, fpsSourceModel) + QML_RO_PROPERTY(QVariant, sharingFpsSourceModel) + public: explicit VideoDevices(LRCInstance* lrcInstance, QObject* parent = nullptr); - ~VideoDevices(); - - Q_INVOKABLE QVariant devicesFilterModel(); - Q_INVOKABLE QVariant devicesSourceModel(); - - Q_INVOKABLE QVariant resFilterModel(); - Q_INVOKABLE QVariant resSourceModel(); + ~VideoDevices() = default; - Q_INVOKABLE QVariant fpsFilterModel(); - Q_INVOKABLE QVariant fpsSourceModel(); - Q_INVOKABLE QVariant getScreenSharingFpsModel(); - - Q_INVOKABLE void setDefaultDevice(int index, bool useSourceModel = false); + Q_INVOKABLE void setDefaultDevice(int index); Q_INVOKABLE const QString getDefaultDevice(); Q_INVOKABLE QString startDevice(const QString& deviceId, bool force = false); Q_INVOKABLE void stopDevice(const QString& deviceId, bool force = false); @@ -198,17 +162,13 @@ private: LRCInstance* lrcInstance_; - CurrentItemFilterModel* devicesFilterModel_; - CurrentItemFilterModel* resFilterModel_; - CurrentItemFilterModel* fpsFilterModel_; - - VideoInputDeviceModel* devicesSourceModel_; - VideoFormatResolutionModel* resSourceModel_; - VideoFormatFpsModel* fpsSourceModel_; + VideoInputDeviceModel* deviceListModel_; + VideoFormatResolutionModel* resListModel_; + VideoFormatFpsModel* fpsListModel_; lrc::api::video::ResRateList defaultResRateList_; lrc::api::video::FrameratesList defaultFpsList_; - lrc::api::video::FrameratesList desktopfpsSourceModel_; + lrc::api::video::FrameratesList sharingFpsListModel_; constexpr static const char DEVICE_DESKTOP[] = "desktop"; constexpr static const char CHANNEL_DEFAULT[] = "default"; -- GitLab