Документация
ОС Аврора 5.1.5

Пользовательский интерфейс VPN-подключений

Данная статья описывает процесс реализации расширения для приложения «Настройки», которое позволяет управлять параметрами VPN-профилей подключений для собственных VPN-плагинов ConnMan. Руководство описывает только часть действий, которые необходимо выполнить для реализации полноценного VPN-расширения в ОС Аврора.

Подсистема управления VPN-соединениями в приложении «Настройки»

Приложение «Настройки» реализовано по модульному принципу, что позволяет реализовывать расширения для поддержки новых типов VPN-подключений. Задачей каждого такого расширения является создание профиля VPN-подключения, включающего поля для соответствующего VPN-плагина ConnMan. В профиле VPN-подключения содержатся параметры для установления VPN-соединения: адрес сервера, имя пользователя и т. д.

Расширения для VPN-подключения представляют собой набор QML-документов, каждый из которых используется приложением «Настройки» на различных этапах работы пользователя по созданию и редактированию VPN-профилей. Все документы должны находиться в одном каталоге с названием, совпадающим с названием VPN-плагина для ConnMan.

Для реализации данных файлов расширения можно использовать все доступные QML-библиотеки, создавать собственные QML-документы для решения специфических задач. Основной библиотекой для создания данных файлов выступает Sailfish.Settings.Networking.Vpn, типы которой позволяют формировать VPN-профили.

Для решения задачи локализации пользовательского интерфейса применяется подход с созданием собственного глобального QML-плагина. В рамках данного плагина можно также разместить более сложную логику с использованием языка C++.

Схемы расширения приложения «Настройки»

Существуют две схемы реализации расширения: реализация всей логики по указанию параметров VPN-подключения внутри расширения и реализация отдельного приложения, менеджера конфигураций, для формирования параметров подключения.

В рамках первого подхода пользователь управляет всеми параметрами подключения внутри приложений «Настройки». Плюсы такого подхода:

  • Пользователь использует одно приложение для настройки VPN-подключений.
  • Количество компонентов для разработки меньше по сравнению с альтернативной схемой.
  • Сложную логику, включая предварительное сетевое взаимодействие, можно реализовать в рамках QML-плагина.
  • Пользователь взаимодействует исключительно с приложением, которое ему знакомо.

Основной сложностью при реализации данного подхода является необходимость в обработке всех параметров подключения в рамках расширения приложения «Настройки» и в рамках VPN-плагина ConnMan.

В рамках второго подхода пользователь формирует параметры соединения в отдельном приложении с графическим интерфейсом, менеджере конфигураций. Обычно эти настройки записываются в собственный формат подключения, который может быть использован VPN-клиентом напрямую. В рамках же VPN-расширений платформы передаётся лишь путь к данному конфигурационному файлу. Плюсы такого подхода:

  • При реализации менеджера конфигураций можно повторно использовать бизнес-логику по работе с конфигурациями подключения из-под других платформ.
  • В рамках расширений для реализации VPN-компонентов требуется передавать минимальный набор дополнительных данных: путь к конфигурационному файлу.

Основными трудностями при реализации данной схемы становятся:

  • Необходимость в реализации ещё одного дополнительного компонента для поставки конечному пользователю, то есть менеджера конфигураций.
  • При реализации менеджера конфигураций все компоненты пользовательского интерфейса будет необходимо реализовывать самостоятельно.
  • Пользователю необходимо взаимодействовать как с приложением «Настройки», так и с менеджером конфигураций для настройки VPN-подключения.
  • Пользователь может удалить конфигурацию VPN-подключения из менеджера конфигураций, не изменив профиль подключения в «Настройках».

При выборе схемы реализации оцените все плюсы и минусы каждого из подходов.

Реализация расширения приложения «Настройки»

Рассмотрим детали реализации подхода расширения приложения «Настройки», при котором вся логика по формированию профилей VPN-подключения выполняется исключительно силами расширения.

Структура проекта

Расширение для приложения «Настройки» состоит следующих компонент:

  • QML-документы, образующие само расширение;
  • QML-плагин, который обеспечивает локализацию для строк пользовательского интерфейса;
  • набор файлов для локализации пользовательского интерфейса.

Для доставки каждого из них необходимо создать отдельный проект.

Таким образом при использовании системы сборки qmake структура проекта выглядит следующим образом:

