1
0
Fork 0
mirror of https://git.jami.net/savoirfairelinux/jami-client-qt.git synced 2025-07-22 08:25:26 +02:00
jami-client-qt/src/app/connectioninfolistmodel.cpp
lcoursodon c4c2415d6b Connection monitoring : Correct layout after migration
Change-Id: I8c480be77e1ef0a8778d4e8420523b71c76c4555
2023-12-11 16:13:11 -05:00

227 lines
No EOL
7.6 KiB
C++

/*
* Copyright (C) 2023 Savoir-faire Linux Inc.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "connectioninfolistmodel.h"
ConnectionInfoListModel::ConnectionInfoListModel(LRCInstance* instance, QObject* parent)
: AbstractListModelBase(parent)
{
lrcInstance_ = instance;
connect(lrcInstance_,
&LRCInstance::currentAccountIdChanged,
this,
&ConnectionInfoListModel::resetData);
}
int
ConnectionInfoListModel::rowCount(const QModelIndex& parent) const
{
return peerIds_.size();
}
QVariant
ConnectionInfoListModel::data(const QModelIndex& index, int role) const
{
const auto accountId = lrcInstance_->get_currentAccountId();
if (accountId.isEmpty()) {
qWarning() << "ConnectionInfoListModel::data: accountId or peerID is empty";
return {};
}
const auto peerId = peerIds_[index.row()];
const auto peerData = peerData_[peerId];
switch (role) {
case ConnectionInfoList::ChannelsMap: {
QVariantMap channelsMapMap;
int i = 0;
for (const auto& device : peerData.keys()) {
QString channelsId = peerData[device]["id"].toString();
QVariantMap channelsMap;
const auto channelInfoList = lrcInstance_->getChannelList(accountId, channelsId);
for (const auto& channelInfo : channelInfoList) {
channelsMap.insert(channelInfo["id"], channelInfo["name"]);
}
channelsMapMap.insert(QString::number(i++), channelsMap);
}
return QVariant(channelsMapMap);
}
case ConnectionInfoList::ConnectionDatas: {
QString peerString;
peerString += "Peer:" + peerId;
for (const auto& device : peerData.keys()) {
peerString += "{";
peerString += "Device:" + device + ",";
peerString += "Status:" + peerData[device]["status"].toString() + ",";
peerString += "Channels:" + peerData[device]["channels"].toString() + ",";
peerString += "Remote Address" + peerData[device]["remoteAddress"].toString();
peerString += "}";
}
return peerString;
}
case ConnectionInfoList::PeerId:
return peerId;
case ConnectionInfoList::RemoteAddress: {
QVariantMap remoteAddressMap;
int i = 0;
for (const auto& device : peerData.keys()) {
remoteAddressMap.insert(QString::number(i++), peerData[device]["remoteAddress"]);
}
return QVariant(remoteAddressMap);
}
case ConnectionInfoList::DeviceId: {
QVariantMap deviceMap;
int i = 0;
for (const auto& device : peerData.keys()) {
deviceMap.insert(QString::number(i++), device);
}
return QVariant(deviceMap);
}
case ConnectionInfoList::Status: {
QVariantMap statusMap;
int i = 0;
for (const auto& device : peerData.keys()) {
statusMap.insert(QString::number(i++), peerData[device]["status"]);
}
return QVariantMap(statusMap);
}
case ConnectionInfoList::Channels: {
QVariantMap channelsMap;
int i = 0;
for (const auto& device : peerData.keys()) {
channelsMap.insert(QString::number(i++), peerData[device]["channels"]);
}
return QVariant(channelsMap);
}
case ConnectionInfoList::Count:
return peerData.size();
}
return {};
}
QHash<int, QByteArray>
ConnectionInfoListModel::roleNames() const
{
using namespace ConnectionInfoList;
QHash<int, QByteArray> roles;
#define X(role) roles[role] = #role;
CONNECTONINFO_ROLES
#undef X
return roles;
}
void
ConnectionInfoListModel::update()
{
const auto accountId = lrcInstance_->get_currentAccountId();
if (accountId.isEmpty()) {
return;
}
aggregateData();
}
template<typename T>
std::tuple<QVector<T>, QVector<T>>
getSetDiff(QVector<T> u, QVector<T> v)
{
using namespace std;
QVector<T> a, r;
set_difference(v.begin(), v.end(), u.begin(), u.end(), inserter(a, a.begin()));
set_difference(u.begin(), u.end(), v.begin(), v.end(), inserter(r, r.begin()));
return {a, r};
}
void
ConnectionInfoListModel::aggregateData()
{
const auto accountId = lrcInstance_->get_currentAccountId();
if (accountId.isEmpty()) {
return;
}
connectionInfoList_ = lrcInstance_->getConnectionList(accountId);
peerData_ = {};
QSet<QString> newPeerIds;
for (const auto& connectionInfo : connectionInfoList_) {
if (!connectionInfo["peer"].isEmpty()) {
newPeerIds.insert(connectionInfo["peer"]);
}
const auto channelInfoList = lrcInstance_->getChannelList(accountId, connectionInfo["id"]);
peerData_[connectionInfo["peer"]][connectionInfo["device"]] = {};
peerData_[connectionInfo["peer"]][connectionInfo["device"]]["status"]
= connectionInfo["status"];
peerData_[connectionInfo["peer"]][connectionInfo["device"]]["channels"] = channelInfoList
.size();
peerData_[connectionInfo["peer"]][connectionInfo["device"]]["id"] = connectionInfo["id"];
peerData_[connectionInfo["peer"]][connectionInfo["device"]]["remoteAddress"]
= connectionInfo["remoteAddress"];
}
QVector<QString> oldVector;
for (const auto& peerId : peerIds_) {
oldVector << peerId;
}
QVector<QString> newVector;
for (const auto& peerId : newPeerIds) {
newVector << peerId;
}
std::sort(oldVector.begin(), oldVector.end());
std::sort(newVector.begin(), newVector.end());
QVector<QString> removed, added;
std::tie(added, removed) = getSetDiff(oldVector, newVector);
Q_FOREACH (const auto& key, added) {
auto index = std::distance(newVector.begin(),
std::find(newVector.begin(), newVector.end(), key));
beginInsertRows(QModelIndex(), index, index);
peerIds_.insert(index, key);
endInsertRows();
}
Q_FOREACH (const auto& key, removed) {
auto index = std::distance(oldVector.begin(),
std::find(oldVector.begin(), oldVector.end(), key));
beginRemoveRows(QModelIndex(), index, index);
if (peerIds_.size() > index) {
peerIds_.remove(index);
} else {
qWarning() << "ConnectionInfoListModel::aggregateData: index out of range";
qWarning() << "index: " << index;
qWarning() << "key: " << key;
}
endRemoveRows();
}
// HACK: loop through all the peerIds_ and update the data for each one.
// This is not efficient, but it works.
Q_FOREACH (const auto& peerId, peerIds_) {
auto index = std::distance(peerIds_.begin(),
std::find(peerIds_.begin(), peerIds_.end(), peerId));
Q_EMIT dataChanged(this->index(index), this->index(index));
}
}
void
ConnectionInfoListModel::resetData()
{
beginResetModel();
peerIds_.clear();
peerData_.clear();
endResetModel();
}