mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-17 11:28:07 +00:00
Remove storing core from GUI on fields. Core should never be stored in GUI because they are managed by CPP and not QML. Fix crashes on account settings. Add missing exception verbosing.
423 lines
16 KiB
C++
423 lines
16 KiB
C++
/*
|
|
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
*
|
|
* This file is part of linphone-desktop
|
|
* (see https://www.linphone.org).
|
|
*
|
|
* 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 "AccountModel.hpp"
|
|
|
|
#include "core/path/Paths.hpp"
|
|
#include "model/core/CoreModel.hpp"
|
|
#include "tool/Utils.hpp"
|
|
#include "tool/providers/AvatarProvider.hpp"
|
|
#include <QDebug>
|
|
#include <QUrl>
|
|
|
|
DEFINE_ABSTRACT_OBJECT(AccountModel)
|
|
|
|
AccountModel::AccountModel(const std::shared_ptr<linphone::Account> &account, QObject *parent)
|
|
: ::Listener<linphone::Account, linphone::AccountListener>(account, parent) {
|
|
mustBeInLinphoneThread(getClassName());
|
|
connect(CoreModel::getInstance().get(), &CoreModel::defaultAccountChanged, this,
|
|
&AccountModel::onDefaultAccountChanged);
|
|
|
|
// Hack because Account doesn't provide callbacks on updated data
|
|
connect(this, &AccountModel::defaultAccountChanged, this, [this]() {
|
|
emit pictureUriChanged(Utils::coreStringToAppString(mMonitor->getParams()->getPictureUri()));
|
|
emit displayNameChanged(
|
|
Utils::coreStringToAppString(mMonitor->getParams()->getIdentityAddress()->getDisplayName()));
|
|
});
|
|
|
|
connect(CoreModel::getInstance().get(), &CoreModel::unreadNotificationsChanged, this, [this]() {
|
|
emit unreadNotificationsChanged(0 /*mMonitor->getUnreadChatMessageCount()*/,
|
|
mMonitor->getMissedCallsCount()); // TODO
|
|
});
|
|
}
|
|
|
|
AccountModel::~AccountModel() {
|
|
mustBeInLinphoneThread("~" + getClassName());
|
|
}
|
|
|
|
void AccountModel::onRegistrationStateChanged(const std::shared_ptr<linphone::Account> &account,
|
|
linphone::RegistrationState state,
|
|
const std::string &message) {
|
|
emit registrationStateChanged(account, state, message);
|
|
}
|
|
|
|
void AccountModel::onMessageWaitingIndicationChanged(
|
|
const std::shared_ptr<linphone::Account> &account,
|
|
const std::shared_ptr<const linphone::MessageWaitingIndication> &mwi) {
|
|
auto userData = getUserData(account);
|
|
if (!userData) userData = std::make_shared<AccountUserData>();
|
|
userData->showMwi = mwi->hasMessageWaiting();
|
|
for (auto summary : mwi->getSummaries()) {
|
|
qInfo() << "[MWI] new" << summary->getNbNew() << "new+urgent" << summary->getNbNewUrgent() << "old"
|
|
<< summary->getNbOld() << "old+urgent" << summary->getNbOldUrgent();
|
|
|
|
userData->voicemailCount = summary->getNbNew();
|
|
emit voicemailCountChanged(summary->getNbNew());
|
|
}
|
|
setUserData(account, userData);
|
|
emit showMwiChanged(mwi->hasMessageWaiting());
|
|
}
|
|
|
|
void AccountModel::setPictureUri(QString uri) {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
auto params = mMonitor->getParams()->clone();
|
|
auto oldPictureUri = Utils::coreStringToAppString(params->getPictureUri());
|
|
if (!oldPictureUri.isEmpty()) {
|
|
QString appPrefix = QStringLiteral("image://%1/").arg(AvatarProvider::ProviderId);
|
|
if (oldPictureUri.startsWith(appPrefix)) {
|
|
oldPictureUri = Paths::getAvatarsDirPath() + oldPictureUri.mid(appPrefix.length());
|
|
}
|
|
QFile oldPicture(oldPictureUri);
|
|
if (!oldPicture.remove()) qWarning() << log().arg("Cannot delete old avatar file at " + oldPictureUri);
|
|
}
|
|
params->setPictureUri(Utils::appStringToCoreString(uri));
|
|
mMonitor->setParams(params);
|
|
// Hack because Account doesn't provide callbacks on updated data
|
|
// emit pictureUriChanged(uri);
|
|
auto core = CoreModel::getInstance()->getCore();
|
|
emit CoreModel::getInstance()->defaultAccountChanged(core, core->getDefaultAccount());
|
|
}
|
|
|
|
void AccountModel::onDefaultAccountChanged() {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
emit defaultAccountChanged(CoreModel::getInstance()->getCore()->getDefaultAccount() == mMonitor);
|
|
}
|
|
|
|
void AccountModel::setDefault() {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
auto core = CoreModel::getInstance()->getCore();
|
|
core->setDefaultAccount(mMonitor);
|
|
}
|
|
|
|
void AccountModel::removeAccount() {
|
|
CoreModel::getInstance()->getCore()->removeAccount(mMonitor);
|
|
removeUserData(mMonitor);
|
|
emit removed();
|
|
}
|
|
|
|
void AccountModel::resetMissedCallsCount() {
|
|
mMonitor->resetMissedCallsCount();
|
|
emit unreadNotificationsChanged(0 /*mMonitor->getUnreadChatMessageCount()*/,
|
|
mMonitor->getMissedCallsCount()); // TODO
|
|
}
|
|
|
|
void AccountModel::refreshUnreadNotifications() {
|
|
emit unreadNotificationsChanged(0 /*mMonitor->getUnreadChatMessageCount()*/,
|
|
mMonitor->getMissedCallsCount()); // TODO
|
|
}
|
|
|
|
int AccountModel::getMissedCallsCount() const {
|
|
return mMonitor->getMissedCallsCount();
|
|
}
|
|
|
|
int AccountModel::getUnreadMessagesCount() const {
|
|
return mMonitor->getUnreadChatMessageCount();
|
|
}
|
|
|
|
void AccountModel::setDisplayName(QString displayName) {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
auto params = mMonitor->getParams()->clone();
|
|
auto address = params->getIdentityAddress()->clone();
|
|
address->setDisplayName(Utils::appStringToCoreString(displayName));
|
|
params->setIdentityAddress(address);
|
|
mMonitor->setParams(params);
|
|
// Hack because Account doesn't provide callbacks on updated data
|
|
// emit displayNameChanged(displayName);
|
|
auto core = CoreModel::getInstance()->getCore();
|
|
emit CoreModel::getInstance()->defaultAccountChanged(core, core->getDefaultAccount());
|
|
}
|
|
|
|
void AccountModel::setDialPlan(int index) {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
std::string callingCode = "";
|
|
std::string countryCode = "";
|
|
if (index != -1) {
|
|
auto plans = linphone::Factory::get()->getDialPlans();
|
|
std::vector<std::shared_ptr<linphone::DialPlan>> vectorPlans(plans.begin(), plans.end());
|
|
auto plan = vectorPlans[index];
|
|
callingCode = plan->getCountryCallingCode();
|
|
countryCode = plan->getIsoCountryCode();
|
|
}
|
|
auto params = mMonitor->getParams()->clone();
|
|
params->setInternationalPrefix(callingCode);
|
|
params->setInternationalPrefixIsoCountryCode(countryCode);
|
|
mMonitor->setParams(params);
|
|
emit dialPlanChanged(index);
|
|
}
|
|
|
|
void AccountModel::setRegisterEnabled(bool enabled) {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
auto params = mMonitor->getParams()->clone();
|
|
params->enableRegister(enabled);
|
|
mMonitor->setParams(params);
|
|
emit registerEnabledChanged(enabled);
|
|
}
|
|
|
|
std::string AccountModel::getConfigAccountUiSection() {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
return "ui_" + mMonitor->getParams()->getIdentityAddress()->asStringUriOnly();
|
|
}
|
|
|
|
bool AccountModel::getNotificationsAllowed() {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
return mMonitor->getCore()->getConfig()->getBool(getConfigAccountUiSection(), "notifications_allowed", true);
|
|
}
|
|
|
|
void AccountModel::setNotificationsAllowed(bool value) {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
mMonitor->getCore()->getConfig()->setBool(getConfigAccountUiSection(), "notifications_allowed", value);
|
|
emit notificationsAllowedChanged(value);
|
|
}
|
|
|
|
QString AccountModel::getMwiServerAddress() const {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
return Utils::coreStringToAppString(mMonitor->getParams()->getMwiServerAddress()->asString());
|
|
}
|
|
|
|
void AccountModel::setMwiServerAddress(QString value) {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
auto address = value.isEmpty()
|
|
? nullptr
|
|
: CoreModel::getInstance()->getCore()->interpretUrl(Utils::appStringToCoreString(value), false);
|
|
|
|
if (value.isEmpty() || address) {
|
|
auto params = mMonitor->getParams();
|
|
auto oldAddress = params->getMwiServerAddress();
|
|
if (address != oldAddress && (!address || !address->weakEqual(oldAddress))) {
|
|
auto newParams = params->clone();
|
|
newParams->setMwiServerAddress(address);
|
|
if (!mMonitor->setParams(newParams)) emit mwiServerAddressChanged(value);
|
|
}
|
|
} else qWarning() << "Unable to set MWI address, failed creating address from" << value;
|
|
}
|
|
|
|
linphone::TransportType AccountModel::getTransport() const {
|
|
return mMonitor->getParams()->getTransport();
|
|
}
|
|
|
|
void AccountModel::setTransport(linphone::TransportType value) {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
auto params = mMonitor->getParams()->clone();
|
|
params->setTransport(value);
|
|
mMonitor->setParams(params);
|
|
emit transportChanged(value);
|
|
}
|
|
|
|
QString AccountModel::getServerAddress() const {
|
|
return Utils::coreStringToAppString(mMonitor->getParams()->getServerAddress()->asString());
|
|
}
|
|
|
|
void AccountModel::setServerAddress(QString value) {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
auto params = mMonitor->getParams()->clone();
|
|
auto address = CoreModel::getInstance()->getCore()->interpretUrl(Utils::appStringToCoreString(value), false);
|
|
if (address) {
|
|
params->setServerAddress(address);
|
|
mMonitor->setParams(params);
|
|
emit serverAddressChanged(value);
|
|
} else qWarning() << "Unable to set ServerAddress, failed creating address from" << value;
|
|
}
|
|
|
|
bool AccountModel::getOutboundProxyEnabled() const {
|
|
return mMonitor->getParams()->outboundProxyEnabled();
|
|
}
|
|
|
|
void AccountModel::setOutboundProxyEnabled(bool value) {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
auto params = mMonitor->getParams()->clone();
|
|
params->enableOutboundProxy(value);
|
|
mMonitor->setParams(params);
|
|
emit outboundProxyEnabledChanged(value);
|
|
}
|
|
|
|
QString AccountModel::getStunServer() const {
|
|
auto policy = mMonitor->getParams()->getNatPolicy();
|
|
if (policy) return Utils::coreStringToAppString(policy->getStunServer());
|
|
else return QString();
|
|
}
|
|
|
|
void AccountModel::setStunServer(QString value) {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
auto params = mMonitor->getParams()->clone();
|
|
auto policy = params->getNatPolicy();
|
|
if (!policy) policy = mMonitor->getCore()->createNatPolicy();
|
|
policy->setStunServer(Utils::appStringToCoreString(value));
|
|
policy->enableStun(!value.isEmpty());
|
|
params->setNatPolicy(policy);
|
|
mMonitor->setParams(params);
|
|
emit stunServerChanged(value);
|
|
}
|
|
|
|
bool AccountModel::getIceEnabled() const {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
auto policy = mMonitor->getParams()->getNatPolicy();
|
|
return policy && policy->iceEnabled();
|
|
}
|
|
|
|
void AccountModel::setIceEnabled(bool value) {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
auto params = mMonitor->getParams()->clone();
|
|
auto policy = params->getNatPolicy();
|
|
if (!policy) policy = mMonitor->getCore()->createNatPolicy();
|
|
policy->enableIce(value);
|
|
params->setNatPolicy(policy);
|
|
mMonitor->setParams(params);
|
|
emit iceEnabledChanged(value);
|
|
}
|
|
|
|
bool AccountModel::getAvpfEnabled() const {
|
|
return mMonitor->getParams()->getAvpfMode() == linphone::AVPFMode::Enabled;
|
|
}
|
|
|
|
void AccountModel::setAvpfEnabled(bool value) {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
auto params = mMonitor->getParams()->clone();
|
|
params->setAvpfMode(value ? linphone::AVPFMode::Enabled : linphone::AVPFMode::Disabled);
|
|
mMonitor->setParams(params);
|
|
emit avpfEnabledChanged(value);
|
|
}
|
|
|
|
bool AccountModel::getBundleModeEnabled() const {
|
|
return mMonitor->getParams()->rtpBundleEnabled();
|
|
}
|
|
|
|
void AccountModel::setBundleModeEnabled(bool value) {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
auto params = mMonitor->getParams()->clone();
|
|
params->enableRtpBundle(value);
|
|
mMonitor->setParams(params);
|
|
emit bundleModeEnabledChanged(value);
|
|
}
|
|
|
|
int AccountModel::getExpire() const {
|
|
return mMonitor->getParams()->getExpires();
|
|
}
|
|
|
|
void AccountModel::setExpire(int value) {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
auto params = mMonitor->getParams()->clone();
|
|
params->setExpires(value);
|
|
mMonitor->setParams(params);
|
|
emit expireChanged(value);
|
|
}
|
|
|
|
QString AccountModel::getConferenceFactoryAddress() const {
|
|
auto confAddress = mMonitor->getParams()->getConferenceFactoryAddress();
|
|
return confAddress ? Utils::coreStringToAppString(confAddress->asString()) : QString();
|
|
}
|
|
|
|
void AccountModel::setConferenceFactoryAddress(QString value) {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
auto params = mMonitor->getParams()->clone();
|
|
auto address = value.isEmpty()
|
|
? nullptr
|
|
: CoreModel::getInstance()->getCore()->interpretUrl(Utils::appStringToCoreString(value), false);
|
|
if (value.isEmpty() || address) {
|
|
params->setConferenceFactoryAddress(address);
|
|
mMonitor->setParams(params);
|
|
emit conferenceFactoryAddressChanged(value);
|
|
} else qWarning() << "Unable to set ConferenceFactoryAddress address, failed creating address from" << value;
|
|
}
|
|
|
|
QString AccountModel::getAudioVideoConferenceFactoryAddress() const {
|
|
auto confAddress = mMonitor->getParams()->getAudioVideoConferenceFactoryAddress();
|
|
return confAddress ? Utils::coreStringToAppString(confAddress->asString()) : QString();
|
|
}
|
|
|
|
void AccountModel::setAudioVideoConferenceFactoryAddress(QString value) {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
auto params = mMonitor->getParams()->clone();
|
|
auto address = value.isEmpty()
|
|
? nullptr
|
|
: CoreModel::getInstance()->getCore()->interpretUrl(Utils::appStringToCoreString(value), false);
|
|
if (value.isEmpty() || address) {
|
|
params->setAudioVideoConferenceFactoryAddress(address);
|
|
mMonitor->setParams(params);
|
|
emit audioVideoConferenceFactoryAddressChanged(value);
|
|
} else
|
|
qWarning() << "Unable to set AudioVideoConferenceFactoryAddress address, failed creating address from" << value;
|
|
}
|
|
|
|
QString AccountModel::getLimeServerUrl() const {
|
|
return Utils::coreStringToAppString(mMonitor->getParams()->getLimeServerUrl());
|
|
}
|
|
|
|
void AccountModel::setLimeServerUrl(QString value) {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
auto params = mMonitor->getParams()->clone();
|
|
params->setLimeServerUrl(Utils::appStringToCoreString(value));
|
|
mMonitor->setParams(params);
|
|
emit limeServerUrlChanged(value);
|
|
}
|
|
|
|
QString AccountModel::dialPlanAsString(const std::shared_ptr<linphone::DialPlan> &dialPlan) {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
return Utils::coreStringToAppString(dialPlan->getFlag() + " " + dialPlan->getCountry() + " | +" +
|
|
dialPlan->getCountryCallingCode());
|
|
}
|
|
|
|
int AccountModel::getVoicemailCount() {
|
|
auto userData = getUserData(mMonitor);
|
|
if (userData) return userData->voicemailCount;
|
|
else return 0;
|
|
}
|
|
|
|
bool AccountModel::getShowMwi() {
|
|
auto userData = getUserData(mMonitor);
|
|
if (userData) return userData->showMwi;
|
|
else return false;
|
|
}
|
|
|
|
void AccountModel::setVoicemailAddress(QString value) {
|
|
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
|
|
auto params = mMonitor->getParams()->clone();
|
|
auto address = value.isEmpty()
|
|
? nullptr
|
|
: CoreModel::getInstance()->getCore()->interpretUrl(Utils::appStringToCoreString(value), false);
|
|
if (value.isEmpty() || address) {
|
|
params->setVoicemailAddress(address);
|
|
mMonitor->setParams(params);
|
|
emit voicemailAddressChanged(value);
|
|
} else qWarning() << "Unable to set VoicemailAddress, failed creating address from" << value;
|
|
}
|
|
|
|
QString AccountModel::getVoicemailAddress() const {
|
|
auto addr = mMonitor->getParams()->getVoicemailAddress();
|
|
return addr ? Utils::coreStringToAppString(addr->asString()) : "";
|
|
}
|
|
|
|
// UserData (see hpp for explanations)
|
|
|
|
static QMap<const std::shared_ptr<linphone::Account>, std::shared_ptr<AccountUserData>> userDataMap;
|
|
|
|
void AccountModel::setUserData(const std::shared_ptr<linphone::Account> &account,
|
|
std::shared_ptr<AccountUserData> &data) {
|
|
mustBeInLinphoneThread(sLog().arg(Q_FUNC_INFO));
|
|
userDataMap[account] = data;
|
|
}
|
|
std::shared_ptr<AccountUserData> AccountModel::getUserData(const std::shared_ptr<linphone::Account> &account) {
|
|
mustBeInLinphoneThread(sLog().arg(Q_FUNC_INFO));
|
|
if (userDataMap.contains(account)) return userDataMap.value(account);
|
|
else return nullptr;
|
|
}
|
|
void AccountModel::removeUserData(const std::shared_ptr<linphone::Account> &account) {
|
|
mustBeInLinphoneThread(sLog().arg(Q_FUNC_INFO));
|
|
userDataMap.remove(account);
|
|
}
|