From c1663278355db5cb508d64b7f5b252653eddf5a8 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Wed, 6 Sep 2023 22:20:59 +0500 Subject: [PATCH] filedialog for qml moved to main.qml --- client/amnezia_application.cpp | 6 + client/amnezia_application.h | 2 + client/ui/controllers/importController.cpp | 7 +- client/ui/controllers/pageController.h | 4 + client/ui/controllers/systemController.cpp | 103 ++++++++++++++++++ client/ui/controllers/systemController.h | 30 +++++ client/ui/qml/Pages2/PageSettingsBackup.qml | 14 +-- client/ui/qml/Pages2/PageSettingsLogging.qml | 2 +- .../qml/Pages2/PageSettingsSplitTunneling.qml | 28 ++--- .../Pages2/PageSetupWizardConfigSource.qml | 21 +--- client/ui/qml/main2.qml | 48 ++++++++ 11 files changed, 213 insertions(+), 52 deletions(-) create mode 100644 client/ui/controllers/systemController.cpp create mode 100644 client/ui/controllers/systemController.h diff --git a/client/amnezia_application.cpp b/client/amnezia_application.cpp index f248c34f..8db6f8de 100644 --- a/client/amnezia_application.cpp +++ b/client/amnezia_application.cpp @@ -10,6 +10,8 @@ #include #include +#include + #include "logger.h" #include "version.h" @@ -130,6 +132,7 @@ void AmneziaApplication::init() &ConnectionController::closeConnection); m_engine->load(url); + m_systemController->setQmlRoot(m_engine->rootObjects().value(0)); if (m_settings->isSaveLogs()) { if (!Logger::init()) { @@ -345,4 +348,7 @@ void AmneziaApplication::initControllers() m_sitesController.reset(new SitesController(m_settings, m_vpnConnection, m_sitesModel)); m_engine->rootContext()->setContextProperty("SitesController", m_sitesController.get()); + + m_systemController.reset(new SystemController(m_settings)); + m_engine->rootContext()->setContextProperty("SystemController", m_systemController.get()); } diff --git a/client/amnezia_application.h b/client/amnezia_application.h index 40ea81b4..1ace6d8b 100644 --- a/client/amnezia_application.h +++ b/client/amnezia_application.h @@ -23,6 +23,7 @@ #include "ui/controllers/pageController.h" #include "ui/controllers/settingsController.h" #include "ui/controllers/sitesController.h" +#include "ui/controllers/systemController.h" #include "ui/models/containers_model.h" #include "ui/models/languageModel.h" #include "ui/models/protocols/cloakConfigModel.h" @@ -114,6 +115,7 @@ private: QScopedPointer m_exportController; QScopedPointer m_settingsController; QScopedPointer m_sitesController; + QScopedPointer m_systemController; }; #endif // AMNEZIA_APPLICATION_H diff --git a/client/ui/controllers/importController.cpp b/client/ui/controllers/importController.cpp index b76302c5..c0aaeeb9 100644 --- a/client/ui/controllers/importController.cpp +++ b/client/ui/controllers/importController.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include "core/errorstrings.h" @@ -87,7 +88,11 @@ ImportController::ImportController(const QSharedPointer &serversMo void ImportController::extractConfigFromFile(const QString &fileName) { - QFile file(FileUtilites::getFileName(fileName)); + QQuickItem *obj = findChild("saveFileDialog"); + + QUrl url(fileName); + QString path = url.toLocalFile(); + QFile file(path); if (file.open(QIODevice::ReadOnly)) { QString data = file.readAll(); diff --git a/client/ui/controllers/pageController.h b/client/ui/controllers/pageController.h index 8d3da507..952f716c 100644 --- a/client/ui/controllers/pageController.h +++ b/client/ui/controllers/pageController.h @@ -103,6 +103,10 @@ signals: void showPassphraseRequestDrawer(); void passphraseRequestDrawerClosed(QString passphrase); + void setupFileDialogForConfig(); + void setupFileDialogForSites(bool replaceExistingSites); + void setupFileDialogForBackup(); + private: QSharedPointer m_serversModel; diff --git a/client/ui/controllers/systemController.cpp b/client/ui/controllers/systemController.cpp new file mode 100644 index 00000000..a843b660 --- /dev/null +++ b/client/ui/controllers/systemController.cpp @@ -0,0 +1,103 @@ +#include "systemController.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef Q_OS_ANDROID + #include "platforms/android/android_controller.h" +#endif + +#ifdef Q_OS_IOS + #include "platforms/ios/MobileUtils.h" + #include +#endif + +SystemController::SystemController(const std::shared_ptr &settings, QObject *parent) + : QObject(parent), m_settings(settings) +{ +} + +void SystemController::saveFile(QString fileName, const QString &data) +{ +#if defined Q_OS_ANDROID + AndroidController::instance()->shareConfig(data, fileName); + return; +#endif + +#ifdef Q_OS_IOS + QUrl fileUrl = QDir::tempPath() + "/" + fileName; + QFile file(fileUrl.toString()); +#else + QUrl fileUrl = QUrl(fileName); + QFile file(fileUrl.toLocalFile()); +#endif + + // todo check if save successful + file.open(QIODevice::WriteOnly); + file.write(data.toUtf8()); + file.close(); + +#ifdef Q_OS_IOS + QStringList filesToSend; + filesToSend.append(fileUrl.toString()); + MobileUtils::shareText(filesToSend); + return; +#else + QFileInfo fi(fileUrl.toLocalFile()); + QDesktopServices::openUrl(fi.absoluteDir().absolutePath()); +#endif +} + +QString SystemController::getFileName() +{ + auto mainFileDialog = m_qmlRoot->findChild("mainFileDialog").parent(); + if (!mainFileDialog) { + return ""; + } + QMetaObject::invokeMethod(mainFileDialog, "open", Qt::DirectConnection); + + QEventLoop wait; + QObject::connect(this, &SystemController::fileDialogAccepted, &wait, &QEventLoop::quit); + wait.exec(); + + auto fileName = mainFileDialog->property("selectedFile").toString(); + +#ifdef Q_OS_IOS + CFURLRef url = CFURLCreateWithFileSystemPath( + kCFAllocatorDefault, + CFStringCreateWithCharacters(0, reinterpret_cast(fileName.unicode()), fileName.length()), + kCFURLPOSIXPathStyle, 0); + + if (!CFURLStartAccessingSecurityScopedResource(url)) { + qDebug() << "Could not access path " << QUrl::fromLocalFile(fileName).toString(); + } + + return fileName; +#endif + +#ifdef Q_OS_ANDROID + // patch for files containing spaces etc + const QString sep { "raw%3A%2F" }; + if (fileName.startsWith("content://") && fileName.contains(sep)) { + QString contentUrl = fileName.split(sep).at(0); + QString rawUrl = fileName.split(sep).at(1); + rawUrl.replace(" ", "%20"); + fileName = contentUrl + sep + rawUrl; + } + + return fileName; +#endif + + return QUrl(fileName).toLocalFile(); +} + +void SystemController::setQmlRoot(QObject *qmlRoot) +{ + m_qmlRoot = qmlRoot; +} diff --git a/client/ui/controllers/systemController.h b/client/ui/controllers/systemController.h new file mode 100644 index 00000000..fbcc52f1 --- /dev/null +++ b/client/ui/controllers/systemController.h @@ -0,0 +1,30 @@ +#ifndef SYSTEMCONTROLLER_H +#define SYSTEMCONTROLLER_H + +#include + +#include "settings.h" + +class SystemController : public QObject +{ + Q_OBJECT +public: + explicit SystemController(const std::shared_ptr &setting, QObject *parent = nullptr); + +public slots: + void saveFile(QString fileName, const QString &data); + QString getFileName(); + + void setQmlRoot(QObject *qmlRoot); + +signals: + void fileDialogAccepted(); + void fileDialogRejected(); + +private: + std::shared_ptr m_settings; + + QObject *m_qmlRoot; +}; + +#endif // SYSTEMCONTROLLER_H diff --git a/client/ui/qml/Pages2/PageSettingsBackup.qml b/client/ui/qml/Pages2/PageSettingsBackup.qml index 363bc66f..edd527c1 100644 --- a/client/ui/qml/Pages2/PageSettingsBackup.qml +++ b/client/ui/qml/Pages2/PageSettingsBackup.qml @@ -125,18 +125,8 @@ PageType { text: qsTr("Restore from backup") onClicked: { - openFileDialog.open() - } - - FileDialog { - id: openFileDialog - acceptLabel: qsTr("Open backup file") - nameFilters: [ "Backup files (*.backup)" ] - onAccepted: { - PageController.showBusyIndicator(true) - SettingsController.restoreAppConfig(openFileDialog.selectedFile.toString()) - PageController.showBusyIndicator(false) - } + PageController.setupFileDialogForBackup() + SystemController.getFileName() } } } diff --git a/client/ui/qml/Pages2/PageSettingsLogging.qml b/client/ui/qml/Pages2/PageSettingsLogging.qml index 0e4e486e..c0a35c0f 100644 --- a/client/ui/qml/Pages2/PageSettingsLogging.qml +++ b/client/ui/qml/Pages2/PageSettingsLogging.qml @@ -117,7 +117,7 @@ PageType { currentFile: StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/AmneziaVPN" defaultSuffix: ".log" onAccepted: { - ExportController.saveFile(fileDialog.currentFile.toString()) + SettingsController.exportLogsFile(fileDialog.currentFile.toString()) } } } diff --git a/client/ui/qml/Pages2/PageSettingsSplitTunneling.qml b/client/ui/qml/Pages2/PageSettingsSplitTunneling.qml index 898ce17b..155ecc3c 100644 --- a/client/ui/qml/Pages2/PageSettingsSplitTunneling.qml +++ b/client/ui/qml/Pages2/PageSettingsSplitTunneling.qml @@ -44,8 +44,6 @@ PageType { allExceptSites ] - property bool replaceExistingSites - QtObject { id: onlyForwardSites property string name: qsTr("Only the addresses in the list must be opened via VPN") @@ -303,7 +301,7 @@ PageType { clickedFunction: function() { if (Qt.platform.os === "ios") { - ExportController.saveFile("amezia_tunnel.json") + SitesController.exportSites("amezia_tunnel.json") } else { saveFileDialog.open() } @@ -311,6 +309,7 @@ PageType { FileDialog { id: saveFileDialog + objectName: saveFileDialog acceptLabel: qsTr("Save sites") nameFilters: [ "Sites files (*.json)" ] fileMode: FileDialog.SaveFile @@ -378,8 +377,8 @@ PageType { text: qsTr("Replace site list") clickedFunction: function() { - root.replaceExistingSites = true - openFileDialog.open() + PageController.setupFileDialogForSites(true) + SystemController.getFileName() } } @@ -390,25 +389,14 @@ PageType { text: qsTr("Add imported sites to existing ones") clickedFunction: function() { - root.replaceExistingSites = false - openFileDialog.open() + PageController.setupFileDialogForSites(false) + SystemController.getFileName() + importSitesDrawer.close() + moreActionsDrawer.close() } } DividerType {} - - FileDialog { - id: openFileDialog - acceptLabel: qsTr("Open sites file") - nameFilters: [ "Sites files (*.json)" ] - onAccepted: { - PageController.showBusyIndicator(true) - SitesController.importSites(openFileDialog.selectedFile.toString(), replaceExistingSites) - importSitesDrawer.close() - moreActionsDrawer.close() - PageController.showBusyIndicator(false) - } - } } } } diff --git a/client/ui/qml/Pages2/PageSetupWizardConfigSource.qml b/client/ui/qml/Pages2/PageSetupWizardConfigSource.qml index c0ad6249..3f460f65 100644 --- a/client/ui/qml/Pages2/PageSetupWizardConfigSource.qml +++ b/client/ui/qml/Pages2/PageSetupWizardConfigSource.qml @@ -65,28 +65,13 @@ It's okay as long as it's from someone you trust.") Layout.fillWidth: true Layout.topMargin: 16 - text: qsTr("File with connection settings or backup") + text: !ServersModel.getServersCount() ? qsTr("File with connection settings or backup") : qsTr("File with connection settings") rightImageSource: "qrc:/images/controls/chevron-right.svg" leftImageSource: "qrc:/images/controls/folder-open.svg" clickedFunction: function() { - fileDialog.open() - } - - FileDialog { - id: fileDialog - acceptLabel: qsTr("Open config file") - nameFilters: [ "Config or backup files (*.vpn *.ovpn *.conf *.backup)" ] - onAccepted: { - if (fileDialog.selectedFile.toString().indexOf(".backup") != -1) { - PageController.showBusyIndicator(true) - SettingsController.restoreAppConfig(fileDialog.selectedFile.toString()) - PageController.showBusyIndicator(false) - } else { - ImportController.extractConfigFromFile(fileDialog.selectedFile.toString()) - PageController.goToPage(PageEnum.PageSetupWizardViewConfig) - } - } + PageController.setupFileDialogForConfig() + SystemController.getFileName() } } diff --git a/client/ui/qml/main2.qml b/client/ui/qml/main2.qml index e78f35a2..e09882c0 100644 --- a/client/ui/qml/main2.qml +++ b/client/ui/qml/main2.qml @@ -2,6 +2,7 @@ import QtQuick import QtQuick.Window import QtQuick.Controls import QtQuick.Layouts +import QtQuick.Dialogs import PageEnum 1.0 @@ -10,6 +11,7 @@ import "Controls2" Window { id: root + objectName: "mainWindow" visible: true width: GC.screenWidth height: GC.screenHeight @@ -79,6 +81,42 @@ Window { function onShowPassphraseRequestDrawer() { privateKeyPassphraseDrawer.open() } + + function onSetupFileDialogForConfig() { + mainFileDialog.acceptLabel = qsTr("Open config file") + mainFileDialog.nameFilters = !ServersModel.getServersCount() ? [ "Config or backup files (*.vpn *.ovpn *.conf *.backup)" ] : + [ "Config files (*.vpn *.ovpn *.conf)" ] + mainFileDialog.acceptFunction = function() { + if (mainFileDialog.selectedFile.toString().indexOf(".backup") !== -1 && !ServersModel.getServersCount()) { + PageController.showBusyIndicator(true) + SettingsController.restoreAppConfig(mainFileDialog.selectedFile.toString()) + PageController.showBusyIndicator(false) + } else { + ImportController.extractConfigFromFile(mainFileDialog.selectedFile) + PageController.goToPage(PageEnum.PageSetupWizardViewConfig) + } + } + } + + function onSetupFileDialogForSites(replaceExistingSites) { + mainFileDialog.acceptLabel = qsTr("Open sites file") + mainFileDialog.nameFilters = [ "Sites files (*.json)" ] + mainFileDialog.acceptFunction = function() { + PageController.showBusyIndicator(true) + SitesController.importSites(mainFileDialog.selectedFile.toString(), replaceExistingSites) + PageController.showBusyIndicator(false) + } + } + + function onSetupFileDialogForBackup() { + mainFileDialog.acceptLabel = qsTr("Open backup file") + mainFileDialog.nameFilters = [ "Backup files (*.backup)" ] + mainFileDialog.acceptFunction = function() { + PageController.showBusyIndicator(true) + SettingsController.restoreAppConfig(mainFileDialog.selectedFile.toString()) + PageController.showBusyIndicator(false) + } + } } Connections { @@ -192,4 +230,14 @@ Window { } } } + + FileDialog { + id: mainFileDialog + + property var acceptFunction + + objectName: "mainFileDialog" + + onAccepted: acceptFunction() + } }