From 948e2cc837b8646eace757a782666507485c959c Mon Sep 17 00:00:00 2001 From: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> Date: Mon, 29 May 2023 13:24:19 -0300 Subject: [PATCH] callactionbar: avoid multiple resets GitLab: #1073 Change-Id: I7dc2ab632170a959b8d29979deacd3fb03ff6671 --- src/app/calloverlaymodel.cpp | 48 +++++-- src/app/calloverlaymodel.h | 9 +- src/app/currentcall.cpp | 7 + src/app/mainview/components/CallActionBar.qml | 120 ++++++++---------- 4 files changed, 104 insertions(+), 80 deletions(-) diff --git a/src/app/calloverlaymodel.cpp b/src/app/calloverlaymodel.cpp index dd1ee9c9e..a15496eca 100644 --- a/src/app/calloverlaymodel.cpp +++ b/src/app/calloverlaymodel.cpp @@ -35,10 +35,11 @@ IndexRangeFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& s { auto index = sourceModel()->index(sourceRow, 0, sourceParent); bool predicate = true; + bool enabled = sourceModel()->data(index, CallControl::Role::Enabled).toBool(); if (filterRole() != Qt::DisplayRole) { predicate = sourceModel()->data(index, filterRole()).toInt() != 0; } - return sourceRow <= max_ && sourceRow >= min_ && predicate; + return sourceRow <= max_ && sourceRow >= min_ && predicate && enabled; } void @@ -197,10 +198,12 @@ CallControlListModel::data(const QModelIndex& index, int role) const auto item = data_.at(index.row()); switch (role) { - case Role::ItemAction: + case CallControl::Role::ItemAction: return QVariant::fromValue(item.itemAction); - case Role::UrgentCount: + case CallControl::Role::UrgentCount: return QVariant::fromValue(item.urgentCount); + case CallControl::Role::Enabled: + return QVariant::fromValue(item.enabled); } return QVariant(); } @@ -212,6 +215,7 @@ CallControlListModel::roleNames() const QHash<int, QByteArray> roles; roles[ItemAction] = "ItemAction"; roles[UrgentCount] = "UrgentCount"; + roles[Enabled] = "Enabled"; return roles; } @@ -232,6 +236,24 @@ CallControlListModel::setUrgentCount(QVariant item, int count) } } +void +CallControlListModel::setEnabled(QObject* obj, bool enabled) +{ + beginResetModel(); + auto it = std::find_if(data_.cbegin(), data_.cend(), [obj](const auto& item) { + return item.itemAction == obj; + }); + if (it != data_.cend()) { + auto row = std::distance(data_.cbegin(), it); + if (row >= rowCount()) + return; + data_[row].enabled = enabled; + auto idx = index(row, 0); + Q_EMIT dataChanged(idx, idx); + } + endResetModel(); +} + void CallControlListModel::addItem(const CallControl::Item& item) { @@ -264,15 +286,15 @@ CallOverlayModel::CallOverlayModel(LRCInstance* instance, QObject* parent) } void -CallOverlayModel::addPrimaryControl(const QVariant& action) +CallOverlayModel::addPrimaryControl(const QVariant& action, bool enabled) { - primaryModel_->addItem(CallControl::Item {action.value<QObject*>()}); + primaryModel_->addItem(CallControl::Item {action.value<QObject*>(), enabled}); } void -CallOverlayModel::addSecondaryControl(const QVariant& action) +CallOverlayModel::addSecondaryControl(const QVariant& action, bool enabled) { - secondaryModel_->addItem(CallControl::Item {action.value<QObject*>()}); + secondaryModel_->addItem(CallControl::Item {action.value<QObject*>(), enabled}); setControlRanges(); } @@ -282,6 +304,13 @@ CallOverlayModel::setUrgentCount(QVariant row, int count) secondaryModel_->setUrgentCount(row, count); } +void +CallOverlayModel::setEnabled(QObject* obj, bool enabled) +{ + primaryModel_->setEnabled(obj, enabled); + secondaryModel_->setEnabled(obj, enabled); +} + QVariant CallOverlayModel::primaryModel() { @@ -363,7 +392,8 @@ CallOverlayModel::eventFilter(QObject* object, QEvent* event) void CallOverlayModel::setControlRanges() { + auto count = secondaryModel_->rowCount(); overflowModel_->setRange(0, overflowIndex_); - overflowVisibleModel_->setRange(overflowIndex_, secondaryModel_->rowCount()); - overflowHiddenModel_->setRange(overflowIndex_ + 1, secondaryModel_->rowCount()); + overflowVisibleModel_->setRange(overflowIndex_, count); + overflowHiddenModel_->setRange(overflowIndex_ + 1, count); } diff --git a/src/app/calloverlaymodel.h b/src/app/calloverlaymodel.h index 3193a3a6d..2cbb7d074 100644 --- a/src/app/calloverlaymodel.h +++ b/src/app/calloverlaymodel.h @@ -36,12 +36,13 @@ namespace CallControl { Q_NAMESPACE -enum Role { ItemAction = Qt::UserRole + 1, UrgentCount }; +enum Role { ItemAction = Qt::UserRole + 1, UrgentCount, Enabled}; Q_ENUM_NS(Role) struct Item { QObject* itemAction; + bool enabled {true}; int urgentCount {0}; }; } // namespace CallControl @@ -106,6 +107,7 @@ public: QHash<int, QByteArray> roleNames() const override; void setUrgentCount(QVariant item, int count); + void setEnabled(QObject* obj, bool enabled); void addItem(const CallControl::Item& item); void clearData(); @@ -121,9 +123,10 @@ class CallOverlayModel : public QObject public: CallOverlayModel(LRCInstance* instance, QObject* parent = nullptr); - Q_INVOKABLE void addPrimaryControl(const QVariant& action); - Q_INVOKABLE void addSecondaryControl(const QVariant& action); + Q_INVOKABLE void addPrimaryControl(const QVariant& action, bool enabled); + Q_INVOKABLE void addSecondaryControl(const QVariant& action, bool enabled); Q_INVOKABLE void setUrgentCount(QVariant item, int count); + Q_INVOKABLE void setEnabled(QObject* obj, bool enabled); Q_INVOKABLE void clearControls(); Q_INVOKABLE QVariant primaryModel(); diff --git a/src/app/currentcall.cpp b/src/app/currentcall.cpp index 8406633e7..ce2bc874c 100644 --- a/src/app/currentcall.cpp +++ b/src/app/currentcall.cpp @@ -43,6 +43,13 @@ CurrentCall::CurrentCall(LRCInstance* lrcInstance, QObject* parent) this, &CurrentCall::onShowIncomingCallView); + try { + auto& accInfo = lrcInstance_->getCurrentAccountInfo(); + set_isSIP(accInfo.profileInfo.type == profile::Type::SIP); + } catch (const std::exception& e) { + qWarning() << "Can't update current call type" << e.what(); + } + connectModel(); } diff --git a/src/app/mainview/components/CallActionBar.qml b/src/app/mainview/components/CallActionBar.qml index efdaff3f6..155f6c021 100644 --- a/src/app/mainview/components/CallActionBar.qml +++ b/src/app/mainview/components/CallActionBar.qml @@ -18,6 +18,7 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts +import SortFilterProxyModel 0.2 import net.jami.Models 1.1 import net.jami.Adapters 1.1 import net.jami.Constants 1.1 @@ -299,6 +300,8 @@ Control { text: !checked ? JamiStrings.muteCamera : JamiStrings.unmuteCamera checked: !CurrentCall.isCapturing property var menuAction: videoInputMenuAction + enabled: CurrentAccount.videoEnabled_Video + onEnabledChanged: CallOverlayModel.setEnabled(this, muteVideoAction.enabled) } ] @@ -319,6 +322,8 @@ Control { icon.source: JamiResources.add_people_black_24dp_svg icon.color: "white" text: JamiStrings.addParticipants + enabled: CurrentCall.isModerator && !CurrentCall.isSIP + onEnabledChanged: CallOverlayModel.setEnabled(this, addPersonAction.enabled) }, Action { id: chatAction @@ -333,6 +338,8 @@ Control { icon.source: CurrentCall.isPaused ? JamiResources.play_circle_outline_24dp_svg : JamiResources.pause_circle_outline_24dp_svg icon.color: "white" text: CurrentCall.isPaused ? JamiStrings.resumeCall : JamiStrings.pauseCall + enabled: CurrentCall.isSIP + onEnabledChanged: CallOverlayModel.setEnabled(this, resumePauseCallAction.enabled) }, Action { id: inputPanelSIPAction @@ -340,6 +347,8 @@ Control { icon.source: JamiResources.ic_keypad_svg icon.color: "white" text: JamiStrings.sipInputPanel + enabled: CurrentCall.isSIP + onEnabledChanged: CallOverlayModel.setEnabled(this, inputPanelSIPAction.enabled) }, Action { id: callTransferAction @@ -347,6 +356,8 @@ Control { icon.source: JamiResources.phone_forwarded_24dp_svg icon.color: "white" text: JamiStrings.transferCall + enabled: CurrentCall.isSIP + onEnabledChanged: CallOverlayModel.setEnabled(this, callTransferAction.enabled) }, Action { id: shareAction @@ -361,6 +372,8 @@ Control { text: CurrentCall.isSharing ? JamiStrings.stopSharing : JamiStrings.shareScreen property real size: 34 property var menuAction: shareMenuAction + enabled: CurrentAccount.videoEnabled_Video && !CurrentCall.isSIP + onEnabledChanged: CallOverlayModel.setEnabled(this, shareAction.enabled) }, Action { id: raiseHandAction @@ -371,6 +384,8 @@ Control { text: checked ? JamiStrings.lowerHand : JamiStrings.raiseHand checked: CurrentCall.isHandRaised property real size: 34 + enabled: CurrentCall.isConference + onEnabledChanged: CallOverlayModel.setEnabled(this, raiseHandAction.enabled) }, Action { id: layoutAction @@ -406,6 +421,7 @@ Control { icon.color: "white" text: JamiStrings.viewPlugin enabled: PluginAdapter.isEnabled && PluginAdapter.callMediaHandlersListCount + onEnabledChanged: CallOverlayModel.setEnabled(this, pluginsAction.enabled) }, Action { id: swarmDetailsAction @@ -414,7 +430,7 @@ Control { icon.color: "white" text: JamiStrings.details enabled: { - if (LRCInstance.currentAccountType === Profile.Type.SIP) + if (CurrentCall.isSIP) return true; if (!CurrentConversation.isTemporary && !CurrentConversation.isSwarm) return false; @@ -422,81 +438,35 @@ Control { return false; return true; } + onEnabledChanged: CallOverlayModel.setEnabled(this, swarmDetailsAction.enabled) } ] property var overflowItemCount - Connections { - target: CurrentCall - - function onIsActiveChanged() { - if (CurrentCall.isActive) - reset(); - } - function onIsRecordingLocallyChanged() { - Qt.callLater(reset); - } - function onIsHandRaisedChanged() { - Qt.callLater(reset); - } - function onIsConferenceChanged() { - Qt.callLater(reset); - } - function onIsModeratorChanged() { - Qt.callLater(reset); - } - function onIsSIPChanged() { - Qt.callLater(reset); - } - function onIsAudioOnlyChanged() { - Qt.callLater(reset); - } - function onIsAudioMutedChanged() { - Qt.callLater(reset); - } - function onIsVideoMutedChanged() { - Qt.callLater(reset); - } - } - - Connections { - target: CurrentAccount - function onVideoEnabledVideoChanged() { - reset(); - } - } - - function reset() { + Component.onCompleted: { CallOverlayModel.clearControls(); // centered controls - CallOverlayModel.addPrimaryControl(muteAudioAction); - CallOverlayModel.addPrimaryControl(hangupAction); - if (CurrentAccount.videoEnabled_Video) - CallOverlayModel.addPrimaryControl(muteVideoAction); + CallOverlayModel.addPrimaryControl(muteAudioAction, muteAudioAction.enabled); + CallOverlayModel.addPrimaryControl(hangupAction, hangupAction.enabled); + CallOverlayModel.addPrimaryControl(muteVideoAction, muteVideoAction.enabled); // overflow controls - CallOverlayModel.addSecondaryControl(audioOutputAction); - if (CurrentCall.isConference) { - CallOverlayModel.addSecondaryControl(raiseHandAction); - } - if (CurrentCall.isModerator && !CurrentCall.isSIP) - CallOverlayModel.addSecondaryControl(addPersonAction); - if (CurrentCall.isSIP) { - CallOverlayModel.addSecondaryControl(resumePauseCallAction); - CallOverlayModel.addSecondaryControl(inputPanelSIPAction); - CallOverlayModel.addSecondaryControl(callTransferAction); - } - CallOverlayModel.addSecondaryControl(chatAction); - if (CurrentAccount.videoEnabled_Video && !CurrentCall.isSIP) - CallOverlayModel.addSecondaryControl(shareAction); - CallOverlayModel.addSecondaryControl(layoutAction); - CallOverlayModel.addSecondaryControl(recordAction); - if (pluginsAction.enabled) - CallOverlayModel.addSecondaryControl(pluginsAction); - if (swarmDetailsAction.enabled) - CallOverlayModel.addSecondaryControl(swarmDetailsAction); + CallOverlayModel.addSecondaryControl(audioOutputAction, audioOutputAction.enabled); + CallOverlayModel.addSecondaryControl(raiseHandAction, raiseHandAction.enabled); + CallOverlayModel.addSecondaryControl(addPersonAction, addPersonAction.enabled); + + CallOverlayModel.addSecondaryControl(resumePauseCallAction, resumePauseCallAction.enabled); + CallOverlayModel.addSecondaryControl(inputPanelSIPAction, inputPanelSIPAction.enabled); + CallOverlayModel.addSecondaryControl(callTransferAction, callTransferAction.enabled); + + CallOverlayModel.addSecondaryControl(chatAction, chatAction.enabled); + CallOverlayModel.addSecondaryControl(shareAction, shareAction.enabled); + CallOverlayModel.addSecondaryControl(layoutAction, layoutAction.enabled); + CallOverlayModel.addSecondaryControl(recordAction, recordAction.enabled); + CallOverlayModel.addSecondaryControl(pluginsAction, pluginsAction.enabled); + CallOverlayModel.addSecondaryControl(swarmDetailsAction, swarmDetailsAction.enabled); overflowItemCount = CallOverlayModel.secondaryModel().rowCount(); } @@ -519,7 +489,13 @@ Control { implicitHeight: contentHeight interactive: false - model: CallOverlayModel.primaryModel() + model: SortFilterProxyModel { + sourceModel: CallOverlayModel.primaryModel() + filters: ValueFilter { + roleName: "Enabled" + value: true + } + } delegate: buttonDelegate } } @@ -547,7 +523,15 @@ Control { property int overflowIndex: { var maxItems = Math.floor((overflowRect.remainingSpace) / (root.height + itemSpacing)) - 2; - return Math.min(overflowItemCount, maxItems); + var idx = Math.min(overflowItemCount, maxItems); + idx = Math.max(0, idx); + if (CallOverlayModel.overflowModel().rowCount() > 0 || CallOverlayModel.overflowHiddenModel().rowCount() > 0) { + var visibleIdx = CallOverlayModel.overflowModel().mapToSource(CallOverlayModel.overflowModel().index(idx, 0)).row; + var hiddenIdx = CallOverlayModel.overflowHiddenModel().mapToSource(CallOverlayModel.overflowHiddenModel().index(idx - CallOverlayModel.overflowModel().rowCount(), 0)).row; + if (visibleIdx >= 0 || hiddenIdx >= 0) + idx = Math.max(visibleIdx, hiddenIdx); + } + return idx; } property int nOverflowItems: overflowItemCount - overflowIndex onNOverflowItemsChanged: { -- GitLab