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
This commit is contained in:
Julien Wadel 2023-06-05 16:37:10 +02:00
parent 7b9e9136dd
commit 296da3b7db
8 changed files with 29 additions and 20 deletions

View file

@ -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.

View file

@ -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<T> 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<T> 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;
}

View file

@ -65,12 +65,13 @@ public:
template <class T>
void add(QList<QSharedPointer<T>> 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<QObject>();
endInsertRows();
emit layoutChanged();
auto lastIndex = index(mList.size()-1,0);
emit dataChanged(firstIndex,lastIndex);
}
template <class T>
@ -80,12 +81,11 @@ public:
template <class T>
void prepend(QList<QSharedPointer<T>> 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{

View file

@ -186,7 +186,8 @@ void CallsListModel::launchVideoCall (const QString &sipAddress, const QString&
shared_ptr<linphone::CallParams> 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;

View file

@ -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;

View file

@ -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_ptr<linphone::ParticipantDevice
deviceModel->updateVideoEnabled();
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;

View file

@ -50,8 +50,8 @@ bool ParticipantDeviceProxyModel::filterAcceptsRow (
bool ParticipantDeviceProxyModel::lessThan (const QModelIndex &left, const QModelIndex &right) const {
const ParticipantDeviceModel *deviceA = sourceModel()->data(left).value<ParticipantDeviceModel *>();
const ParticipantDeviceModel *deviceB = sourceModel()->data(right).value<ParticipantDeviceModel *>();
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);
}
}

View file

@ -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{