vpn-provider
├── connman-plugin
├── settings-controls
│   └── settings-controls.pro
├── settings-translations
│   └── settings-translations.pro
├── qml-plugin
│   └── qml-plugin.pro
├── rpm
│   └── vpn-plugin-project.spec
├── vpn-provider
│   └── vpn-provider.pro
└── vpn-provider.pro

Корнем проекта является каталог vpn-provider, в котором располагается одноимённый .pro-файл. Данный файл должен описывать проект согласно шаблону поддиректорий (subdirs) и включать в себя другие каталоги. Название проекта и следовательно каталога должно быть уникальным, то есть вместо vpn-provider следует использовать название VPN-провайдера.

В подкаталогах располагаются соответствующие компоненты расширения. В подкаталоге rpm описывается процесс сборки RPM-архива для установки на целевые устройства.

В каталоге connman-plugin находится VPN-плагин для ConnMan. Детали его разработки приведены в соответствующем руководстве.

В подкаталоге vpn-provider должно находиться обычное приложение для ОС Аврора. Данное приложение не должно выполнять никаких действий, оно необходимо исключительно для успешного прохождения валидации. В рамках второго подхода данное приложение будет выполнять задачи менеджера конфигураций.

QML-плагин

В подкаталоге проекта qml-plugin должен располагаться QML-плагин. В его задачи входит:

  • предоставление локализованных строк для пользовательского интерфейса;
  • предоставление собственных QML-типов, реализованных на языке C++.

Подробное описание по созданию QML-плагина находится в официальной документации библиотеки Qt. Остановимся на важных аспектах, на которые следует обратить внимание при его реализации.

Установка данного плагина будет производится в глобальный набор QML-плагинов для платформы. Это означает, что все ресурсы данного плагина будут доступны в рамках любого приложения, которое устанавливается на мобильное устройство.

Из этого следует, что необходимо тщательно подойти к выбору наименования плагина, чтобы оно было уникальным в рамках мобильного устройства. Хорошим вариантом для этого является использование доменного имени компании. В рамках примера будем использовать имя ru.omprussia.vpnprovider.

В рамках .pro-файла указывается системный путь к установке данного плагина:

TEMPLATE = lib
TARGET = vpnprovider
CONFIG += plugin

OTHER_FILES += qmldir

MODULENAME = ru/omprussia/vpnprovider
TARGETPATH = $$[QT_INSTALL_QML]/$$MODULENAME

import.files = qmldir
import.path = $$TARGETPATH
target.path = $$TARGETPATH

INSTALLS += target import

Следует обратить внимание на формирование переменной MODULENAME. Она должна состоять из частей названия QML-плагина, где каждой части названия соответствует отдельный каталог.

Название QML-плагина также должно быть указано в файле qmldir:

module ru.omprussia.vpnprovider
plugin vpnprovider

В .spec-файл также необходимо добавить указание, что файлы QML-плагина необходимо включить в RPM-пакет:

