- change user agent for device name.

- add a settings to change device name (default is machine hostname)
- fix table layout : no more empty line at top (eg. in network protocol and ports settings)
This commit is contained in:
Julien Wadel 2022-01-21 11:47:48 +01:00
parent 0863bd2321
commit b709a6af69
25 changed files with 357 additions and 227 deletions

View file

@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Option to enable message notifications.
- CPIM on basic chat rooms.
- New event on new messages in chat and a shortcut to go to the end of chat if last message is not shown.
- Device name can be changed from settings.
- Based on Linphone SDK 5.1
### Fixed
@ -23,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Enable G729 on public builds.
- Take account of return key on Numpad
- Huge messages are better shown and with less flickering.
- Adapt UserAgent with device name.
## 4.3.2

View file

@ -2288,6 +2288,11 @@ Klik her: <a href="%1">%1</a>
<source>assistantSupportsPhoneNumbersLabel</source>
<translation>Understøtter telefonnumre</translation>
</message>
<message>
<source>defaultDeviceNameLabel</source>
<extracomment>&apos;Device Name&apos; : Label for setting the device name.</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsSipAccountsEdit</name>

View file

@ -2288,6 +2288,11 @@ Klicken Sie hier: &lt;a href=&quot;%1&quot;&gt;%1&lt;/a&gt;
<source>assistantSupportsPhoneNumbersLabel</source>
<translation>Telefonnummern werden unterstützt</translation>
</message>
<message>
<source>defaultDeviceNameLabel</source>
<extracomment>&apos;Device Name&apos; : Label for setting the device name.</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsSipAccountsEdit</name>

View file

@ -2311,6 +2311,11 @@ Click here: &lt;a href=&quot;%1&quot;&gt;%1&lt;/a&gt;
<source>assistantSupportsPhoneNumbersLabel</source>
<translation>Supports phone numbers</translation>
</message>
<message>
<source>defaultDeviceNameLabel</source>
<extracomment>&apos;Device Name&apos; : Label for setting the device name.</extracomment>
<translation>Device name</translation>
</message>
</context>
<context>
<name>SettingsSipAccountsEdit</name>

View file

@ -2288,6 +2288,11 @@ Haga clic aquí: &lt;a href=&quot;%1&quot;&gt;%1 &lt;/a&gt;
<source>assistantSupportsPhoneNumbersLabel</source>
<translation>Soportar números de teléfono</translation>
</message>
<message>
<source>defaultDeviceNameLabel</source>
<extracomment>&apos;Device Name&apos; : Label for setting the device name.</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsSipAccountsEdit</name>

View file

@ -2288,6 +2288,11 @@ Cliquez ici : &lt;a href=&quot;%1&quot;&gt;%1&lt;/a&gt;
<source>assistantSupportsPhoneNumbersLabel</source>
<translation>Supporter les numéros de tél.</translation>
</message>
<message>
<source>defaultDeviceNameLabel</source>
<extracomment>&apos;Device Name&apos; : Label for setting the device name.</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsSipAccountsEdit</name>

View file

@ -2277,6 +2277,11 @@ Kattintson ide: &lt;a href=&quot;%1&quot;&gt;%1&lt;/a&gt;
<source>assistantSupportsPhoneNumbersLabel</source>
<translation>Támogatja a telefonszámokat</translation>
</message>
<message>
<source>defaultDeviceNameLabel</source>
<extracomment>&apos;Device Name&apos; : Label for setting the device name.</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsSipAccountsEdit</name>

View file

@ -2288,6 +2288,11 @@ Clicca: &lt;a href=&quot;%1&quot;&gt;%1&lt;/a&gt;
<source>assistantSupportsPhoneNumbersLabel</source>
<translation>Supporta i numeri di telefono</translation>
</message>
<message>
<source>defaultDeviceNameLabel</source>
<extracomment>&apos;Device Name&apos; : Label for setting the device name.</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsSipAccountsEdit</name>

View file

@ -2277,6 +2277,11 @@
<source>assistantSupportsPhoneNumbersLabel</source>
<translation></translation>
</message>
<message>
<source>defaultDeviceNameLabel</source>
<extracomment>&apos;Device Name&apos; : Label for setting the device name.</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsSipAccountsEdit</name>

