2025-02-15 11:50:42 +07:00
|
|
|
|
#include "coreController.h"
|
|
|
|
|
|
|
2026-04-13 07:14:42 +04:00
|
|
|
|
#include <QCoreApplication>
|
2025-03-24 09:35:22 +02:00
|
|
|
|
#include <QDirIterator>
|
2025-12-31 18:48:57 +04:00
|
|
|
|
#include <QDebug>
|
2025-02-15 15:29:53 +07:00
|
|
|
|
#include <QTranslator>
|
2025-08-08 06:44:18 +04:00
|
|
|
|
#include <QStandardPaths>
|
2026-04-30 14:53:03 +08:00
|
|
|
|
#include <QTimer>
|
|
|
|
|
|
|
|
|
|
|
|
#include "core/utils/selfhosted/sshSession.h"
|
|
|
|
|
|
#include "core/controllers/selfhosted/installController.h"
|
|
|
|
|
|
#include "core/controllers/selfhosted/importController.h"
|
|
|
|
|
|
#include "core/controllers/coreSignalHandlers.h"
|
|
|
|
|
|
#include "logger.h"
|
|
|
|
|
|
#include "secureQSettings.h"
|
2025-02-15 15:29:53 +07:00
|
|
|
|
|
2025-02-15 11:50:42 +07:00
|
|
|
|
#if defined(Q_OS_ANDROID)
|
2026-04-30 14:53:03 +08:00
|
|
|
|
#include "core/utils/installedAppsImageProvider.h"
|
2025-02-15 11:50:42 +07:00
|
|
|
|
#include "platforms/android/android_controller.h"
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(Q_OS_IOS)
|
|
|
|
|
|
#include "platforms/ios/ios_controller.h"
|
|
|
|
|
|
#include <AmneziaVPN-Swift.h>
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
CoreController::CoreController(const QSharedPointer<VpnConnection> &vpnConnection, SecureQSettings* settings,
|
2025-02-15 11:50:42 +07:00
|
|
|
|
QQmlApplicationEngine *engine, QObject *parent)
|
|
|
|
|
|
: QObject(parent), m_vpnConnection(vpnConnection), m_settings(settings), m_engine(engine)
|
|
|
|
|
|
{
|
2026-04-30 14:53:03 +08:00
|
|
|
|
initRepositories();
|
|
|
|
|
|
initCoreControllers();
|
2025-02-15 11:50:42 +07:00
|
|
|
|
initModels();
|
|
|
|
|
|
initControllers();
|
|
|
|
|
|
initSignalHandlers();
|
|
|
|
|
|
|
2025-02-25 18:29:58 +03:00
|
|
|
|
initAndroidController();
|
|
|
|
|
|
initAppleController();
|
2026-04-30 14:53:03 +08:00
|
|
|
|
initLogging();
|
2025-02-25 18:29:58 +03:00
|
|
|
|
|
2026-05-29 05:10:27 +04:00
|
|
|
|
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
|
2025-08-08 06:44:18 +04:00
|
|
|
|
initLocalProxy();
|
2026-05-29 05:10:27 +04:00
|
|
|
|
#endif
|
2025-08-08 06:44:18 +04:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_translator = new QTranslator(this);
|
|
|
|
|
|
if (m_appSettingsRepository) {
|
|
|
|
|
|
updateTranslator(m_appSettingsRepository->getAppLanguage());
|
|
|
|
|
|
}
|
2025-02-15 11:50:42 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
void CoreController::setQmlContextProperty(const QString &name, QObject *value)
|
2025-08-08 06:44:18 +04:00
|
|
|
|
{
|
2026-04-30 14:53:03 +08:00
|
|
|
|
if (m_engine) {
|
|
|
|
|
|
m_engine->rootContext()->setContextProperty(name, value);
|
|
|
|
|
|
}
|
2025-02-15 11:50:42 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-08 06:44:18 +04:00
|
|
|
|
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
|
2026-05-29 05:10:27 +04:00
|
|
|
|
void CoreController::initLocalProxy()
|
|
|
|
|
|
{
|
2026-01-27 11:09:27 +04:00
|
|
|
|
constexpr quint16 kLocalProxyApiPort = 49490;
|
|
|
|
|
|
|
2026-05-29 05:10:27 +04:00
|
|
|
|
m_proxyServer.reset(new ProxyServer(m_serversRepository, m_appSettingsRepository, this));
|
2025-12-31 18:48:57 +04:00
|
|
|
|
|
2026-04-13 07:14:42 +04:00
|
|
|
|
QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, [this]() {
|
2026-05-29 05:10:27 +04:00
|
|
|
|
if (m_appSettingsRepository && m_appSettingsRepository->isLocalProxyHttpEnabled()) {
|
|
|
|
|
|
m_appSettingsRepository->setLocalProxyHttpEnabled(false);
|
2026-04-13 07:14:42 +04:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-12-31 18:48:57 +04:00
|
|
|
|
auto syncLocalProxy = [this]() {
|
|
|
|
|
|
if (!m_proxyServer) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-29 05:10:27 +04:00
|
|
|
|
const bool httpEnabled = m_appSettingsRepository->isLocalProxyHttpEnabled();
|
2025-12-31 18:48:57 +04:00
|
|
|
|
|
|
|
|
|
|
if (!httpEnabled) {
|
|
|
|
|
|
qInfo() << "Local proxy: HTTP API disabled";
|
|
|
|
|
|
m_proxyServer->stop();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-27 11:09:27 +04:00
|
|
|
|
if (!m_proxyServer->start(kLocalProxyApiPort)) {
|
|
|
|
|
|
qWarning() << "Local proxy: failed to start on port" << kLocalProxyApiPort;
|
2026-05-29 05:10:27 +04:00
|
|
|
|
m_appSettingsRepository->setLocalProxyHttpEnabled(false);
|
|
|
|
|
|
emit m_appSettingsRepository->localProxyStartFailed(tr("Local proxy failed to start. Check if the port is available."));
|
2025-12-31 18:48:57 +04:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-13 15:46:27 +04:00
|
|
|
|
if (!m_proxyServer->syncSettings()) {
|
|
|
|
|
|
qWarning() << "Local proxy: failed to start proxy core (Xray)";
|
2026-05-29 05:10:27 +04:00
|
|
|
|
m_appSettingsRepository->setLocalProxyHttpEnabled(false);
|
|
|
|
|
|
emit m_appSettingsRepository->localProxyStartFailed(tr("Couldn’t start the proxy due to an internal error. Try restarting the app."));
|
2026-02-13 15:46:27 +04:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-01-27 11:09:27 +04:00
|
|
|
|
|
|
|
|
|
|
qInfo() << "Local proxy: running on 127.0.0.1:" << kLocalProxyApiPort;
|
2025-12-31 18:48:57 +04:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
syncLocalProxy();
|
|
|
|
|
|
|
2026-05-29 05:10:27 +04:00
|
|
|
|
connect(m_appSettingsRepository, &SecureAppSettingsRepository::localProxySettingsChanged, this, syncLocalProxy);
|
|
|
|
|
|
|
|
|
|
|
|
connect(m_serversRepository, &SecureServersRepository::serverEdited, this, [this](const QString &serverId) {
|
|
|
|
|
|
if (m_appSettingsRepository && m_appSettingsRepository->isLocalProxyHttpEnabled()
|
|
|
|
|
|
&& m_appSettingsRepository->localProxyOwnerId() == serverId) {
|
|
|
|
|
|
m_appSettingsRepository->bumpLocalProxyRestartToken();
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
connect(m_serversRepository, &SecureServersRepository::serverRemoved, this, [this](const QString &serverId, int) {
|
|
|
|
|
|
if (m_appSettingsRepository && m_appSettingsRepository->localProxyOwnerId() == serverId) {
|
|
|
|
|
|
m_appSettingsRepository->setLocalProxyOwnerId(QString());
|
|
|
|
|
|
m_appSettingsRepository->setLocalProxyHttpEnabled(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-08-08 06:44:18 +04:00
|
|
|
|
}
|
2026-05-29 05:10:27 +04:00
|
|
|
|
#endif
|
2025-08-08 06:44:18 +04:00
|
|
|
|
|
2025-02-15 11:50:42 +07:00
|
|
|
|
void CoreController::initModels()
|
|
|
|
|
|
{
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_containersModel = new ContainersModel(this);
|
|
|
|
|
|
setQmlContextProperty("ContainersModel", m_containersModel);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_defaultServerContainersModel = new ContainersModel(this);
|
|
|
|
|
|
setQmlContextProperty("DefaultServerContainersModel", m_defaultServerContainersModel);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_serversModel = new ServersModel(this);
|
|
|
|
|
|
setQmlContextProperty("ServersModel", m_serversModel);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_languageModel = new LanguageModel(this);
|
|
|
|
|
|
setQmlContextProperty("LanguageModel", m_languageModel);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_ipSplitTunnelingModel = new IpSplitTunnelingModel(this);
|
|
|
|
|
|
setQmlContextProperty("IpSplitTunnelingModel", m_ipSplitTunnelingModel);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_allowedDnsModel = new AllowedDnsModel(this);
|
|
|
|
|
|
setQmlContextProperty("AllowedDnsModel", m_allowedDnsModel);
|
2025-05-02 23:54:36 -07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_appSplitTunnelingModel = new AppSplitTunnelingModel(this);
|
|
|
|
|
|
setQmlContextProperty("AppSplitTunnelingModel", m_appSplitTunnelingModel);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_protocolsModel = new ProtocolsModel(this);
|
|
|
|
|
|
setQmlContextProperty("ProtocolsModel", m_protocolsModel);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_openVpnConfigModel = new OpenVpnConfigModel(this);
|
|
|
|
|
|
setQmlContextProperty("OpenVpnConfigModel", m_openVpnConfigModel);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_wireGuardConfigModel = new WireGuardConfigModel(this);
|
|
|
|
|
|
setQmlContextProperty("WireGuardConfigModel", m_wireGuardConfigModel);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_awgConfigModel = new AwgConfigModel(this);
|
|
|
|
|
|
setQmlContextProperty("AwgConfigModel", m_awgConfigModel);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_xrayConfigModel = new XrayConfigModel(this);
|
|
|
|
|
|
setQmlContextProperty("XrayConfigModel", m_xrayConfigModel);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-05-18 17:35:01 +03:00
|
|
|
|
m_xrayConfigSnapshotsModel = new XrayConfigSnapshotsModel(m_appSettingsRepository, m_xrayConfigModel, this);
|
|
|
|
|
|
setQmlContextProperty("XrayConfigSnapshotsModel", m_xrayConfigSnapshotsModel);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_torConfigModel = new TorConfigModel(this);
|
|
|
|
|
|
setQmlContextProperty("TorConfigModel", m_torConfigModel);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
|
|
|
|
|
#ifdef Q_OS_WINDOWS
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_ikev2ConfigModel = new Ikev2ConfigModel(this);
|
|
|
|
|
|
setQmlContextProperty("Ikev2ConfigModel", m_ikev2ConfigModel);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
#endif
|
|
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_sftpConfigModel = new SftpConfigModel(this);
|
|
|
|
|
|
setQmlContextProperty("SftpConfigModel", m_sftpConfigModel);
|
|
|
|
|
|
|
|
|
|
|
|
m_socks5ConfigModel = new Socks5ProxyConfigModel(this);
|
|
|
|
|
|
setQmlContextProperty("Socks5ProxyConfigModel", m_socks5ConfigModel);
|
|
|
|
|
|
|
2026-05-18 14:52:58 +03:00
|
|
|
|
m_mtProxyConfigModel = new MtProxyConfigModel(this);
|
|
|
|
|
|
setQmlContextProperty("MtProxyConfigModel", m_mtProxyConfigModel);
|
|
|
|
|
|
|
2026-05-18 15:01:09 +03:00
|
|
|
|
m_telemtConfigModel = new TelemtConfigModel(this);
|
|
|
|
|
|
setQmlContextProperty("TelemtConfigModel", m_telemtConfigModel);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_clientManagementModel = new ClientManagementModel(this);
|
|
|
|
|
|
setQmlContextProperty("ClientManagementModel", m_clientManagementModel);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_apiServicesModel = new ApiServicesModel(this);
|
|
|
|
|
|
setQmlContextProperty("ApiServicesModel", m_apiServicesModel);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_apiCountryModel = new ApiCountryModel(this);
|
|
|
|
|
|
setQmlContextProperty("ApiCountryModel", m_apiCountryModel);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_apiSubscriptionPlansModel = new ApiSubscriptionPlansModel(this);
|
|
|
|
|
|
setQmlContextProperty("ApiSubscriptionPlansModel", m_apiSubscriptionPlansModel);
|
2026-04-08 11:21:12 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_apiBenefitsModel = new ApiBenefitsModel(this);
|
|
|
|
|
|
setQmlContextProperty("ApiBenefitsModel", m_apiBenefitsModel);
|
2026-04-08 11:21:12 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_apiAccountInfoModel = new ApiAccountInfoModel(this);
|
|
|
|
|
|
setQmlContextProperty("ApiAccountInfoModel", m_apiAccountInfoModel);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_apiDevicesModel = new ApiDevicesModel(this);
|
|
|
|
|
|
setQmlContextProperty("ApiDevicesModel", m_apiDevicesModel);
|
2025-02-28 18:17:43 +03:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_newsModel = new NewsModel(m_appSettingsRepository, this);
|
|
|
|
|
|
setQmlContextProperty("NewsModel", m_newsModel);
|
|
|
|
|
|
}
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
void CoreController::initRepositories()
|
|
|
|
|
|
{
|
|
|
|
|
|
m_serversRepository = new SecureServersRepository(m_settings, this);
|
|
|
|
|
|
m_appSettingsRepository = new SecureAppSettingsRepository(m_settings, this);
|
2025-10-06 08:06:36 +04:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
if (m_vpnConnection) {
|
|
|
|
|
|
m_vpnConnection->setRepositories(m_serversRepository, m_appSettingsRepository);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-10-06 08:06:36 +04:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
void CoreController::initCoreControllers()
|
|
|
|
|
|
{
|
|
|
|
|
|
m_serversController = new ServersController(m_serversRepository, m_appSettingsRepository, this);
|
|
|
|
|
|
m_appSplitTunnelingController = new AppSplitTunnelingController(m_appSettingsRepository);
|
|
|
|
|
|
m_usersController = new UsersController(m_serversRepository, this);
|
|
|
|
|
|
m_ipSplitTunnelingController = new IpSplitTunnelingController(m_appSettingsRepository, this);
|
|
|
|
|
|
m_allowedDnsController = new AllowedDnsController(m_appSettingsRepository);
|
|
|
|
|
|
m_servicesCatalogController = new ServicesCatalogController(m_appSettingsRepository);
|
|
|
|
|
|
m_subscriptionController = new SubscriptionController(m_serversRepository, m_appSettingsRepository);
|
2026-05-15 12:33:36 +08:00
|
|
|
|
m_newsController = new NewsController(m_appSettingsRepository, m_serversRepository);
|
2026-05-04 07:37:19 +03:00
|
|
|
|
m_updateController = new UpdateController(m_appSettingsRepository, this);
|
2026-04-30 14:53:03 +08:00
|
|
|
|
|
|
|
|
|
|
m_installController = new InstallController(m_serversRepository, m_appSettingsRepository, this);
|
|
|
|
|
|
m_exportController = new ExportController(m_serversRepository, m_appSettingsRepository, this);
|
|
|
|
|
|
m_importCoreController = new ImportController(m_serversRepository, m_appSettingsRepository, this);
|
|
|
|
|
|
m_connectionController = new ConnectionController(m_serversRepository, m_appSettingsRepository, m_vpnConnection.get(), this);
|
|
|
|
|
|
m_settingsController = new SettingsController(m_serversRepository, m_appSettingsRepository, this);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoreController::initControllers()
|
|
|
|
|
|
{
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_connectionUiController = new ConnectionUiController(m_connectionController, m_serversController, this);
|
|
|
|
|
|
setQmlContextProperty("ConnectionController", m_connectionUiController);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
if (m_engine) {
|
|
|
|
|
|
m_focusController = new FocusController(m_engine, this);
|
|
|
|
|
|
setQmlContextProperty("FocusController", m_focusController);
|
|
|
|
|
|
}
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-05-15 12:33:36 +08:00
|
|
|
|
m_installUiController = new InstallUiController(m_installController, m_serversController, m_settingsController, m_protocolsModel, m_usersController,
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_awgConfigModel, m_wireGuardConfigModel, m_openVpnConfigModel, m_xrayConfigModel, m_torConfigModel,
|
|
|
|
|
|
#ifdef Q_OS_WINDOWS
|
|
|
|
|
|
m_ikev2ConfigModel,
|
|
|
|
|
|
#endif
|
2026-05-18 15:01:09 +03:00
|
|
|
|
m_sftpConfigModel, m_socks5ConfigModel, m_mtProxyConfigModel, m_telemtConfigModel, this);
|
2026-04-30 14:53:03 +08:00
|
|
|
|
setQmlContextProperty("InstallController", m_installUiController);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_importController = new ImportUiController(m_importCoreController, this);
|
|
|
|
|
|
setQmlContextProperty("ImportController", m_importController);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_exportUiController = new ExportUiController(m_exportController, this);
|
|
|
|
|
|
setQmlContextProperty("ExportController", m_exportUiController);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_languageUiController = new LanguageUiController(m_settingsController, m_languageModel, this);
|
|
|
|
|
|
setQmlContextProperty("LanguageUiController", m_languageUiController);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_settingsUiController = new SettingsUiController(m_settingsController, m_serversController, m_languageUiController, this);
|
|
|
|
|
|
setQmlContextProperty("SettingsController", m_settingsUiController);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_pageController = new PageController(m_serversController, m_settingsController, this);
|
|
|
|
|
|
setQmlContextProperty("PageController", m_pageController);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-05-29 05:10:27 +04:00
|
|
|
|
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
|
|
|
|
|
|
connect(m_connectionController, &ConnectionController::localProxyStoppedBecauseVpnTurnedOn, m_pageController,
|
|
|
|
|
|
&PageController::showNotificationMessage);
|
|
|
|
|
|
#endif
|
2025-08-01 07:52:11 +04:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_serversUiController = new ServersUiController(m_serversController, m_settingsController, m_serversModel, m_containersModel, m_defaultServerContainersModel, this);
|
|
|
|
|
|
setQmlContextProperty("ServersUiController", m_serversUiController);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_ipSplitTunnelingUiController = new IpSplitTunnelingUiController(m_ipSplitTunnelingController, m_ipSplitTunnelingModel, this);
|
|
|
|
|
|
setQmlContextProperty("IpSplitTunnelingController", m_ipSplitTunnelingUiController);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_allowedDnsUiController = new AllowedDnsUiController(m_allowedDnsController, m_allowedDnsModel, this);
|
|
|
|
|
|
setQmlContextProperty("AllowedDnsController", m_allowedDnsUiController);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_appSplitTunnelingUiController = new AppSplitTunnelingUiController(m_appSplitTunnelingController, m_appSplitTunnelingModel, this);
|
|
|
|
|
|
setQmlContextProperty("AppSplitTunnelingController", m_appSplitTunnelingUiController);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_systemController = new SystemController(this);
|
|
|
|
|
|
setQmlContextProperty("SystemController", m_systemController);
|
2025-05-02 23:54:36 -07:00
|
|
|
|
|
2026-05-18 14:52:58 +03:00
|
|
|
|
m_networkReachabilityController = new NetworkReachabilityController(this);
|
|
|
|
|
|
m_engine->rootContext()->setContextProperty("NetworkReachabilityController", m_networkReachabilityController);
|
|
|
|
|
|
m_engine->rootContext()->setContextProperty("NetworkReachability", m_networkReachabilityController);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_servicesCatalogUiController = new ServicesCatalogUiController(m_servicesCatalogController, m_apiServicesModel, this);
|
|
|
|
|
|
setQmlContextProperty("ServicesCatalogUiController", m_servicesCatalogUiController);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_subscriptionUiController = new SubscriptionUiController(m_serversController, m_apiServicesModel, m_servicesCatalogController, m_subscriptionController,
|
|
|
|
|
|
m_apiSubscriptionPlansModel, m_apiBenefitsModel, m_apiAccountInfoModel,
|
|
|
|
|
|
m_apiCountryModel, m_apiDevicesModel, m_settingsController, this);
|
|
|
|
|
|
setQmlContextProperty("SubscriptionUiController", m_subscriptionUiController);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_apiNewsUiController = new ApiNewsUiController(m_newsModel, m_newsController, this);
|
|
|
|
|
|
setQmlContextProperty("ApiNewsController", m_apiNewsUiController);
|
2025-05-13 12:29:33 +08:00
|
|
|
|
|
2026-05-04 07:37:19 +03:00
|
|
|
|
m_updateUiController = new UpdateUiController(m_updateController, this);
|
|
|
|
|
|
setQmlContextProperty("UpdateController", m_updateUiController);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoreController::initAndroidController()
|
|
|
|
|
|
{
|
|
|
|
|
|
#ifdef Q_OS_ANDROID
|
|
|
|
|
|
if (!AndroidController::initLogging()) {
|
|
|
|
|
|
qFatal("Android logging initialization failed");
|
|
|
|
|
|
}
|
2026-04-30 14:53:03 +08:00
|
|
|
|
AndroidController::instance()->setSaveLogs(m_appSettingsRepository->isSaveLogs());
|
|
|
|
|
|
AndroidController::instance()->setScreenshotsEnabled(m_appSettingsRepository->isScreenshotsEnabled());
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
|
|
|
|
|
if (!AndroidController::instance()->initialize()) {
|
|
|
|
|
|
qFatal("Android controller initialization failed");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
if (m_engine) {
|
|
|
|
|
|
m_engine->addImageProvider(QLatin1String("installedAppImage"), new InstalledAppsImageProvider);
|
|
|
|
|
|
}
|
2025-02-15 11:50:42 +07:00
|
|
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoreController::initAppleController()
|
|
|
|
|
|
{
|
|
|
|
|
|
#ifdef Q_OS_IOS
|
|
|
|
|
|
IosController::Instance()->initialize();
|
2026-04-30 14:53:03 +08:00
|
|
|
|
QTimer::singleShot(0, this, [this]() { AmneziaVPN::toggleScreenshots(m_appSettingsRepository->isScreenshotsEnabled()); });
|
2025-02-15 11:50:42 +07:00
|
|
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
void CoreController::initLogging()
|
2025-02-15 11:50:42 +07:00
|
|
|
|
{
|
2026-04-30 14:53:03 +08:00
|
|
|
|
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
|
|
|
|
|
|
bool enabled = m_appSettingsRepository->isSaveLogs();
|
|
|
|
|
|
if (enabled) {
|
|
|
|
|
|
if (!Logger::init(false)) {
|
|
|
|
|
|
qWarning() << "Initialization of debug subsystem failed";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
Logger::setServiceLogsEnabled(enabled);
|
|
|
|
|
|
#endif
|
2025-02-15 11:50:42 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
void CoreController::initSignalHandlers()
|
2025-02-15 11:50:42 +07:00
|
|
|
|
{
|
2026-04-30 14:53:03 +08:00
|
|
|
|
m_signalHandlers = new CoreSignalHandlers(this, this);
|
|
|
|
|
|
m_signalHandlers->initAllHandlers();
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
// Trigger initial update after handlers are connected
|
|
|
|
|
|
m_serversUiController->updateModel();
|
2026-05-15 12:33:36 +08:00
|
|
|
|
if (m_serversUiController->hasServersFromGatewayApi()) {
|
|
|
|
|
|
m_apiNewsUiController->fetchNews(false);
|
|
|
|
|
|
}
|
2025-02-15 11:50:42 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoreController::updateTranslator(const QLocale &locale)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!m_translator->isEmpty()) {
|
2026-04-30 14:53:03 +08:00
|
|
|
|
QCoreApplication::removeTranslator(m_translator);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-03-24 09:35:22 +02:00
|
|
|
|
QStringList availableTranslations;
|
|
|
|
|
|
QDirIterator it(":/translations", QStringList("amneziavpn_*.qm"), QDir::Files);
|
|
|
|
|
|
while (it.hasNext()) {
|
|
|
|
|
|
availableTranslations << it.next();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// This code allow to load translation for the language only, without country code
|
|
|
|
|
|
const QString lang = locale.name().split("_").first();
|
|
|
|
|
|
const QString translationFilePrefix = QString(":/translations/amneziavpn_") + lang;
|
|
|
|
|
|
QString strFileName = QString(":/translations/amneziavpn_%1.qm").arg(locale.name());
|
|
|
|
|
|
for (const QString &translation : availableTranslations) {
|
|
|
|
|
|
if (translation.contains(translationFilePrefix)) {
|
|
|
|
|
|
strFileName = translation;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-15 11:50:42 +07:00
|
|
|
|
if (m_translator->load(strFileName)) {
|
2026-04-30 14:53:03 +08:00
|
|
|
|
QCoreApplication::installTranslator(m_translator);
|
2025-02-15 11:50:42 +07:00
|
|
|
|
} else {
|
2026-04-30 14:53:03 +08:00
|
|
|
|
if (m_translator->load(QString(":/translations/amneziavpn_en.qm"))) {
|
|
|
|
|
|
QCoreApplication::installTranslator(m_translator);
|
|
|
|
|
|
}
|
2025-02-15 11:50:42 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
if (m_engine) {
|
|
|
|
|
|
m_engine->retranslate();
|
|
|
|
|
|
}
|
2025-02-15 11:50:42 +07:00
|
|
|
|
|
|
|
|
|
|
emit translationsUpdated();
|
2026-04-30 14:53:03 +08:00
|
|
|
|
if (m_languageUiController) {
|
|
|
|
|
|
emit websiteUrlChanged(m_languageUiController->getCurrentSiteUrl());
|
|
|
|
|
|
}
|
2025-02-19 20:27:15 +07:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-15 11:50:42 +07:00
|
|
|
|
void CoreController::setQmlRoot()
|
|
|
|
|
|
{
|
2026-04-30 14:53:03 +08:00
|
|
|
|
if (m_engine && m_systemController) {
|
|
|
|
|
|
m_systemController->setQmlRoot(m_engine->rootObjects().value(0));
|
2025-02-15 11:50:42 +07:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-30 14:53:03 +08:00
|
|
|
|
PageController* CoreController::pageController() const
|
2025-02-15 11:50:42 +07:00
|
|
|
|
{
|
|
|
|
|
|
return m_pageController;
|
|
|
|
|
|
}
|
2025-12-11 18:54:24 +08:00
|
|
|
|
|
|
|
|
|
|
void CoreController::openConnectionByIndex(int serverIndex)
|
|
|
|
|
|
{
|
2026-05-15 12:33:36 +08:00
|
|
|
|
const QString serverId =
|
|
|
|
|
|
m_serversUiController ? m_serversUiController->getServerId(serverIndex) : QString();
|
|
|
|
|
|
if (serverId.isEmpty()) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-12-11 18:54:24 +08:00
|
|
|
|
if (m_serversModel) {
|
|
|
|
|
|
m_serversModel->setProcessedServerIndex(serverIndex);
|
|
|
|
|
|
}
|
2026-04-30 14:53:03 +08:00
|
|
|
|
if (m_serversController) {
|
2026-05-15 12:33:36 +08:00
|
|
|
|
m_serversController->setDefaultServer(serverId);
|
2026-04-30 14:53:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
m_connectionUiController->toggleConnection();
|
2025-12-11 18:54:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CoreController::importConfigFromData(const QString &data)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!m_importController)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (m_importController->extractConfigFromData(data)) {
|
|
|
|
|
|
m_importController->importConfig();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|