%files
%{_libdir}/qt5/qml/ru/omprussia/vpnprovider/*

В рамках реализации QML-плагина необходимо добавить свой класс-наследник QTranslator, чтобы обеспечить использование файлов локализации пользовательского интерфейса. Пример реализации данного переводчика можно посмотреть в репозитории TrifleVpn.

Также следует отметить, что в рамках QML-плагина должен поставляться хотя бы один QML-тип. Если этого не сделать, то плагин будет считаться недействительным и будет выгружен, что повлечёт за собой также отключение транслятора.

Локализация строк пользовательского интерфейса

Процесс локализации расширения приложения «Настройки» схож с локализацией обычного приложения под ОС Аврора: в исходных кодах приложения содержатся файлы с текстовым представлением переводом, которые затем компилируются в бинарные файлы в процессе компиляции приложения.

Отличиями являются нестандартное расположение как файлов, которые необходимо локализовать, так и местоположение скомпилированных файлов локализации. Эти отличия требуют ручной настройки процесса компиляции и установки данных файлов.

В рамках примера переводы располагаются в каталоге settings-translations, в котором указана следующая конфигурация процесса сборки в .pro-файле:

TEMPLATE = aux

TRANSLATIONS = vpnprovider-vpn-plugin.ts \ # Default translation
			   vpnprovider-vpn-plugin-ru.ts \
			   vpnprovider-vpn-plugin-en_US.ts

for(t, TRANSLATIONS) {
	TRANSLATIONS_IN += $${_PRO_FILE_PWD_}/$$t
}

qm.files = $$replace(TRANSLATIONS_IN, \.ts, .qm)
qm.path = /usr/lib/qt5/qml/ru/omprussia/vpnprovider/translations
qm.CONFIG += no_check_exist
qm.commands += lupdate -no-obsolete -locations none $$PWD/.. -ts $$TRANSLATIONS_IN \
			   && lrelease -idbased $$TRANSLATIONS_IN

QMAKE_EXTRA_TARGETS += qm
INSTALLS += qm
PRE_TARGETDEPS += qm

QMAKE_CLEAN += "$$PWD/*.qm"

При адаптации данной конфигурации необходимо изменить название файлов-переводов в соответствии с названием приложения. Это название также необходимо учитывать в переводчике. Также необходимо изменить место установки .qm-файлов. Они должны устанавливаться в каталог QML-плагина.

Дополнительных изменений в .spec-файл не нужно, так как конфигурация, добавленная на этапе работы над QML-плагином включает в себя все файлы из соответствующего данному плагину каталога.

При выполнении локализации проекта рекомендуется использовать уникальные идентификаторы строк. Для выполнения этой задачи необходимо использовать функцию qsTrId() с передачей ей уникального идентификатора строки.

Идентификаторы строк должны быть уникальными в рамках всей системы ОС Аврора. Для достижения этой задачи рекомендуется использовать название плагина в качестве префикса для данных строк. Пример использования префикса можно посмотреть на странице редактирования подключения TrifleVpn.

Проект расширения приложения «Настройки»

QML-документы для расширения приложения «Настройки» располагаются в каталоге settings-controls. В данном каталоге следует создать подкаталог с названием провайдера, который будет поставляться. Данное название должно быть уникальным и не совпадать ни с одним стандартным каталогом провайдера. В рамках примера будем использовать имя vpnprovider.

Каталог расширения после установки RPM-пакета должен располагаться в каталоге /usr/share/sailfish-vpn. Для этого необходимо сформировать соответствующий .pro-файл:

TEMPLATE = aux
QT -= gui

OTHER_FILES += \
	vpnprovider/*.qml \

settings_files.files = vpnprovider
settings_files.path = /usr/share/sailfish-vpn/

INSTALLS += settings_files

При его адаптации необходимо изменить название каталога в переменных OTHER_FILES и settings_files.

Данные файлы также необходимо добавить в RPM-файл, добавив следующие строки в секцию %files .spec-файла:

%{_datadir}/sailfish-vpn/*

В каталоге должны находится QML-документы расширения. В настоящий момент поддерживаются следующие документы:

  • advanced.qml — вызывается при вызове расширенных настроек соединения;
  • details.qml — вызывается при просмотре параметров соединения;
  • edit.qml — вызывается при редактировании настроек соединения;
  • listitem.qml — элемент списка доступных плагинов VPN, динамически подгружающийся в системное меню при создании нового подключения.

Для реализации этих документов следует использовать QML-компоненты Sailfish.Settings.Networking.Vpn. Эти компоненты были специально разработаны для быстрого создания редакторов профилей VPN-соединений.

Поддержка нескольких выпусков ОС Аврора

QML-компоненты Sailfish.Settings.Networking.Vpn являются специфичными для конкретного выпуска ОС Аврора, т.е. между значимыми выпусками ОС публичный интерфейс данных компонентов может отличаться.

Для поддержки разных версий QML-компонентов в рамках одной кодовой базы необходимо усложнить структуру файлов расширения приложения «Настройки»: для каждого поддерживаемого выпуска создать отдельный каталог, в котором разместить QML-файлы соответствующей версии. Логика по выбору подходящего набора файлов размещается в конфигурации сборочной системы.

Предположим, что имеются QML-компоненты для поддержки третьей и четвёртой версии ОС Аврора. Для каждой версии требуется создать отдельный каталог:

settings-controls
├── aurora_3
│   └── vpnprovider
│       ├── advanced.qml
│       ├── details.qml
│       ├── edit.qml
│       └── listitem.qml
├── aurora_4
│   └── vpnprovider
│       ├── advanced.qml
│       ├── details.qml
│       ├── edit.qml
│       └── listitem.qml
└── settings-controls.pro

Для выбора нужного каталога в зависимости от версии в .pro-файл необходимо добавить определение версии ОС в рамках процесса сборки:

OTHER_FILES += \
	aurora_3/vpnprovider/*.qml \
	aurora_4/vpnprovider/*.qml

OSVERSION = $$system(cat /etc/issue | cut -d\' \' -f2)
VERSIONS = $$split(OSVERSION, ".")
VERSION_MAJ = $$member(VERSIONS, 0)

lessThan(VERSION_MAJ, 4) {
	settings_files.files = aurora_3/vpnprovider
	settings_files.path = /usr/share/sailfish-vpn/
} else {
	settings_files.files = aurora_4/vpnprovider
	settings_files.path = /usr/share/sailfish-vpn/
}
INSTALLS += settings_files

Если необходимо определить более точное деление между версиями, то следует брать второй элемент из массива VERSIONS.

Для каждого поддерживаемого выпуска ОС будет необходимо поставлять отдельные RPM-файлы.

Реализация документа для списка типов подключений listitem.qml

Данный документ используется для отображения позиции в списке типов подключений, которые доступны пользователю для создания новых профилей. Он должен предоставлять название VPN-провайдера и его краткое описание.

Корневым элементом данного документа должен стать тип VpnTypeItem. Этому элементу необходимо указать свойства:

  • name — наименование VPN-провайдера.
  • description — расширенное описание провайдера.

Для версии ОС Аврора 4:

  • canImport — поддерживается ли импорт профилей. Данное свойство рекомендуется в значение false, так как отсутствует публичное API для прямого редактирования параметров профиля VPN-подключения.

Для версии ОС Аврора 3:

  • vpnType — идентификатор VPN-плагина. Он должен совпадать с типом VPN-плагина для ConnMan.

Реализация документа для редактирования профиля подключений edit.qml

Данный документ используется для формирования параметров VPN-профиля как в момент создания, так и в случае редактирования. Корневым элементом данного документа должен быть VpnPlatformEditDialog. Данному компоненту необходимо установить следующие свойства:

  • vpnType — тип VPN-подключения. Он должен совпадать с типом VPN-плагина для ConnMan.

Для версии ОС Аврора 4:

  • newTitle — название для диалога, запущенного в режиме добавления нового VPN-профиля.
  • editTitle — название для диалога, запущенного в режиме редактирования существующего VPN-профиля.

Для версии ОС Аврора 3:

  • title — название для диалога. Рекомендуется выставлять значение в зависимости свойства newConnection, которое будет равно true в случае запуска при создании нового подключения.

Внутри корневого элемента должны быть размещены другие элементы, которые позволяют редактировать параметры подключения. Можно использовать как обычные компоненты Silica, так и компоненты Sailfish.Settings.Networking.Vpn.

Например для редактирования имени пользователя можно воспользоваться компонентом ConfigTextField:

ConfigTextField {
	id: vpnproviderVpnUsername
	//% "Username"
	label: qsTrId("vpnprovider-user_name")
}

Для работы с параметрами VPN-профиля необходимо при создании компонента:

  • Вызвать метод init().
  • Считать значения свойств профиля с помощью метода getProviderProperty(name).

При успешном закрытии диалога, в обработчике сигнала accepted:

  • Записать значения полей ввода в свойства профиля с помощью метода updateProvider.
  • Сохранить новые параметры профиля с помощью метода saveConnection().

Базовая структура обработки сообщений приведена ниже.

VpnPlatformEditDialog {

	// ...

	Component.onCompleted: {
		init();
		vpnproviderVpnUsername.text = getProviderProperty(vpnprovider.User');
	}

	onAccepted: {
		updateProvider(vpnprovider.User', vpnproviderVpnUsername.text);
		saveConnection();
	}
}

Реализация документа для расширенного редактирования профиля подключений advanced.qml

Данный документ используется для редактирования расширенного списка свойств VPN-профиля. Его корневым элементом должна быть колонка, Column. Данная колонка должна занимать всё доступное по ширине пространство родительского элемента. Родительским элементом выступает компонент VpnAdvancedSettingsPage, который предоставляет методы для записи параметров VPN-профиля.

Содержимым колонки должны быть элементы, которые позволяют редактировать расширенный набор параметров VPN-профиля. Данные параметры не должны пересекаться с параметрами на основной странице редактирования. На странице можно использовать такие же компоненты, как и при реализации документа edit.qml.

Компонент также должен предлагать публичные функции setProperties и updateProperties.

Метод setProperties вызывается в момент показа данного компонента. Его следует использовать для установления состояния графических компонентов редактора на основании параметров VPN-профиля. Для получения значения поля следует использовать метод getProperty(name).

Метод updateProperties вызывается для сохранения значений полей ввода в свойства VPN-профиля. Для выполнения этой задачи следует использовать метод updateProvider.

В качестве примера рассмотрим страницу с одним дополнительным свойством логического типа.

Column {
	function setProperties() {
		vpnproviderAllowSelfSignedCert.checked = getProperty(
			'vpnprovider.AllowSelfSignedCert') === 'true';
	}

	function updateProperties() {
		updateProvider('vpnprovider.AllowSelfSignedCert',
			vpnproviderAllowSelfSignedCert.checked ? 'true' : 'false');
	}

	TextSwitch {
		id: vpnproviderAllowSelfSignedCert
		objectName: "vpnproviderAllowSelfSignedCert"
		//% "Allow self signed certificate"
		text: qsTrId("vpnprovider-allow_self_signed_certificate")
	}
}

Реализация документа для просмотра параметров подключения details.qml

Данный документ используется для отображения информации о подключении. Его корневым элементом должна быть страница VpnPlatformsDetailsPage. Этому компоненту необходимо указать значение свойства subtitle, в котором расположить наименование VPN-провайдера.

Данная страница самостоятельно отобразит все свойства, которые были записаны в VPN-профиль во время его редактирования.

Расширение с использованием внешнего менеджера конфигураций

В рамках данной схемы расширения необходимо реализовать те же компоненты, что и в рамках первой схемы, но также придётся реализовать приложение — менеджер конфигураций и организовать взаимодействие между ним и расширением приложения «Настройки».

Схемы взаимодействия компонентов расширения

Рассмотрим схему, при которой менеджер конфигураций формирует параметры подключения в собственном формате VPN-клиента. Данных конфигурационных файлов должно быть достаточно для установления VPN-подключения. При таком подходе в рамках VPN-профиля будет храниться минимальный набор данных для работы VPN-плагина.

Данная схема по распределению обязанностей между компонентами обладает следующими преимуществами:

  • Не надо реализовывать схему синхронизации параметров соединения между менеджером конфигурации и приложением «Настройки».
  • Объём данных внутри VPN-профиля минимальный, что облегчает реализацию расширения внутри приложения «Настройки» и ConnMan-плагина.

Существенным минусом такого подхода является то, что пользователь может удалить конфигурацию внутри менеджера конфигурации, но не исправить соответствующий ей VPN-профиль.

Альтернативной схемой является передача всех параметров подключения в VPN-профиль. Преимуществом данной схемы является самодостаточность VPN-профиля, однако помимо проблемы удаления появляется также проблема синхронизации содержимого конфигурации и VPN-профиля.

Сценарий выполнения VPN-подключения

  1. Пользователь формирует конфигурацию VPN-подключения внутри менеджера конфигураций через его графический пользовательский интерфейс.
  2. Пользователь открывает приложение «Настройки» и формирует VPN-профиль подключения для нужного VPN-провайдера.
  3. В момент формирования VPN-профиля пользователь нажимает кнопку выбора внешней конфигурации VPN-подключения.
  4. Приложение «Настройки» запрашивает у менеджера конфигураций VPN-профиль путём отправки D-Bus запроса в менеджер конфигураций.
  5. При получении запроса менеджер конфигураций отображает диалог для выбора конфигурации из списка сформированных конфигураций.
  6. Пользователь выбирает нужную VPN-конфигурацию и подтверждает свой выбор в диалоге.
  7. Система отображает VPN-профиль с заполненным полем внешней конфигурации.
  8. Пользователь заполняет дополнительные поля, которые необходимы для полноценного формирования VPN-профиля, параметры VPN-плагина ConnMan. Пользователь завершает формирование VPN-профиля.
  9. Пользователь инициирует подключение согласно сформированному VPN-профилю.
  10. VPN-плагин ConnMan использует полученные параметры: запрашивает имя пользователя и пароль, одноразовый пароль, если это необходимо. Затем передаёт путь к VPN-конфигурации и дополнительные параметры VPN-клиенту.

В рамках данного сценария конфигурации подключения хранятся в домашней директории пользователя. Если в рамках VPN-профиля хранится путь к данной конфигурации, то необходимо удостоверится, что VPN-клиенту указанные файлы будут доступны на чтение в момент исполнения.

Реализация D-Bus сервиса менеджера конфигураций

В основе взаимодействия между приложениями «Настройки» и менеджером конфигураций лежит обмен сообщениями с помощью D-Bus. Менеджер конфигураций должен предоставлять службу для получения пути к VPN-конфигурации, а приложение «Настройки» будет обращаться к данной службе. Детали реализации такого рода взаимодействия в рамках приложений под ОС Аврора можно найти в соответствующем разделе документации. В рамках данного раздела рассмотрим ключевые детали реализации такого взаимодействия.

Сначала необходимо спроектировать интерфейс службы:

  • определить название интерфейса;
  • выбрать название метода для вызова менеджера конфигурации для получения VPN-конфигурации;
  • сформировать набор данных, которые должны быть возвращены данным методом.

Название интерфейса должно быть уникальным в рамках платформы, рекомендуется использовать доменное имя организации вместе с названием приложения, например ru.omp.VpnProviderConfigurator.

Следующий этап — реализовать D-Bus-службу в рамках менеджера конфигураций. При старте менеджера конфигураций служба должна регистрироваться на сессионной шине D-Bus и ожидать входящих запросов от приложения «Настройки». Для реализации службы можно воспользоваться как QML-типом QDBusAdaptor, так и решением на уровне C++.

По умолчанию служба будет доступна исключительно в случае, когда приложение активно. Для обеспечения поддержки запуска приложения при обращении к D-Bus-службе необходимо разместить её описание в каталоге $XDG_DATA_HOME/dbus-1/services. Таким образом при поступлении запроса к описанной службе будет произведён запуск приложения.

Приложение должно размещать конфигурационный файл D-Bus-службы при первом старте.
Пример такой конфигурации приведён ниже:

[D-BUS Service]
Name=ru.omp.vpnprovider-configurator
Exec=/usr/bin/vpnprovider-configurator --select-configuration

Для разделения ситуации запуска из системы D-Bus и из списка приложений приложению передаётся дополнительный аргумент. В случае примера — это --select-configuration. В рамках .desktop-файла данный аргумент приложению не передаётся. В зависимости от наличия данного аргумента менеджер конфигураций будет запускаться либо в режиме редактора, либо в режиме выбора.

Вызов менеджера конфигураций из страницы редактирования VPN-профиля

Для доступа к D-Bus-службе со стороны расширения приложения «Настройки» можно разместить как в QML-плагине (реализовать взаимодействие на уровне языка C++), так и на уровне QML-расширения (реализовать взаимодействие с помощью QML) с использованием типа QDbusInterface.

Рассмотрим процесс реализации данной логики внутри QML-плагина. Для решения задачи потребуется описать новый QML-компонент, который будет предоставлять метод для получения информации от D-Bus-службы и два сигнала для обработки успешной и ошибочной ситуации при получении данных.

Данный QML-компонент необходимо создать на экране редактирования подключения edit.qml. На экране редактирования также потребуется разместить кнопку, по нажатию на которую необходимо вызвать метод для получения пути к конфигурации. Также в рамках обработки нажатия рекомендуется заблокировать кнопку, чтобы исключить повторное нажатие.

В рамках обработки успешного сигнала о получении конфигурации необходимо сохранить путь к конфигурационному файлу в соответствующий параметр VPN-профиля, отобразить название файла в соответствующем текстовом поле на странице редактирования подключения. В случае неудачного соединения необходимо отобразить соответствующее ошибке сообщение пользователю, чтобы он смог попытаться решить данную ситуацию. При получении любого из сигналов кнопку необходимо разблокировать.

VpnPlatformEditDialog {
	property string vpnConfigurationData

	function basename(str) {
		return (str.slice(str.lastIndexOf("/")+1))
	}

	Connections {
		target: vpnproviderConfiguratorAdaptor
		onConfigurationReceived: {
			vpnConfigurationData = config
			vpnproviderConfig.enabled = true
		}
	}

	VpnproviderConfiguratorAdaptor {
		id: vpnproviderConfiguratorAdaptor
		objectName: "vpnproviderConfiguratorAdaptor"
	}

	ValueButton {
		id: vpnproviderConfig

		objectName: "configValueButton"
		//% "Select"
		label: qsTrId("vpnprovider-config_button")
		value: basename(vpnConfigurationData)

		onClicked: {
			vpnproviderConfig.enabled = false
			vpnproviderConfiguratorAdaptor.getConfigurationData()
		}
	}
}

Мы используем cookies для персонализации сайта и его более удобного использования. Вы можете запретить cookies в настройках браузера.

Пожалуйста ознакомьтесь с политикой использования cookies.