View file

@ -2299,6 +2299,11 @@ Spustelėkite čia: &lt;a href=&quot;%1&quot;&gt;%1&lt;/a&gt;
<source>assistantSupportsPhoneNumbersLabel</source>
<translation>Palaiko telefonų numerius</translation>
</message>
<message>
<source>defaultDeviceNameLabel</source>
<extracomment>&apos;Device Name&apos; : Label for setting the device name.</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsSipAccountsEdit</name>

View file

@ -2288,6 +2288,11 @@ Clique aqui: &lt;a href=&quot;%1&quot;&gt;%1 &lt;/a&gt;
<source>assistantSupportsPhoneNumbersLabel</source>
<translation>Suporta números de telefone</translation>
</message>
<message>
<source>defaultDeviceNameLabel</source>
<extracomment>&apos;Device Name&apos; : Label for setting the device name.</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsSipAccountsEdit</name>

View file

@ -2299,6 +2299,11 @@
<source>assistantSupportsPhoneNumbersLabel</source>
<translation>Поддерживает номера телефонов</translation>
</message>
<message>
<source>defaultDeviceNameLabel</source>
<extracomment>&apos;Device Name&apos; : Label for setting the device name.</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsSipAccountsEdit</name>

View file

@ -2288,6 +2288,11 @@ Klicka här: &lt;a href=&quot;%1&quot;&gt;%1&lt;/a&gt;
<source>assistantSupportsPhoneNumbersLabel</source>
<translation>Stöder telefonnummer</translation>
</message>
<message>
<source>defaultDeviceNameLabel</source>
<extracomment>&apos;Device Name&apos; : Label for setting the device name.</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsSipAccountsEdit</name>

View file

@ -2277,6 +2277,11 @@ Buraya tıklayın: &lt;a href=&quot;%1&quot;&gt;%1&lt;/a&gt;
<source>assistantSupportsPhoneNumbersLabel</source>
<translation>Telefon numaralarını destekler</translation>
</message>
<message>
<source>defaultDeviceNameLabel</source>
<extracomment>&apos;Device Name&apos; : Label for setting the device name.</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsSipAccountsEdit</name>

View file

@ -2299,6 +2299,11 @@
<source>assistantSupportsPhoneNumbersLabel</source>
<translation>Підтримує номери телефонів</translation>
</message>
<message>
<source>defaultDeviceNameLabel</source>
<extracomment>&apos;Device Name&apos; : Label for setting the device name.</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsSipAccountsEdit</name>

View file

@ -2277,6 +2277,11 @@
<source>assistantSupportsPhoneNumbersLabel</source>
<translation></translation>
</message>
<message>
<source>defaultDeviceNameLabel</source>
<extracomment>&apos;Device Name&apos; : Label for setting the device name.</extracomment>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsSipAccountsEdit</name>

View file

@ -261,15 +261,6 @@ void CoreManager::createLinphoneCore (const QString &configPath) {
mCore->setVideoDisplayFilter("MSQOGL");
mCore->usePreviewWindow(true);
mCore->enableVideoPreview(false);
mCore->setUserAgent(
Utils::appStringToCoreString(
QStringLiteral(APPLICATION_NAME" Desktop/%1 (%2, Qt %3) LinphoneCore")
.arg(QCoreApplication::applicationVersion())
.arg(QSysInfo::prettyProductName())
.arg(qVersion())
),
mCore->getVersion()
);
// Force capture/display.
// Useful if the app was built without video support.
// (The capture/display attributes are reset by the core in this case.)
@ -278,12 +269,19 @@ void CoreManager::createLinphoneCore (const QString &configPath) {
config->setInt("video", "capture", 1);
config->setInt("video", "display", 1);
}
QString userAgent = Utils::computeUserAgent(config);
mCore->setUserAgent(Utils::appStringToCoreString(userAgent), mCore->getVersion());
mCore->start();
setDatabasesPaths();
setOtherPaths();
mCore->enableFriendListSubscription(true);
}
void CoreManager::updateUserAgent(){
mCore->setUserAgent(Utils::appStringToCoreString(Utils::computeUserAgent(mCore->getConfig())), mCore->getVersion());
forceRefreshRegisters(); // After setting a new device name, REGISTER need to take account it.
}
void CoreManager::handleChatRoomCreated(const std::shared_ptr<ChatRoomModel> &chatRoomModel){
emit chatRoomModelCreated(chatRoomModel);
}

