From 296da3b7dbbc5edd7c0ab38da7c4a5e9255e75ce Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Mon, 5 Jun 2023 16:37:10 +0200 Subject: [PATCH] Avoid refreshing all layout when removing/adding items in list. Use default video conference layout when making a call. Fix active speaker device on GUI initialization (going from/to fullscreen, opening new call window). Changing sort heuristics on participant devices to stabilized stickers: Ignore time of joining and keep only the order of the list of participants. Display the preview at the end of the list. In active speaker : Replace the layout refresh workaround by moving the top margin on participant list. This avoid to reload camera each time. TODO: update SDK to retrieve the correct order of participant devices. # Conflicts: # linphone-app/src/components/calls/CallsListModel.cpp --- CHANGELOG.md | 1 + .../src/app/proxyModel/ProxyAbstractListModel.hpp | 14 ++++++++------ linphone-app/src/app/proxyModel/ProxyListModel.hpp | 8 ++++---- .../src/components/calls/CallsListModel.cpp | 3 ++- linphone-app/src/components/camera/Camera.cpp | 4 ++-- .../participant/ParticipantDeviceListModel.cpp | 4 +++- .../participant/ParticipantDeviceProxyModel.cpp | 8 +++++--- .../ui/views/App/Calls/IncallActiveSpeaker.qml | 7 ++++--- 8 files changed, 29 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4032cf678..cf02be85b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Primary color for links in chat. - Bubble chat layout. +- Camera stickers and conference layout stabilization. ### Added - VFS Encryption. diff --git a/linphone-app/src/app/proxyModel/ProxyAbstractListModel.hpp b/linphone-app/src/app/proxyModel/ProxyAbstractListModel.hpp index 52363b6aa..a959b1147 100644 --- a/linphone-app/src/app/proxyModel/ProxyAbstractListModel.hpp +++ b/linphone-app/src/app/proxyModel/ProxyAbstractListModel.hpp @@ -62,24 +62,26 @@ public: // Add functions virtual void add(T item){ int row = mList.count(); - emit layoutAboutToBeChanged(); beginInsertRows(QModelIndex(), row, row); mList << item; endInsertRows(); - emit layoutChanged(); + auto lastIndex = index(mList.size()-1,0); + emit dataChanged(lastIndex,lastIndex ); } virtual void add(QList items){ - emit layoutAboutToBeChanged(); + auto firstIndex = index(mList.size()-1,0); beginInsertRows(QModelIndex(), mList.size(), mList.size() + items.size()-1); mList << items; endInsertRows(); - emit layoutChanged(); + auto lastIndex = index(mList.size()-1,0); + emit dataChanged(firstIndex,lastIndex); } virtual void prepend(T item){ beginInsertRows(QModelIndex(), 0, 0); mList.prepend(item); endInsertRows(); + emit dataChanged(index(0),index(0)); } virtual void prepend(QList items){ @@ -87,6 +89,7 @@ public: items << mList; mList = items; endInsertRows(); + emit dataChanged(index(0),index(items.size()-1)); } // Remove functions @@ -97,12 +100,11 @@ public: int limit = row + count - 1; if (row < 0 || count < 0 || limit >= mList.count()) return false; - emit layoutAboutToBeChanged(); beginRemoveRows(parent, row, limit); for (int i = 0; i < count; ++i) mList.takeAt(row); endRemoveRows(); - emit layoutChanged(); + emit dataChanged(index(row), index(limit)); return true; } diff --git a/linphone-app/src/app/proxyModel/ProxyListModel.hpp b/linphone-app/src/app/proxyModel/ProxyListModel.hpp index 45781dc79..608ee4fef 100644 --- a/linphone-app/src/app/proxyModel/ProxyListModel.hpp +++ b/linphone-app/src/app/proxyModel/ProxyListModel.hpp @@ -65,12 +65,13 @@ public: template void add(QList> items){ - emit layoutAboutToBeChanged(); + auto firstIndex = index(mList.size()-1,0); beginInsertRows(QModelIndex(), mList.size(), mList.size() + items.size() - 1); for(auto i : items) mList << i.template objectCast(); endInsertRows(); - emit layoutChanged(); + auto lastIndex = index(mList.size()-1,0); + emit dataChanged(firstIndex,lastIndex); } template @@ -80,12 +81,11 @@ public: template void prepend(QList> items){ - emit layoutAboutToBeChanged(); beginInsertRows(QModelIndex(), 0, items.size()-1); items << mList; mList = items; endInsertRows(); - emit layoutChanged(); + emit dataChanged(index(0),index(items.size()-1)); } virtual bool remove(QObject *itemToRemove) override{ diff --git a/linphone-app/src/components/calls/CallsListModel.cpp b/linphone-app/src/components/calls/CallsListModel.cpp index 4c774b19b..758e11af6 100644 --- a/linphone-app/src/components/calls/CallsListModel.cpp +++ b/linphone-app/src/components/calls/CallsListModel.cpp @@ -186,7 +186,8 @@ void CallsListModel::launchVideoCall (const QString &sipAddress, const QString& shared_ptr params = core->createCallParams(nullptr); - auto layout = options.contains("layout") ? LinphoneEnums::toLinphone((LinphoneEnums::ConferenceLayout)options["layout"].toInt()) : linphone::Conference::Layout::Grid; + auto layout = options.contains("layout") ? LinphoneEnums::toLinphone((LinphoneEnums::ConferenceLayout)options["layout"].toInt()) : LinphoneEnums::toLinphone(CoreManager::getInstance()->getSettingsModel()->getVideoConferenceLayout()); + bool enableMicro =options.contains("micro") ? options["micro"].toBool() : true; bool enableVideo = options.contains("video") ? options["video"].toBool() : true; bool enableCamera = options.contains("camera") ? options["camera"].toBool() : true; diff --git a/linphone-app/src/components/camera/Camera.cpp b/linphone-app/src/components/camera/Camera.cpp index 9d2737386..0d7c2b4d4 100644 --- a/linphone-app/src/components/camera/Camera.cpp +++ b/linphone-app/src/components/camera/Camera.cpp @@ -109,7 +109,7 @@ void Camera::resetWindowId() const{ if(mLinphonePlayer && mLinphonePlayer->getLinphonePlayer()) mLinphonePlayer->getLinphonePlayer()->setWindowId(nullptr); } - qInfo() << "[Camera] (" << mQmlName << ") Removed " << oldRenderer << " at " << mWindowIdLocation << " for " << this; + qInfo() << "[Camera] (" << mQmlName << ") Removed " << oldRenderer << " at " << mWindowIdLocation << " for " << this << " Device(" << mParticipantDeviceModel << ")"; mIsWindowIdSet = false; } } @@ -226,7 +226,7 @@ QQuickFramebufferObject::Renderer *Camera::createRenderer () const { }else{ mIsWindowIdSet = true; - qInfo() << "[Camera] (" << mQmlName << ") Added " << renderer << " at " << mWindowIdLocation << " for " << this; + qInfo() << "[Camera] (" << mQmlName << ") Added " << renderer << " at " << mWindowIdLocation << " for " << this << " Device(" << mParticipantDeviceModel << ")"; QTimer::singleShot(1, this, &Camera::isReady);// Workaround for const createRenderer. } return renderer; diff --git a/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp b/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp index 82e1af73b..388cfbd8b 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp +++ b/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp @@ -69,7 +69,8 @@ void ParticipantDeviceListModel::initConferenceModel(){ connect(conferenceModel.get(), &ConferenceModel::conferenceStateChanged, this, &ParticipantDeviceListModel::onConferenceStateChanged); connect(conferenceModel.get(), &ConferenceModel::participantDeviceMediaCapabilityChanged, this, &ParticipantDeviceListModel::onParticipantDeviceMediaCapabilityChanged); connect(conferenceModel.get(), &ConferenceModel::participantDeviceMediaAvailabilityChanged, this, &ParticipantDeviceListModel::onParticipantDeviceMediaAvailabilityChanged); - connect(conferenceModel.get(), &ConferenceModel::participantDeviceIsSpeakingChanged, this, &ParticipantDeviceListModel::onParticipantDeviceIsSpeakingChanged); + connect(conferenceModel.get(), &ConferenceModel::participantDeviceIsSpeakingChanged, this, &ParticipantDeviceListModel::onParticipantDeviceIsSpeakingChanged); + mActiveSpeaker = get(conferenceModel->getConference()->getActiveSpeakerParticipantDevice()); mInitialized = true; } } @@ -112,6 +113,7 @@ bool ParticipantDeviceListModel::add(std::shared_ptrupdateVideoEnabled(); return false; }else if(deviceToAddAddr->equal(deviceModel->getDevice()->getAddress())){// Address is the same (same device) but the model is using another linphone object. Replace it. + qDebug() << "Replacing device : Device exists but the model is using another linphone object."; deviceModel->updateVideoEnabled(); removeRow(row); break; diff --git a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp index 5ba0144e0..adab908fd 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp +++ b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp @@ -50,8 +50,8 @@ bool ParticipantDeviceProxyModel::filterAcceptsRow ( bool ParticipantDeviceProxyModel::lessThan (const QModelIndex &left, const QModelIndex &right) const { const ParticipantDeviceModel *deviceA = sourceModel()->data(left).value(); const ParticipantDeviceModel *deviceB = sourceModel()->data(right).value(); - - return deviceA->getTimeOfJoining() > deviceB->getTimeOfJoining(); + // 'me' at end (for grid). + return deviceB->isMe() || left.row() < right.row(); } //--------------------------------------------------------------------------------- @@ -97,6 +97,7 @@ void ParticipantDeviceProxyModel::setCallModel(CallModel * callModel){ connectTo(newSourceModel); setSourceModel(newSourceModel); mDeleteSourceModel = true; + sort(0); emit countChanged(); emit meChanged(); } @@ -108,6 +109,7 @@ void ParticipantDeviceProxyModel::setParticipant(ParticipantModel * participant) connectTo(newSourceModel); setSourceModel(newSourceModel); mDeleteSourceModel = false; + sort(0); emit countChanged(); emit meChanged(); } @@ -126,4 +128,4 @@ void ParticipantDeviceProxyModel::onCountChanged(){ void ParticipantDeviceProxyModel::onParticipantSpeaking(ParticipantDeviceModel * speakingDevice){ emit participantSpeaking(speakingDevice); -} \ No newline at end of file +} diff --git a/linphone-app/ui/views/App/Calls/IncallActiveSpeaker.qml b/linphone-app/ui/views/App/Calls/IncallActiveSpeaker.qml index 51d91922e..747ad1772 100644 --- a/linphone-app/ui/views/App/Calls/IncallActiveSpeaker.qml +++ b/linphone-app/ui/views/App/Calls/IncallActiveSpeaker.qml @@ -130,6 +130,7 @@ Item { } } Item{ + id: miniViewArea anchors.right: parent.right anchors.top: parent.top anchors.bottom: preview.top @@ -151,9 +152,9 @@ Item { property int oldCount : 0// Count changed can be called without a change... (bug?). Use oldCount to avoid it. onCountChanged: {if(oldCount != count){ oldCount = count ; Qt.callLater(forceRefresh)}} onHeightChanged: Qt.callLater(forceRefresh) - function forceRefresh(){// Force a content refresh via layout direction. Qt is buggy when managing sizes in ListView. - miniViews.verticalLayoutDirection = ListView.TopToBottom - miniViews.verticalLayoutDirection = ListView.BottomToTop + function forceRefresh(){// Force a content refresh via margins. Qt is buggy when managing sizes in ListView. + ++miniViewArea.anchors.topMargin + --miniViewArea.anchors.topMargin } Component.onCompleted: {Qt.callLater(forceRefresh)} delegate:Item{