
* add focusController class * add more key handlers * add focus navigation to qml * fixed language selector * add reverse focus change to FocusController * add default focus item * update transitions * update pages * add ListViewFocusController * fix ListView navigation * update CardType for using with focus navigation * remove useless key navigation * remove useless slots, logs, Drawer open and close * fix reverse focus move on listView * fix drawer radio buttons selection * fix drawer layout and focus move * fix PageSetupWizardProtocolSettings focus move * fix back navigation on default focus item * fix crashes after ListView navigation * fix protocol settings focus move * fix focus on users on page share * clean up page share * fix server rename * fix page share default server selection * refactor about page for correct focus move * fix focus move on list views with header and-or footer * minor fixes * fix server list back button handler * fix spawn signals on switch * fix share details drawer * fix drawer open close usage * refactor listViewFocusController * refactor focusController to make the logic more straightforward * fix focus on notification * update config page for scrolling with tab * fix crash on return with esc key * fix focus navigation in dynamic delegate of list view * fix focus move on qr code on share page * refactor page logging settings for focus navigation * update popup * Bump version * Add mandatory requirement for android.software.leanback. * Fix importing files on TVs * fix: add separate method for reading files to fix file reading on Android TV * fix(android): add CHANGE_NETWORK_STATE permission for all Android versions * Fix connection check for AWG/WG * chore: minor fixes (#1235) * fix: add a workaround to open files on Android TV due to lack of SAF * fix: change the banner format for TV * refactor: make TvFilePicker activity more sustainable * fix: add the touch emulation method for Android TV * fix: null uri processing * fix: add the touch emulation method for Android TV * fix: hide UI elements that use file saving * chore: bump version code * add `ScrollBarType` * update initial config page * refactor credentials setup page to handle the focus navigation * add `setDelegateIndex` method to `listViewFocusController` * fix focus behavior on new page/popup * make minor fixes and clean up * fix: get rid of the assign function call * Scrollbar is on if the content is larger than a screen * Fix selection in language change list * Update select language list * update logging settings page * fix checked item in lists * fix split tunneling settings * make unchangable properties readonly * refactor SwitcherType * fix hide/unhide password * `PageShare` readonly properties * Fix list view focus moving on `PageShare` * remove manual focus control on `PageShare` * format `ListViewFocusController` * format `FocusController` * add `focusControl` with utility functions for focus control * refactor `listViewFocusController` acoording to `focusControl` * refactor `focusConroller` according to `focusControl` * add `printSectionName` method to `listViewController` * remove arrow from `Close application` item * fix focus movement in `ServersListView` * `Restore from backup` is visible only on start screen * `I have nothing` is visible only on start screen * fix back button on `SelectLanguageDrawer` * rename `focusControl` to `qmlUtils` * fix `CMakeLists.txt` * fix `ScrollBarType` * fix `PageSetupWizardApiServicesList` * fix focus movement on dynamic delegates in listView * refactor `PageSetupWizardProtocols` * remove comments and clean up * fix `ListViewWithLabelsType` * fix `PageProtocolCloakSettings` * fix `PageSettingsAppSplitTunneling` * fix `PageDevMenu` * remove debug output from `FocusController` * remove debug output from `ListViewFocusController` * remove debug output from `focusControl` * `focusControl` => `FocusControl` --------- Co-authored-by: albexk <albexk@proton.me> Co-authored-by: Nethius <nethiuswork@gmail.com>
149 lines
5.1 KiB
C++
149 lines
5.1 KiB
C++
#include "sitesController.h"
|
|
|
|
#include <QFile>
|
|
#include <QHostInfo>
|
|
#include <QStandardPaths>
|
|
|
|
#include "systemController.h"
|
|
#include "core/networkUtilities.h"
|
|
|
|
SitesController::SitesController(const std::shared_ptr<Settings> &settings,
|
|
const QSharedPointer<VpnConnection> &vpnConnection,
|
|
const QSharedPointer<SitesModel> &sitesModel, QObject *parent)
|
|
: QObject(parent), m_settings(settings), m_vpnConnection(vpnConnection), m_sitesModel(sitesModel)
|
|
{
|
|
}
|
|
|
|
void SitesController::addSite(QString hostname)
|
|
{
|
|
if (hostname.isEmpty()) {
|
|
return;
|
|
}
|
|
|
|
if (!hostname.contains(".")) {
|
|
emit errorOccurred(tr("Hostname not look like ip adress or domain name"));
|
|
return;
|
|
}
|
|
|
|
if (!NetworkUtilities::ipAddressWithSubnetRegExp().exactMatch(hostname)) {
|
|
// get domain name if it present
|
|
hostname.replace("https://", "");
|
|
hostname.replace("http://", "");
|
|
hostname.replace("ftp://", "");
|
|
|
|
hostname = hostname.split("/", Qt::SkipEmptyParts).first();
|
|
}
|
|
|
|
const auto &processSite = [this](const QString &hostname, const QString &ip) {
|
|
m_sitesModel->addSite(hostname, ip);
|
|
|
|
if (!ip.isEmpty()) {
|
|
QMetaObject::invokeMethod(m_vpnConnection.get(), "addRoutes", Qt::QueuedConnection,
|
|
Q_ARG(QStringList, QStringList() << ip));
|
|
} else if (NetworkUtilities::ipAddressWithSubnetRegExp().exactMatch(hostname)) {
|
|
QMetaObject::invokeMethod(m_vpnConnection.get(), "addRoutes", Qt::QueuedConnection,
|
|
Q_ARG(QStringList, QStringList() << hostname));
|
|
}
|
|
QMetaObject::invokeMethod(m_vpnConnection.get(), "flushDns", Qt::QueuedConnection);
|
|
};
|
|
|
|
const auto &resolveCallback = [this, processSite](const QHostInfo &hostInfo) {
|
|
const QList<QHostAddress> &addresses = hostInfo.addresses();
|
|
for (const QHostAddress &addr : hostInfo.addresses()) {
|
|
if (addr.protocol() == QAbstractSocket::NetworkLayerProtocol::IPv4Protocol) {
|
|
processSite(hostInfo.hostName(), addr.toString());
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
if (NetworkUtilities::ipAddressWithSubnetRegExp().exactMatch(hostname)) {
|
|
processSite(hostname, "");
|
|
} else {
|
|
processSite(hostname, "");
|
|
QHostInfo::lookupHost(hostname, this, resolveCallback);
|
|
}
|
|
|
|
emit finished(tr("New site added: %1").arg(hostname));
|
|
}
|
|
|
|
void SitesController::removeSite(int index)
|
|
{
|
|
auto modelIndex = m_sitesModel->index(index);
|
|
auto hostname = m_sitesModel->data(modelIndex, SitesModel::Roles::UrlRole).toString();
|
|
m_sitesModel->removeSite(modelIndex);
|
|
|
|
QMetaObject::invokeMethod(m_vpnConnection.get(), "deleteRoutes", Qt::QueuedConnection,
|
|
Q_ARG(QStringList, QStringList() << hostname));
|
|
QMetaObject::invokeMethod(m_vpnConnection.get(), "flushDns", Qt::QueuedConnection);
|
|
|
|
emit finished(tr("Site removed: %1").arg(hostname));
|
|
}
|
|
|
|
void SitesController::importSites(const QString &fileName, bool replaceExisting)
|
|
{
|
|
QByteArray jsonData;
|
|
if (!SystemController::readFile(fileName, jsonData)) {
|
|
emit errorOccurred(tr("Can't open file: %1").arg(fileName));
|
|
return;
|
|
}
|
|
|
|
QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonData);
|
|
if (jsonDocument.isNull()) {
|
|
emit errorOccurred(tr("Failed to parse JSON data from file: %1").arg(fileName));
|
|
return;
|
|
}
|
|
|
|
if (!jsonDocument.isArray()) {
|
|
emit errorOccurred(tr("The JSON data is not an array in file: %1").arg(fileName));
|
|
return;
|
|
}
|
|
|
|
auto jsonArray = jsonDocument.array();
|
|
QMap<QString, QString> sites;
|
|
QStringList ips;
|
|
|
|
for (auto jsonValue : jsonArray) {
|
|
auto jsonObject = jsonValue.toObject();
|
|
auto hostname = jsonObject.value("hostname").toString("");
|
|
auto ip = jsonObject.value("ip").toString("");
|
|
|
|
if (!hostname.contains(".") && !NetworkUtilities::ipAddressWithSubnetRegExp().exactMatch(hostname)) {
|
|
qDebug() << hostname << " not look like ip adress or domain name";
|
|
continue;
|
|
}
|
|
|
|
if (ip.isEmpty()) {
|
|
ips.append(hostname);
|
|
} else {
|
|
ips.append(ip);
|
|
}
|
|
sites.insert(hostname, ip);
|
|
}
|
|
|
|
m_sitesModel->addSites(sites, replaceExisting);
|
|
|
|
QMetaObject::invokeMethod(m_vpnConnection.get(), "addRoutes", Qt::QueuedConnection, Q_ARG(QStringList, ips));
|
|
QMetaObject::invokeMethod(m_vpnConnection.get(), "flushDns", Qt::QueuedConnection);
|
|
|
|
emit finished(tr("Import completed"));
|
|
}
|
|
|
|
void SitesController::exportSites(const QString &fileName)
|
|
{
|
|
auto sites = m_sitesModel->getCurrentSites();
|
|
|
|
QJsonArray jsonArray;
|
|
|
|
for (const auto &site : sites) {
|
|
QJsonObject jsonObject { { "hostname", site.first }, { "ip", site.second } };
|
|
jsonArray.append(jsonObject);
|
|
}
|
|
|
|
QJsonDocument jsonDocument(jsonArray);
|
|
QByteArray jsonData = jsonDocument.toJson();
|
|
|
|
SystemController::saveFile(fileName, jsonData);
|
|
|
|
emit finished(tr("Export completed"));
|
|
}
|