mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-07-25 18:05:34 +02:00

Minor cosmetic changes to the account combo box, search bar, filter tabs, and smartlist. Change-Id: Ie8173504859b325374e42f0dbb4e0ae75f3ed740 Gitlab: #373 Gitlab: #374 Gitlab: #388
422 lines
11 KiB
C++
422 lines
11 KiB
C++
/*
|
|
* Copyright (C) 2019-2021 by Savoir-faire Linux
|
|
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
|
* Author: Isa Nanic <isa.nanic@savoirfairelinux.com>
|
|
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
|
*
|
|
* 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 "lrcinstance.h"
|
|
|
|
#include <QBuffer>
|
|
#include <QMutex>
|
|
#include <QObject>
|
|
#include <QPixmap>
|
|
#include <QRegularExpression>
|
|
#include <QSettings>
|
|
#include <QtConcurrent/QtConcurrent>
|
|
|
|
LRCInstance::LRCInstance(migrateCallback willMigrateCb,
|
|
migrateCallback didMigrateCb,
|
|
const QString& updateUrl,
|
|
ConnectivityMonitor* connectivityMonitor,
|
|
bool muteDring)
|
|
: lrc_(std::make_unique<Lrc>(willMigrateCb, didMigrateCb, muteDring))
|
|
, renderer_(std::make_unique<RenderManager>(lrc_->getAVModel()))
|
|
, updateManager_(std::make_unique<UpdateManager>(updateUrl, connectivityMonitor, this))
|
|
{
|
|
lrc_->holdConferences = false;
|
|
};
|
|
|
|
VectorString
|
|
LRCInstance::getConferenceSubcalls(const QString& callId)
|
|
{
|
|
return lrc_->getConferenceSubcalls(callId);
|
|
}
|
|
|
|
RenderManager*
|
|
LRCInstance::renderer()
|
|
{
|
|
return renderer_.get();
|
|
}
|
|
|
|
UpdateManager*
|
|
LRCInstance::getUpdateManager()
|
|
{
|
|
return updateManager_.get();
|
|
}
|
|
|
|
void
|
|
LRCInstance::connectivityChanged()
|
|
{
|
|
lrc_->connectivityChanged();
|
|
}
|
|
|
|
NewAccountModel&
|
|
LRCInstance::accountModel()
|
|
{
|
|
return lrc_->getAccountModel();
|
|
}
|
|
|
|
BehaviorController&
|
|
LRCInstance::behaviorController()
|
|
{
|
|
return lrc_->getBehaviorController();
|
|
}
|
|
|
|
DataTransferModel&
|
|
LRCInstance::dataTransferModel()
|
|
{
|
|
return lrc_->getDataTransferModel();
|
|
}
|
|
|
|
AVModel&
|
|
LRCInstance::avModel()
|
|
{
|
|
return lrc_->getAVModel();
|
|
}
|
|
|
|
PluginModel&
|
|
LRCInstance::pluginModel()
|
|
{
|
|
return lrc_->getPluginModel();
|
|
}
|
|
|
|
bool
|
|
LRCInstance::isConnected()
|
|
{
|
|
return lrc_->isConnected();
|
|
}
|
|
|
|
VectorString
|
|
LRCInstance::getActiveCalls()
|
|
{
|
|
return lrc_->activeCalls();
|
|
}
|
|
|
|
const account::Info&
|
|
LRCInstance::getAccountInfo(const QString& accountId)
|
|
{
|
|
return accountModel().getAccountInfo(accountId);
|
|
}
|
|
|
|
const account::Info&
|
|
LRCInstance::getCurrentAccountInfo()
|
|
{
|
|
return getAccountInfo(getCurrAccId());
|
|
}
|
|
|
|
bool
|
|
LRCInstance::hasActiveCall(bool withVideo)
|
|
{
|
|
auto activeCalls = lrc_->activeCalls();
|
|
auto accountList = accountModel().getAccountList();
|
|
bool result = false;
|
|
for (const auto& callId : activeCalls) {
|
|
for (const auto& accountId : accountList) {
|
|
auto& accountInfo = accountModel().getAccountInfo(accountId);
|
|
if (withVideo) {
|
|
if (accountInfo.callModel->hasCall(callId))
|
|
return true;
|
|
} else {
|
|
if (accountInfo.callModel->hasCall(callId)) {
|
|
auto call = accountInfo.callModel->getCall(callId);
|
|
result |= !(call.isAudioOnly || call.videoMuted);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
QString
|
|
LRCInstance::getCallIdForConversationUid(const QString& convUid, const QString& accountId)
|
|
{
|
|
const auto& convInfo = getConversationFromConvUid(convUid, accountId);
|
|
if (convInfo.uid.isEmpty()) {
|
|
return {};
|
|
}
|
|
return convInfo.confId.isEmpty() ? convInfo.callId : convInfo.confId;
|
|
}
|
|
|
|
const call::Info*
|
|
LRCInstance::getCallInfo(const QString& callId, const QString& accountId)
|
|
{
|
|
try {
|
|
auto& accInfo = accountModel().getAccountInfo(accountId);
|
|
if (!accInfo.callModel->hasCall(callId)) {
|
|
return nullptr;
|
|
}
|
|
return &accInfo.callModel->getCall(callId);
|
|
} catch (...) {
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
const call::Info*
|
|
LRCInstance::getCallInfoForConversation(const conversation::Info& convInfo, bool forceCallOnly)
|
|
{
|
|
try {
|
|
auto accountId = convInfo.accountId;
|
|
auto& accInfo = accountModel().getAccountInfo(accountId);
|
|
auto callId = forceCallOnly
|
|
? convInfo.callId
|
|
: (convInfo.confId.isEmpty() ? convInfo.callId : convInfo.confId);
|
|
if (!accInfo.callModel->hasCall(callId)) {
|
|
return nullptr;
|
|
}
|
|
return &accInfo.callModel->getCall(callId);
|
|
} catch (...) {
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
const conversation::Info&
|
|
LRCInstance::getConversationFromConvUid(const QString& convUid, const QString& accountId)
|
|
{
|
|
auto& accInfo = accountModel().getAccountInfo(!accountId.isEmpty() ? accountId : getCurrAccId());
|
|
auto& convModel = accInfo.conversationModel;
|
|
return convModel->getConversationForUid(convUid).value_or(invalid);
|
|
}
|
|
|
|
const conversation::Info&
|
|
LRCInstance::getConversationFromPeerUri(const QString& peerUri, const QString& accountId)
|
|
{
|
|
auto& accInfo = accountModel().getAccountInfo(!accountId.isEmpty() ? accountId : getCurrAccId());
|
|
auto& convModel = accInfo.conversationModel;
|
|
return convModel->getConversationForPeerUri(peerUri).value_or(invalid);
|
|
}
|
|
|
|
const conversation::Info&
|
|
LRCInstance::getConversationFromCallId(const QString& callId, const QString& accountId)
|
|
{
|
|
auto& accInfo = accountModel().getAccountInfo(!accountId.isEmpty() ? accountId : getCurrAccId());
|
|
auto& convModel = accInfo.conversationModel;
|
|
return convModel->getConversationForCallId(callId).value_or(invalid);
|
|
}
|
|
|
|
ConversationModel*
|
|
LRCInstance::getCurrentConversationModel()
|
|
{
|
|
return getCurrentAccountInfo().conversationModel.get();
|
|
}
|
|
|
|
NewCallModel*
|
|
LRCInstance::getCurrentCallModel()
|
|
{
|
|
return getCurrentAccountInfo().callModel.get();
|
|
}
|
|
|
|
ContactModel*
|
|
LRCInstance::getCurrentContactModel()
|
|
{
|
|
return getCurrentAccountInfo().contactModel.get();
|
|
}
|
|
|
|
const QString&
|
|
LRCInstance::getCurrAccId()
|
|
{
|
|
if (selectedAccountId_.isEmpty()) {
|
|
auto accountList = accountModel().getAccountList();
|
|
if (accountList.size())
|
|
selectedAccountId_ = accountList.at(0);
|
|
}
|
|
return selectedAccountId_;
|
|
}
|
|
|
|
void
|
|
LRCInstance::setSelectedAccountId(const QString& accountId)
|
|
{
|
|
if (accountId == selectedAccountId_)
|
|
return; // No need to select current selected account
|
|
|
|
selectedAccountId_ = accountId;
|
|
|
|
// Last selected account should be set as preferred.
|
|
accountModel().setTopAccount(accountId);
|
|
|
|
Q_EMIT currentAccountChanged();
|
|
}
|
|
|
|
int
|
|
LRCInstance::getCurrentAccountIndex()
|
|
{
|
|
for (int i = 0; i < accountModel().getAccountList().size(); i++) {
|
|
if (accountModel().getAccountList()[i] == getCurrAccId()) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void
|
|
LRCInstance::setAvatarForAccount(const QPixmap& avatarPixmap, const QString& accountID)
|
|
{
|
|
QByteArray ba;
|
|
QBuffer bu(&ba);
|
|
bu.open(QIODevice::WriteOnly);
|
|
avatarPixmap.save(&bu, "PNG");
|
|
auto str = QString::fromLocal8Bit(ba.toBase64());
|
|
accountModel().setAvatar(accountID, str);
|
|
}
|
|
|
|
void
|
|
LRCInstance::setCurrAccAvatar(const QPixmap& avatarPixmap)
|
|
{
|
|
QByteArray ba;
|
|
QBuffer bu(&ba);
|
|
bu.open(QIODevice::WriteOnly);
|
|
avatarPixmap.save(&bu, "PNG");
|
|
auto str = QString::fromLocal8Bit(ba.toBase64());
|
|
accountModel().setAvatar(getCurrAccId(), str);
|
|
}
|
|
|
|
void
|
|
LRCInstance::setCurrAccAvatar(const QString& avatar)
|
|
{
|
|
accountModel().setAvatar(getCurrAccId(), avatar);
|
|
}
|
|
|
|
void
|
|
LRCInstance::setCurrAccDisplayName(const QString& displayName)
|
|
{
|
|
auto accountId = getCurrAccId();
|
|
accountModel().setAlias(accountId, displayName);
|
|
/*
|
|
* Force save to .yml.
|
|
*/
|
|
auto confProps = accountModel().getAccountConfig(accountId);
|
|
accountModel().setAccountConfig(accountId, confProps);
|
|
}
|
|
|
|
const account::ConfProperties_t&
|
|
LRCInstance::getCurrAccConfig()
|
|
{
|
|
return getCurrentAccountInfo().confProperties;
|
|
}
|
|
|
|
int
|
|
LRCInstance::indexOf(const QString& convId)
|
|
{
|
|
auto& convs = getCurrentConversationModel()->getConversations();
|
|
auto it = std::find_if(convs.begin(),
|
|
convs.end(),
|
|
[convId](const lrc::api::conversation::Info& conv) {
|
|
return conv.uid == convId;
|
|
});
|
|
return it != convs.end() ? std::distance(convs.begin(), it) : -1;
|
|
}
|
|
|
|
void
|
|
LRCInstance::subscribeToDebugReceived()
|
|
{
|
|
lrc_->subscribeToDebugReceived();
|
|
}
|
|
|
|
void
|
|
LRCInstance::startAudioMeter(bool async)
|
|
{
|
|
auto f = [this] {
|
|
if (!getActiveCalls().size()) {
|
|
avModel().startAudioDevice();
|
|
}
|
|
avModel().setAudioMeterState(true);
|
|
};
|
|
if (async) {
|
|
QtConcurrent::run(f);
|
|
} else {
|
|
f();
|
|
}
|
|
}
|
|
|
|
void
|
|
LRCInstance::stopAudioMeter(bool async)
|
|
{
|
|
auto f = [this] {
|
|
if (!getActiveCalls().size()) {
|
|
avModel().stopAudioDevice();
|
|
}
|
|
avModel().setAudioMeterState(false);
|
|
};
|
|
if (async) {
|
|
QtConcurrent::run(f);
|
|
} else {
|
|
f();
|
|
}
|
|
}
|
|
|
|
QString
|
|
LRCInstance::getContentDraft(const QString& convUid, const QString& accountId)
|
|
{
|
|
auto draftKey = accountId + "_" + convUid;
|
|
return contentDrafts_[draftKey];
|
|
}
|
|
|
|
void
|
|
LRCInstance::setContentDraft(const QString& convUid,
|
|
const QString& accountId,
|
|
const QString& content)
|
|
{
|
|
auto draftKey = accountId + "_" + convUid;
|
|
contentDrafts_[draftKey] = content;
|
|
// this signal is only needed to update the current smartlist
|
|
Q_EMIT draftSaved(convUid);
|
|
}
|
|
|
|
void
|
|
LRCInstance::pushlastConference(const QString& confId, const QString& callId)
|
|
{
|
|
lastConferences_[confId] = callId;
|
|
}
|
|
|
|
QString
|
|
LRCInstance::poplastConference(const QString& confId)
|
|
{
|
|
QString callId = {};
|
|
auto iter = lastConferences_.find(confId);
|
|
if (iter != lastConferences_.end()) {
|
|
callId = iter.value();
|
|
lastConferences_.erase(iter);
|
|
}
|
|
return callId;
|
|
}
|
|
|
|
void
|
|
LRCInstance::selectConversation(const QString& convId, const QString& accountId)
|
|
{
|
|
// if the account is not currently selected, do that first, then
|
|
// proceed to select the conversation
|
|
if (!accountId.isEmpty() && accountId != getCurrAccId()) {
|
|
Utils::oneShotConnect(this, &LRCInstance::currentAccountChanged, [this, convId] {
|
|
set_selectedConvUid(convId);
|
|
});
|
|
setSelectedAccountId(accountId);
|
|
return;
|
|
}
|
|
set_selectedConvUid(convId);
|
|
}
|
|
|
|
void
|
|
LRCInstance::deselectConversation()
|
|
{
|
|
set_selectedConvUid();
|
|
}
|
|
|
|
void
|
|
LRCInstance::finish()
|
|
{
|
|
renderer_.reset();
|
|
lrc_.reset();
|
|
}
|