/* * 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 . */ #include "SettingsModel.hpp" #include "core/path/Paths.hpp" #include "model/core/CoreModel.hpp" #include "model/tool/ToolModel.hpp" #include "tool/Utils.hpp" // ============================================================================= DEFINE_ABSTRACT_OBJECT(SettingsModel) using namespace std; const std::string SettingsModel::UiSection("ui"); std::shared_ptr SettingsModel::gSettingsModel; SettingsModel::SettingsModel() { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); connect(CoreModel::getInstance()->thread(), &QThread::finished, this, [this]() { // Model thread gSettingsModel = nullptr; }); auto core = CoreModel::getInstance()->getCore(); mConfig = core->getConfig(); CoreModel::getInstance()->getLogger()->applyConfig(mConfig); if (mConfig->hasEntry(UiSection, "do_not_disturb") == 1) { enableDnd(dndEnabled()); } QObject::connect( CoreModel::getInstance().get(), &CoreModel::globalStateChanged, this, [this](const std::shared_ptr &core, linphone::GlobalState gstate, const std::string &message) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); if (gstate == linphone::GlobalState::On) { // reached when misc|config-uri is set in config and app starts // and after config is fetched. notifyConfigReady(); } }); QObject::connect(CoreModel::getInstance().get(), &CoreModel::configuringStatus, this, [this](const std::shared_ptr &core, linphone::ConfiguringState status, const std::string &message) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); if (status == linphone::ConfiguringState::Successful) { mConfig = core->getConfig(); notifyConfigReady(); } }); } SettingsModel::~SettingsModel() { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); } shared_ptr SettingsModel::create() { // auto model = Utils::makeQObject_ptr(); if (gSettingsModel) return gSettingsModel; auto model = make_shared(); gSettingsModel = model; return model; } shared_ptr SettingsModel::getInstance() { return gSettingsModel; } bool SettingsModel::isReadOnly(const std::string §ion, const std::string &name) const { return mConfig->hasEntry(section, name + "/readonly"); } std::string SettingsModel::getEntryFullName(const std::string §ion, const std::string &name) const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); return isReadOnly(section, name) ? name + "/readonly" : name; } // ============================================================================= // Audio. // ============================================================================= bool SettingsModel::getIsInCall() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); return CoreModel::getInstance()->getCore()->getCallsNb() != 0; } void SettingsModel::resetCaptureGraph() { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); deleteCaptureGraph(); createCaptureGraph(); } void SettingsModel::createCaptureGraph() { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); mSimpleCaptureGraph = new MediastreamerUtils::SimpleCaptureGraph(Utils::appStringToCoreString(getCaptureDevice()["id"].toString()), Utils::appStringToCoreString(getPlaybackDevice()["id"].toString())); mSimpleCaptureGraph->start(); emit captureGraphRunningChanged(getCaptureGraphRunning()); } void SettingsModel::startCaptureGraph() { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); if (!getIsInCall()) { if (!mSimpleCaptureGraph) { qDebug() << "Starting capture graph [" << mCaptureGraphListenerCount << "]"; createCaptureGraph(); } ++mCaptureGraphListenerCount; } } void SettingsModel::stopCaptureGraph() { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); if (mCaptureGraphListenerCount > 0) { if (--mCaptureGraphListenerCount == 0) { qDebug() << "Stopping capture graph [" << mCaptureGraphListenerCount << "]"; deleteCaptureGraph(); } } } void SettingsModel::stopCaptureGraphs() { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); if (mCaptureGraphListenerCount > 0) { mCaptureGraphListenerCount = 0; deleteCaptureGraph(); } } void SettingsModel::deleteCaptureGraph() { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); if (mSimpleCaptureGraph) { if (mSimpleCaptureGraph->isRunning()) { mSimpleCaptureGraph->stop(); } delete mSimpleCaptureGraph; mSimpleCaptureGraph = nullptr; } } // Force a call on the 'detect' method of all audio filters, updating new or removed devices void SettingsModel::accessCallSettings() { // Audio mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); CoreModel::getInstance()->getCore()->reloadSoundDevices(); emit captureDevicesChanged(getCaptureDevices()); emit playbackDevicesChanged(getPlaybackDevices()); emit playbackDeviceChanged(getPlaybackDevice()); emit ringerDevicesChanged(getRingerDevices()); emit ringerDeviceChanged(getRingerDevice()); emit captureDeviceChanged(getCaptureDevice()); emit playbackGainChanged(getPlaybackGain()); emit captureGainChanged(getCaptureGain()); // Media cards must not be used twice (capture card + call) else we will get latencies issues and bad echo // calibrations in call. if (!getIsInCall()) { qDebug() << "Starting capture graph from accessing audio panel"; startCaptureGraph(); } // Video CoreModel::getInstance()->getCore()->reloadVideoDevices(); emit videoDevicesChanged(getVideoDevices()); } void SettingsModel::closeCallSettings() { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); stopCaptureGraph(); emit captureGraphRunningChanged(getCaptureGraphRunning()); } bool SettingsModel::getCaptureGraphRunning() { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); return mSimpleCaptureGraph && mSimpleCaptureGraph->isRunning() && !getIsInCall(); } float SettingsModel::getMicVolume() { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); float v = 0.0; if (mSimpleCaptureGraph && mSimpleCaptureGraph->isRunning()) { v = mSimpleCaptureGraph->getCaptureVolume(); } emit micVolumeChanged(v); return v; } float SettingsModel::getPlaybackGain() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); float dbGain = CoreModel::getInstance()->getCore()->getPlaybackGainDb(); return MediastreamerUtils::dbToLinear(dbGain); } void SettingsModel::setPlaybackGain(float gain) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); float oldGain = getPlaybackGain(); CoreModel::getInstance()->getCore()->setPlaybackGainDb(MediastreamerUtils::linearToDb(gain)); if (mSimpleCaptureGraph && mSimpleCaptureGraph->isRunning()) { mSimpleCaptureGraph->setPlaybackGain(gain); } if ((int)(oldGain * 1000) != (int)(gain * 1000)) emit playbackGainChanged(gain); } float SettingsModel::getCaptureGain() const { mustBeInLinphoneThread(getClassName()); float dbGain = CoreModel::getInstance()->getCore()->getMicGainDb(); return MediastreamerUtils::dbToLinear(dbGain); } void SettingsModel::setCaptureGain(float gain) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); float oldGain = getCaptureGain(); CoreModel::getInstance()->getCore()->setMicGainDb(MediastreamerUtils::linearToDb(gain)); if (mSimpleCaptureGraph && mSimpleCaptureGraph->isRunning()) { mSimpleCaptureGraph->setCaptureGain(gain); } if ((int)(oldGain * 1000) != (int)(gain * 1000)) emit captureGainChanged(gain); } QVariantList SettingsModel::getCaptureDevices() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); shared_ptr core = CoreModel::getInstance()->getCore(); QVariantList list; for (const auto &device : core->getExtendedAudioDevices()) { if (device->hasCapability(linphone::AudioDevice::Capabilities::CapabilityRecord)) { list << ToolModel::createVariant(device); } } return list; } QVariantList SettingsModel::getPlaybackDevices() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); shared_ptr core = CoreModel::getInstance()->getCore(); QVariantList list; for (const auto &device : core->getExtendedAudioDevices()) { if (device->hasCapability(linphone::AudioDevice::Capabilities::CapabilityPlay)) list << ToolModel::createVariant(device); } return list; } QVariantList SettingsModel::getRingerDevices() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); shared_ptr core = CoreModel::getInstance()->getCore(); QVariantList list; for (const auto &device : core->getExtendedAudioDevices()) { if (device->hasCapability(linphone::AudioDevice::Capabilities::CapabilityPlay)) list << ToolModel::createVariant(device); } return list; } QStringList SettingsModel::getVideoDevices() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); auto core = CoreModel::getInstance()->getCore(); QStringList result; for (auto &device : core->getVideoDevicesList()) { result.append(Utils::coreStringToAppString(device)); } return result; } // ----------------------------------------------------------------------------- QVariantMap SettingsModel::getCaptureDevice() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); auto audioDevice = CoreModel::getInstance()->getCore()->getInputAudioDevice(); if (!audioDevice) audioDevice = CoreModel::getInstance()->getCore()->getDefaultInputAudioDevice(); return ToolModel::createVariant(audioDevice); } void SettingsModel::setCaptureDevice(const QVariantMap &device) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); auto audioDevice = ToolModel::findAudioDevice(device["id"].toString(), linphone::AudioDevice::Capabilities::CapabilityRecord); if (audioDevice) { CoreModel::getInstance()->getCore()->setDefaultInputAudioDevice(audioDevice); CoreModel::getInstance()->getCore()->setInputAudioDevice(audioDevice); emit captureDeviceChanged(device); resetCaptureGraph(); } else qWarning() << "Cannot set Capture device. The ID cannot be matched with an existant device : " << device; } linphone::Conference::Layout SettingsModel::getDefaultConferenceLayout() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); return CoreModel::getInstance()->getCore()->getDefaultConferenceLayout(); } void SettingsModel::setDefaultConferenceLayout(const linphone::Conference::Layout layout) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); CoreModel::getInstance()->getCore()->setDefaultConferenceLayout(layout); emit conferenceLayoutChanged(); } linphone::MediaEncryption SettingsModel::getDefaultMediaEncryption() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); return CoreModel::getInstance()->getCore()->getMediaEncryption(); } void SettingsModel::setDefaultMediaEncryption(const linphone::MediaEncryption encryption) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); CoreModel::getInstance()->getCore()->setMediaEncryption(encryption); emit mediaEncryptionChanged(); } bool SettingsModel::getMediaEncryptionMandatory() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); return CoreModel::getInstance()->getCore()->isMediaEncryptionMandatory(); } void SettingsModel::setMediaEncryptionMandatory(bool mandatory) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); CoreModel::getInstance()->getCore()->setMediaEncryptionMandatory(mandatory); emit mediaEncryptionMandatoryChanged(); } // ----------------------------------------------------------------------------- QVariantMap SettingsModel::getPlaybackDevice() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); auto audioDevice = CoreModel::getInstance()->getCore()->getOutputAudioDevice(); if (!audioDevice) audioDevice = CoreModel::getInstance()->getCore()->getDefaultOutputAudioDevice(); return ToolModel::createVariant(audioDevice); } void SettingsModel::setPlaybackDevice(const QVariantMap &device) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); auto audioDevice = ToolModel::findAudioDevice(device["id"].toString(), linphone::AudioDevice::Capabilities::CapabilityPlay); if (audioDevice) { CoreModel::getInstance()->getCore()->setDefaultOutputAudioDevice(audioDevice); CoreModel::getInstance()->getCore()->setOutputAudioDevice(audioDevice); emit playbackDeviceChanged(device); resetCaptureGraph(); } else qWarning() << "Cannot set Playback device. The ID cannot be matched with an existant device : " << device; } // ----------------------------------------------------------------------------- QVariantMap SettingsModel::getRingerDevice() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); auto id = Utils::coreStringToAppString(CoreModel::getInstance()->getCore()->getRingerDevice()); auto audioDevice = ToolModel::findAudioDevice(id, linphone::AudioDevice::Capabilities::CapabilityPlay); return ToolModel::createVariant(audioDevice); } void SettingsModel::setRingerDevice(const QVariantMap &device) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); CoreModel::getInstance()->getCore()->setRingerDevice(Utils::appStringToCoreString(device["id"].toString())); emit ringerDeviceChanged(device); } // ----------------------------------------------------------------------------- QString SettingsModel::getVideoDevice() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); return Utils::coreStringToAppString(CoreModel::getInstance()->getCore()->getVideoDevice()); } void SettingsModel::setVideoDevice(const QString &device) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); CoreModel::getInstance()->getCore()->setVideoDevice(Utils::appStringToCoreString(device)); emit videoDeviceChanged(device); } bool SettingsModel::getVideoEnabled() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); return CoreModel::getInstance()->getCore()->videoEnabled(); } void SettingsModel::setVideoEnabled(const bool enabled) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); auto core = CoreModel::getInstance()->getCore(); core->enableVideoCapture(enabled); core->enableVideoDisplay(enabled); emit videoEnabledChanged(enabled); } // ----------------------------------------------------------------------------- bool SettingsModel::getEchoCancellationEnabled() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); return CoreModel::getInstance()->getCore()->echoCancellationEnabled(); } void SettingsModel::setEchoCancellationEnabled(bool status) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); CoreModel::getInstance()->getCore()->enableEchoCancellation(status); emit echoCancellationEnabledChanged(status); } void SettingsModel::startEchoCancellerCalibration() { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); CoreModel::getInstance()->getCore()->startEchoCancellerCalibration(); } int SettingsModel::getEchoCancellationCalibration() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); return CoreModel::getInstance()->getCore()->getEchoCancellationCalibration(); } bool SettingsModel::getAutomaticallyRecordCallsEnabled() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); return !!mConfig->getInt(UiSection, "automatically_record_calls", 0); } void SettingsModel::setAutomaticallyRecordCallsEnabled(bool enabled) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); mConfig->setInt(UiSection, "automatically_record_calls", enabled); emit automaticallyRecordCallsEnabledChanged(enabled); } // ============================================================================= // VFS. // ============================================================================= bool SettingsModel::getVfsEnabled() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); return !!mConfig->getInt(UiSection, "vfs_enabled", 0); } void SettingsModel::setVfsEnabled(bool enabled) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); mConfig->setInt(UiSection, "vfs_enabled", enabled); emit vfsEnabledChanged(enabled); } // ============================================================================= // Logs. // ============================================================================= bool SettingsModel::getLogsEnabled() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); return getLogsEnabled(mConfig); } void SettingsModel::setLogsEnabled(bool status) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); mConfig->setInt(UiSection, "logs_enabled", status); CoreModel::getInstance()->getLogger()->enable(status); emit logsEnabledChanged(status); } bool SettingsModel::getFullLogsEnabled() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); return getFullLogsEnabled(mConfig); } void SettingsModel::setFullLogsEnabled(bool status) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); mConfig->setInt(UiSection, "full_logs_enabled", status); CoreModel::getInstance()->getLogger()->enableFullLogs(status); emit fullLogsEnabledChanged(status); } bool SettingsModel::getLogsEnabled(const shared_ptr &config) { mustBeInLinphoneThread(sLog().arg(Q_FUNC_INFO)); return config ? config->getInt(UiSection, "logs_enabled", false) : true; } bool SettingsModel::getFullLogsEnabled(const shared_ptr &config) { mustBeInLinphoneThread(sLog().arg(Q_FUNC_INFO)); return config ? config->getInt(UiSection, "full_logs_enabled", false) : false; } QString SettingsModel::getLogsFolder() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); return getLogsFolder(mConfig); } QString SettingsModel::getLogsFolder(const shared_ptr &config) { mustBeInLinphoneThread(sLog().arg(Q_FUNC_INFO)); return config ? Utils::coreStringToAppString(config->getString( UiSection, "logs_folder", Utils::appStringToCoreString(Paths::getLogsDirPath()))) : Paths::getLogsDirPath(); } QString SettingsModel::getLogsUploadUrl() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); auto core = CoreModel::getInstance()->getCore(); return Utils::coreStringToAppString(core->getLogCollectionUploadServerUrl()); } void SettingsModel::setLogsUploadUrl(const QString &serverUrl) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); if (serverUrl != getLogsUploadUrl()) { auto core = CoreModel::getInstance()->getCore(); core->setLogCollectionUploadServerUrl(Utils::appStringToCoreString(serverUrl)); emit logsUploadUrlChanged(); } } void SettingsModel::cleanLogs() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); CoreModel::getInstance()->getCore()->resetLogCollection(); } void SettingsModel::sendLogs() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); auto core = CoreModel::getInstance()->getCore(); qInfo() << QStringLiteral("Send logs to: `%1` from `%2`.") .arg(Utils::coreStringToAppString(core->getLogCollectionUploadServerUrl())) .arg(Utils::coreStringToAppString(core->getLogCollectionPath())); core->uploadLogCollection(); } QString SettingsModel::getLogsEmail() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); return Utils::coreStringToAppString(mConfig->getString(UiSection, "logs_email", Constants::DefaultLogsEmail)); } // ============================================================================= // Do not disturb // ============================================================================= bool SettingsModel::dndEnabled(const shared_ptr &config) { mustBeInLinphoneThread(sLog().arg(Q_FUNC_INFO)); return config ? config->getInt(UiSection, "do_not_disturb", false) : false; } bool SettingsModel::dndEnabled() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); return dndEnabled(mConfig); } void SettingsModel::enableTones(const shared_ptr &config, bool enable) { mustBeInLinphoneThread(sLog().arg(Q_FUNC_INFO)); config->setInt("sound", "tone_indications", enable); // General tones config->setInt("misc", "tone_indications", enable); // Call tones } void SettingsModel::enableRinging(bool enable) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); mConfig->setInt("sound", "disable_ringing", !enable); // Ringing } void SettingsModel::enableDnd(bool enableDnd) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); enableTones(mConfig, !enableDnd); enableRinging(!enableDnd); mConfig->setInt(UiSection, "do_not_disturb", enableDnd); emit dndChanged(enableDnd); } bool SettingsModel::getIpv6Enabled() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); return CoreModel::getInstance()->getCore()->ipv6Enabled(); } void SettingsModel::setIpv6Enabled(bool status) { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); if (getIpv6Enabled() != status) { CoreModel::getInstance()->getCore()->enableIpv6(status); emit ipv6EnabledChanged(status); } } // ============================================================================= // Carddav storage list // ============================================================================= const std::shared_ptr SettingsModel::getCarddavListForNewFriends() { mustBeInLinphoneThread(sLog().arg(Q_FUNC_INFO)); auto core = CoreModel::getInstance()->getCore(); if (core) { auto config = core->getConfig(); auto listName = config->getString(UiSection, "friend_list_to_store_newly_created_contacts", ""); if (!listName.empty()) return core->getFriendListByName(listName); else return nullptr; } else return nullptr; } void SettingsModel::setCarddavListForNewFriends(std::string name) { mustBeInLinphoneThread(sLog().arg(Q_FUNC_INFO)); auto core = CoreModel::getInstance()->getCore(); if (core) { auto config = core->getConfig(); config->setString(UiSection, "friend_list_to_store_newly_created_contacts", name); } } // ============================================================================= // Device name. // ============================================================================= QString SettingsModel::getDeviceName(const std::shared_ptr &config) { return Utils::coreStringToAppString( config->getString(UiSection, "device_name", Utils::appStringToCoreString(QSysInfo::machineHostName()))); } // ============================================================================== // Clears the local "ldap_friends" friend list upon startup (Ldap contacts cache) // ============================================================================== bool SettingsModel::clearLocalLdapFriendsUponStartup(const shared_ptr &config) { mustBeInLinphoneThread(sLog().arg(Q_FUNC_INFO)); return config ? config->getBool(UiSection, "clear_local_ldap_friends_upon_startup", false) : false; } // ============================================================================= // Ui. // ============================================================================= /* bool SettingsModel::getShowChats() const { return mConfig->getBool(UiSection, "disable_chat_feature", false); }*/ QVariantList SettingsModel::getShortcuts() const { mustBeInLinphoneThread(log().arg(Q_FUNC_INFO)); QVariantList shortcuts; auto sections = mConfig->getSectionsNamesList(); for (auto section : sections) { auto sectionTokens = Utils::coreStringToAppString(section).split('_'); if (sectionTokens.size() > 1 && sectionTokens[0].compare("shortcut", Qt::CaseInsensitive) == 0) { QVariantMap shortcut; shortcut["id"] = sectionTokens[1].toInt(); shortcut["name"] = Utils::coreStringToAppString(mConfig->getString(section, "name", "")); shortcut["link"] = Utils::coreStringToAppString(mConfig->getString(section, "link", "")); shortcut["icon"] = Utils::coreStringToAppString(mConfig->getString(section, "icon", "")); shortcuts << shortcut; } } return shortcuts; } void SettingsModel::setShortcuts(QVariantList data) { if (getShortcuts() != data) { // clean auto sections = mConfig->getSectionsNamesList(); for (auto section : sections) { auto sectionTokens = Utils::coreStringToAppString(section).split('_'); if (sectionTokens.size() > 1 && sectionTokens[0].compare("shortcut", Qt::CaseInsensitive) == 0) { mConfig->cleanSection(section); } } int count = 0; for (auto shortcut : data) { auto mShortcut = shortcut.toMap(); auto key = Utils::appStringToCoreString("shortcut_" + QString::number(count++)); mConfig->setString(key, "name", Utils::appStringToCoreString(mShortcut["name"].toString())); mConfig->setString(key, "link", Utils::appStringToCoreString(mShortcut["link"].toString())); mConfig->setString(key, "icon", Utils::appStringToCoreString(mShortcut["icon"].toString())); } emit shortcutsChanged(data); } } // clang-format off void SettingsModel::notifyConfigReady(){ DEFINE_NOTIFY_CONFIG_READY(disableChatFeature, DisableChatFeature) DEFINE_NOTIFY_CONFIG_READY(disableMeetingsFeature, DisableMeetingsFeature) DEFINE_NOTIFY_CONFIG_READY(hideSettings,HideSettings) DEFINE_NOTIFY_CONFIG_READY(hideAccountSettings, HideAccountSettings) DEFINE_NOTIFY_CONFIG_READY(hideFps, HideFps) DEFINE_NOTIFY_CONFIG_READY(disableCallRecordings, DisableCallRecordings) DEFINE_NOTIFY_CONFIG_READY(assistantHideCreateAccount, AssistantHideCreateAccount) DEFINE_NOTIFY_CONFIG_READY(assistantDisableQrCode, AssistantDisableQrCode) DEFINE_NOTIFY_CONFIG_READY(assistantHideThirdPartyAccount, AssistantHideThirdPartyAccount) DEFINE_NOTIFY_CONFIG_READY(onlyDisplaySipUriUsername, OnlyDisplaySipUriUsername) DEFINE_NOTIFY_CONFIG_READY(darkModeAllowed, DarkModeAllowed) DEFINE_NOTIFY_CONFIG_READY(assistantGoDirectlyToThirdPartySipAccountLogin, AssistantGoDirectlyToThirdPartySipAccountLogin) DEFINE_NOTIFY_CONFIG_READY(assistantThirdPartySipAccountDomain, AssistantThirdPartySipAccountDomain) DEFINE_NOTIFY_CONFIG_READY(assistantThirdPartySipAccountTransport, AssistantThirdPartySipAccountTransport) DEFINE_NOTIFY_CONFIG_READY(autoStart, AutoStart) DEFINE_NOTIFY_CONFIG_READY(exitOnClose, ExitOnClose) DEFINE_NOTIFY_CONFIG_READY(syncLdapContacts, SyncLdapContacts) DEFINE_NOTIFY_CONFIG_READY(configLocale, ConfigLocale) DEFINE_NOTIFY_CONFIG_READY(downloadFolder, DownloadFolder) DEFINE_NOTIFY_CONFIG_READY(shortcutCount, ShortcutCount) DEFINE_NOTIFY_CONFIG_READY(shortcuts, Shortcuts) DEFINE_NOTIFY_CONFIG_READY(usernameOnlyForLdapLookupsInCalls, UsernameOnlyForLdapLookupsInCalls) } DEFINE_GETSET_CONFIG(SettingsModel, bool, Bool, disableChatFeature, DisableChatFeature, "disable_chat_feature", true) DEFINE_GETSET_CONFIG( SettingsModel, bool, Bool, disableMeetingsFeature, DisableMeetingsFeature, "disable_meetings_feature", false) DEFINE_GETSET_CONFIG(SettingsModel, bool, Bool, disableBroadcastFeature, DisableBroadcastFeature, "disable_broadcast_feature", true) DEFINE_GETSET_CONFIG(SettingsModel, bool, Bool, hideSettings, HideSettings, "hide_settings", false) DEFINE_GETSET_CONFIG( SettingsModel, bool, Bool, hideAccountSettings, HideAccountSettings, "hide_account_settings", false) DEFINE_GETSET_CONFIG(SettingsModel, bool, Bool, hideFps, HideFps, "hide_fps", true ) DEFINE_GETSET_CONFIG(SettingsModel, bool, Bool, disableCallRecordings, DisableCallRecordings, "disable_call_recordings_feature", false) DEFINE_GETSET_CONFIG(SettingsModel, bool, Bool, assistantHideCreateAccount, AssistantHideCreateAccount, "assistant_hide_create_account", false) DEFINE_GETSET_CONFIG(SettingsModel, bool, Bool, assistantDisableQrCode, AssistantDisableQrCode, "assistant_disable_qr_code", true) DEFINE_GETSET_CONFIG(SettingsModel, bool, Bool, assistantHideThirdPartyAccount, AssistantHideThirdPartyAccount, "assistant_hide_third_party_account", false) DEFINE_GETSET_CONFIG(SettingsModel, bool, Bool, onlyDisplaySipUriUsername, OnlyDisplaySipUriUsername, "only_display_sip_uri_username", false) DEFINE_GETSET_CONFIG(SettingsModel, bool, Bool, darkModeAllowed, DarkModeAllowed, "dark_mode_allowed", false) DEFINE_GETSET_CONFIG(SettingsModel, int, Int, maxAccount, MaxAccount, "max_account", 0) DEFINE_GETSET_CONFIG(SettingsModel, bool, Bool, assistantGoDirectlyToThirdPartySipAccountLogin, AssistantGoDirectlyToThirdPartySipAccountLogin, "assistant_go_directly_to_third_party_sip_account_login", false) DEFINE_GETSET_CONFIG_STRING(SettingsModel, assistantThirdPartySipAccountDomain, AssistantThirdPartySipAccountDomain, "assistant_third_party_sip_account_domain", "") DEFINE_GETSET_CONFIG_STRING(SettingsModel, assistantThirdPartySipAccountTransport, AssistantThirdPartySipAccountTransport, "assistant_third_party_sip_account_transport", "TLS") DEFINE_GETSET_CONFIG(SettingsModel, bool, Bool, autoStart, AutoStart, "auto_start", false) DEFINE_GETSET_CONFIG(SettingsModel, bool, Bool, exitOnClose, ExitOnClose, "exit_on_close", false) DEFINE_GETSET_CONFIG(SettingsModel, bool, Bool, syncLdapContacts, SyncLdapContacts, "sync_ldap_contacts", false) DEFINE_GETSET_CONFIG_STRING(SettingsModel, configLocale, ConfigLocale, "locale", "") DEFINE_GETSET_CONFIG_STRING(SettingsModel, downloadFolder, DownloadFolder, "download_folder", "") DEFINE_GETSET_CONFIG(SettingsModel, int, Int, shortcutCount, ShortcutCount, "shortcut_count", 0) DEFINE_GETSET_CONFIG(SettingsModel, bool, Bool, usernameOnlyForLdapLookupsInCalls, UsernameOnlyForLdapLookupsInCalls, "username_only_for_ldap_lookups_in_calls", false) // clang-format on