View file

@ -168,6 +168,7 @@ public:
Q_INVOKABLE bool isLastRemoteProvisioningGood();
Q_INVOKABLE QString getUserAgent()const;
void updateUserAgent();
public slots:
void initCoreManager();

View file

@ -31,22 +31,22 @@
// =============================================================================
class AccountSettingsModel : public QObject {
Q_OBJECT;
Q_OBJECT
// Selected proxy config.
Q_PROPERTY(QString username READ getUsername WRITE setUsername NOTIFY accountSettingsUpdated);
Q_PROPERTY(QString sipAddress READ getUsedSipAddressAsStringUriOnly NOTIFY accountSettingsUpdated);
Q_PROPERTY(QString fullSipAddress READ getUsedSipAddressAsString);
Q_PROPERTY(RegistrationState registrationState READ getRegistrationState NOTIFY accountSettingsUpdated);
Q_PROPERTY(QString username READ getUsername WRITE setUsername NOTIFY accountSettingsUpdated)
Q_PROPERTY(QString sipAddress READ getUsedSipAddressAsStringUriOnly NOTIFY accountSettingsUpdated)
Q_PROPERTY(QString fullSipAddress READ getUsedSipAddressAsString)
Q_PROPERTY(RegistrationState registrationState READ getRegistrationState NOTIFY accountSettingsUpdated)
Q_PROPERTY(QString conferenceURI READ getConferenceURI NOTIFY accountSettingsUpdated)
// Default info.
Q_PROPERTY(QString primaryDisplayName READ getPrimaryDisplayName WRITE setPrimaryDisplayName NOTIFY accountSettingsUpdated);
Q_PROPERTY(QString primaryUsername READ getPrimaryUsername WRITE setPrimaryUsername NOTIFY accountSettingsUpdated);
Q_PROPERTY(QString primarySipAddress READ getPrimarySipAddress NOTIFY accountSettingsUpdated);
Q_PROPERTY(QString primaryDisplayName READ getPrimaryDisplayName WRITE setPrimaryDisplayName NOTIFY accountSettingsUpdated)
Q_PROPERTY(QString primaryUsername READ getPrimaryUsername WRITE setPrimaryUsername NOTIFY accountSettingsUpdated)
Q_PROPERTY(QString primarySipAddress READ getPrimarySipAddress NOTIFY accountSettingsUpdated)
Q_PROPERTY(QVariantList accounts READ getAccounts NOTIFY accountSettingsUpdated);
Q_PROPERTY(QVariantList accounts READ getAccounts NOTIFY accountSettingsUpdated)
public:
enum RegistrationState {

View file

@ -190,6 +190,24 @@ void SettingsModel::setAssistantLogoutUrl (QString url) {
emit assistantLogoutUrlChanged(url);
}
// =============================================================================
// SIP Accounts.
// =============================================================================
QString SettingsModel::getDeviceName(const std::shared_ptr<linphone::Config>& config){
return Utils::coreStringToAppString(config->getString(UiSection, "device_name", Utils::appStringToCoreString(QSysInfo::machineHostName())));
}
QString SettingsModel::getDeviceName() const{
return getDeviceName(mConfig);
}
void SettingsModel::setDeviceName(const QString& deviceName){
mConfig->setString(UiSection, "device_name", Utils::appStringToCoreString(deviceName));
emit deviceNameChanged();
CoreManager::getInstance()->updateUserAgent();
}
// =============================================================================
// Audio.
// =============================================================================

View file

@ -51,6 +51,10 @@ class SettingsModel : public QObject {
Q_PROPERTY(QString assistantRegistrationUrl READ getAssistantRegistrationUrl WRITE setAssistantRegistrationUrl NOTIFY assistantRegistrationUrlChanged)
Q_PROPERTY(QString assistantLoginUrl READ getAssistantLoginUrl WRITE setAssistantLoginUrl NOTIFY assistantLoginUrlChanged)
Q_PROPERTY(QString assistantLogoutUrl READ getAssistantLogoutUrl WRITE setAssistantLogoutUrl NOTIFY assistantLogoutUrlChanged)
// SIP Accounts. -------------------------------------------------------------
Q_PROPERTY(QString deviceName READ getDeviceName WRITE setDeviceName NOTIFY deviceNameChanged)
// Audio. --------------------------------------------------------------------
@ -248,6 +252,12 @@ public:
QString getAssistantLogoutUrl () const;
void setAssistantLogoutUrl (QString url);
// SIP Accounts. -------------------------------------------------------------
static QString getDeviceName(const std::shared_ptr<linphone::Config>& config);
QString getDeviceName() const;
void setDeviceName(const QString& deviceName);
// Audio. --------------------------------------------------------------------
@ -550,6 +560,10 @@ signals:
void assistantRegistrationUrlChanged (QString url);
void assistantLoginUrlChanged (QString url);
void assistantLogoutUrlChanged (QString url);
// SIP Accounts. -------------------------------------------------------------
void deviceNameChanged();
// Audio. --------------------------------------------------------------------

View file

@ -25,11 +25,13 @@
#include <QImageReader>
#include <QDebug>
#include "config.h"
#include "Utils.hpp"
#include "components/core/CoreManager.hpp"
#include "components/contacts/ContactsListModel.hpp"
#include "components/contact/ContactModel.hpp"
#include "components/contact/VcardModel.hpp"
#include "components/settings/SettingsModel.hpp"
#include "app/paths/Paths.hpp"
// =============================================================================
@ -514,4 +516,12 @@ std::shared_ptr<linphone::Config> Utils::getConfigIfExists (const QString &confi
factoryPath.clear();
return linphone::Config::newWithFactory(configPath.toStdString(), factoryPath);
}
QString Utils::computeUserAgent(const std::shared_ptr<linphone::Config>& config){
return QStringLiteral(APPLICATION_NAME" Desktop/%1 (%2) %3, Qt %4 LinphoneCore")
.arg(QCoreApplication::applicationVersion())
.arg(SettingsModel::getDeviceName(config))
.arg(QSysInfo::prettyProductName())
.arg(qVersion());
}

View file

@ -127,6 +127,7 @@ public:
static void copyDir(QString from, QString to);// Copy a folder recursively without erasing old file
static QString getDisplayName(const std::shared_ptr<const linphone::Address>& address); // Get the displayname from addres in this order : Friends, Contact, Display address, Username address
static std::shared_ptr<linphone::Config> getConfigIfExists (const QString& configPath);
static QString computeUserAgent(const std::shared_ptr<linphone::Config>& config);
};
#endif // UTILS_H_

View file

@ -43,10 +43,10 @@ Column {
Row {
spacing: FormTableLineStyle.spacing
width: parent.width
// No title for the titles column.
Item {
height: FormTableStyle.entry.height
height: header.model.count > 0 ? FormTableStyle.entry.height : 0
width: formTable.legendLineWidth
visible: !formTable.disableLineTitle

View file

@ -11,211 +11,222 @@ import 'SettingsSipAccounts.js' as Logic
// =============================================================================
TabContainer {
Column {
spacing: SettingsWindowStyle.forms.spacing
width: parent.width
// -------------------------------------------------------------------------
// Default identity.
// -------------------------------------------------------------------------
Form {
title: qsTr('defaultIdentityTitle')
width: parent.width
FormLine {
FormGroup {
label: qsTr('defaultDisplayNameLabel')
TextField {
text: AccountSettingsModel.primaryDisplayName
onEditingFinished: AccountSettingsModel.primaryDisplayName = text
}
}
}
FormLine {
FormGroup {
label: qsTr('defaultUsernameLabel')
TextField {
text: AccountSettingsModel.primaryUsername
onEditingFinished: AccountSettingsModel.primaryUsername = text
}
}
}
FormLine {
FormGroup {
label: qsTr('defaultSipAddressLabel')
TextField {
readOnly: true
text: AccountSettingsModel.primarySipAddress
}
}
}
}
// -------------------------------------------------------------------------
// Proxy accounts.
// -------------------------------------------------------------------------
Form {
title: qsTr('proxyAccountsTitle')
width: parent.width
FormTable {
legendLineWidth: SettingsWindowStyle.sipAccounts.legendLineWidth
titles: [
qsTr('editHeader'),
qsTr('deleteHeader')
]
Repeater {
model: SettingsModel.showLocalSipAccount ? AccountSettingsModel.accounts.slice(1) : AccountSettingsModel.accounts
delegate: FormTableLine {
title: modelData.sipAddress
FormTableEntry {
ActionButton {
isCustom: true
backgroundRadius: 4
colorSet: SettingsWindowStyle.buttons.editProxy
onClicked: Logic.editAccount(modelData)
}
}
FormTableEntry {
ActionButton {
isCustom: true
backgroundRadius: 4
colorSet: SettingsWindowStyle.buttons.deleteProxy
onClicked: Logic.deleteAccount(modelData)
}
}
}
}
}
FormEmptyLine {}
}
Row {
anchors.right: parent.right
spacing: SettingsWindowStyle.sipAccounts.buttonsSpacing
TextButtonB {
text: qsTr('eraseAllPasswords')
onClicked: Logic.eraseAllPasswords()
}
TextButtonB {
text: qsTr('addAccount')
onClicked: Logic.editAccount()
}
}
// -------------------------------------------------------------------------
// Assistant.
// -------------------------------------------------------------------------
Form {
title: qsTr('assistantTitle')
width: parent.width
FormLine {
FormGroup {
label: 'Registration URL'
TextField {
text: SettingsModel.assistantRegistrationUrl
onEditingFinished: SettingsModel.assistantRegistrationUrl = text
}
}
}
FormLine {
FormGroup {
label: 'Login URL'
TextField {
text: SettingsModel.assistantLoginUrl
onEditingFinished: SettingsModel.assistantLoginUrl = text
}
}
}
FormLine {
visible: SettingsModel.developerSettingsEnabled
FormGroup {
label: qsTr('createAppSipAccountEnabledLabel')
Switch {
checked: SettingsModel.createAppSipAccountEnabled
onClicked: SettingsModel.createAppSipAccountEnabled = !checked
}
}
FormGroup {
label: qsTr('useAppSipAccountEnabledLabel')
Switch {
checked: SettingsModel.useAppSipAccountEnabled
onClicked: SettingsModel.useAppSipAccountEnabled = !checked
}
}
}
FormLine {
visible: SettingsModel.developerSettingsEnabled
FormGroup {
label: qsTr('useOtherSipAccountEnabledLabel')
Switch {
checked: SettingsModel.useOtherSipAccountEnabled
onClicked: SettingsModel.useOtherSipAccountEnabled = !checked
}
}
FormGroup {
label: qsTr('fetchRemoteConfigurationEnabledLabel')
Switch {
checked: SettingsModel.fetchRemoteConfigurationEnabled
onClicked: SettingsModel.fetchRemoteConfigurationEnabled = !checked
}
}
}
FormLine {
visible: SettingsModel.developerSettingsEnabled
FormGroup {
label: qsTr('assistantSupportsPhoneNumbersLabel')
Switch {
checked: SettingsModel.assistantSupportsPhoneNumbers
onClicked: SettingsModel.assistantSupportsPhoneNumbers = !checked
}
}
}
}
}
Column {
spacing: SettingsWindowStyle.forms.spacing
width: parent.width
// -------------------------------------------------------------------------
// Default identity.
// -------------------------------------------------------------------------
Form {
title: qsTr('defaultIdentityTitle')
width: parent.width
FormLine {
FormGroup {
label: qsTr('defaultDisplayNameLabel')
TextField {
text: AccountSettingsModel.primaryDisplayName
onEditingFinished: AccountSettingsModel.primaryDisplayName = text
}
}
}
FormLine {
FormGroup {
label: qsTr('defaultUsernameLabel')
TextField {
text: AccountSettingsModel.primaryUsername
onEditingFinished: AccountSettingsModel.primaryUsername = text
}
}
}
FormLine {
FormGroup {
label: qsTr('defaultSipAddressLabel')
TextField {
readOnly: true
text: AccountSettingsModel.primarySipAddress
}
}
}
FormLine {
FormGroup {
//: 'Device Name' : Label for setting the device name.
label: qsTr('defaultDeviceNameLabel')
TextField {
text: SettingsModel.deviceName
onEditingFinished: SettingsModel.deviceName = text
}
}
}
}
// -------------------------------------------------------------------------
// Proxy accounts.
// -------------------------------------------------------------------------
Form {
title: qsTr('proxyAccountsTitle')
width: parent.width
FormTable {
legendLineWidth: SettingsWindowStyle.sipAccounts.legendLineWidth
titles: [
qsTr('editHeader'),
qsTr('deleteHeader')
]
Repeater {
model: SettingsModel.showLocalSipAccount ? AccountSettingsModel.accounts.slice(1) : AccountSettingsModel.accounts
delegate: FormTableLine {
title: modelData.sipAddress
FormTableEntry {
ActionButton {
isCustom: true
backgroundRadius: 4
colorSet: SettingsWindowStyle.buttons.editProxy
onClicked: Logic.editAccount(modelData)
}
}
FormTableEntry {
ActionButton {
isCustom: true
backgroundRadius: 4
colorSet: SettingsWindowStyle.buttons.deleteProxy
onClicked: Logic.deleteAccount(modelData)
}
}
}
}
}
FormEmptyLine {}
}
Row {
anchors.right: parent.right
spacing: SettingsWindowStyle.sipAccounts.buttonsSpacing
TextButtonB {
text: qsTr('eraseAllPasswords')
onClicked: Logic.eraseAllPasswords()
}
TextButtonB {
text: qsTr('addAccount')
onClicked: Logic.editAccount()
}
}
// -------------------------------------------------------------------------
// Assistant.
// -------------------------------------------------------------------------
Form {
title: qsTr('assistantTitle')
width: parent.width
FormLine {
FormGroup {
label: 'Registration URL'
TextField {
text: SettingsModel.assistantRegistrationUrl
onEditingFinished: SettingsModel.assistantRegistrationUrl = text
}
}
}
FormLine {
FormGroup {
label: 'Login URL'
TextField {
text: SettingsModel.assistantLoginUrl
onEditingFinished: SettingsModel.assistantLoginUrl = text
}
}
}
FormLine {
visible: SettingsModel.developerSettingsEnabled
FormGroup {
label: qsTr('createAppSipAccountEnabledLabel')
Switch {
checked: SettingsModel.createAppSipAccountEnabled
onClicked: SettingsModel.createAppSipAccountEnabled = !checked
}
}
FormGroup {
label: qsTr('useAppSipAccountEnabledLabel')
Switch {
checked: SettingsModel.useAppSipAccountEnabled
onClicked: SettingsModel.useAppSipAccountEnabled = !checked
}
}
}
FormLine {
visible: SettingsModel.developerSettingsEnabled
FormGroup {
label: qsTr('useOtherSipAccountEnabledLabel')
Switch {
checked: SettingsModel.useOtherSipAccountEnabled
onClicked: SettingsModel.useOtherSipAccountEnabled = !checked
}
}
FormGroup {
label: qsTr('fetchRemoteConfigurationEnabledLabel')
Switch {
checked: SettingsModel.fetchRemoteConfigurationEnabled
onClicked: SettingsModel.fetchRemoteConfigurationEnabled = !checked
}
}
}
FormLine {
visible: SettingsModel.developerSettingsEnabled
FormGroup {
label: qsTr('assistantSupportsPhoneNumbersLabel')
Switch {
checked: SettingsModel.assistantSupportsPhoneNumbers
onClicked: SettingsModel.assistantSupportsPhoneNumbers = !checked
}
}
}
}
}
}