From bd6b1165d7dad3677544b1332b8adfbd001ac97a Mon Sep 17 00:00:00 2001 From: Nodir Temirkhodjaev Date: Mon, 25 Dec 2023 08:11:31 +0300 Subject: [PATCH] UI: Options: Add Backup Export/Import --- src/ui/3rdparty/sqlite/sqlitedb.cpp | 20 +++++--- src/ui/3rdparty/sqlite/sqlitedb.h | 3 ++ src/ui/FortFirewallUI.pro | 2 + src/ui/conf/confappmanager.cpp | 3 ++ src/ui/conf/confappmanager.h | 16 +++++++ src/ui/conf/confmanager.cpp | 65 ++++++++++++++++++++++---- src/ui/conf/confmanager.h | 3 ++ src/ui/control/control.cpp | 6 +++ src/ui/control/control.h | 2 + src/ui/form/dialog/dialogutil.cpp | 5 ++ src/ui/form/dialog/dialogutil.h | 1 + src/ui/form/opt/optionscontroller.cpp | 28 +++++++++++ src/ui/form/opt/optionscontroller.h | 3 ++ src/ui/form/opt/pages/optmainpage.cpp | 26 +++++++++-- src/ui/form/opt/pages/optmainpage.h | 4 ++ src/ui/fort_icons.qrc | 1 + src/ui/icons/disk.png | Bin 0 -> 1385 bytes src/ui/rpc/confmanagerrpc.cpp | 10 ++++ src/ui/rpc/confmanagerrpc.h | 3 ++ src/ui/rpc/rpcmanager.cpp | 14 ++++++ src/ui/util/ini/settings.h | 2 + 21 files changed, 198 insertions(+), 19 deletions(-) create mode 100644 src/ui/conf/confappmanager.cpp create mode 100644 src/ui/conf/confappmanager.h create mode 100644 src/ui/icons/disk.png diff --git a/src/ui/3rdparty/sqlite/sqlitedb.cpp b/src/ui/3rdparty/sqlite/sqlitedb.cpp index 6dd695e8..5f8d5608 100644 --- a/src/ui/3rdparty/sqlite/sqlitedb.cpp +++ b/src/ui/3rdparty/sqlite/sqlitedb.cpp @@ -91,16 +91,12 @@ void SqliteDb::close() bool SqliteDb::attach(const QString &schemaName, const QString &filePath) { - bool ok = false; - executeEx("ATTACH DATABASE ?1 AS ?2;", { filePath, schemaName }, 0, &ok); - return ok; + return executeExOk("ATTACH DATABASE ?1 AS ?2;", { filePath, schemaName }); } bool SqliteDb::detach(const QString &schemaName) { - bool ok = false; - executeEx("DETACH DATABASE ?1;", { schemaName }, 0, &ok); - return ok; + return executeExOk("DETACH DATABASE ?1;", { schemaName }); } bool SqliteDb::vacuum() @@ -108,6 +104,11 @@ bool SqliteDb::vacuum() return execute("VACUUM;"); } +bool SqliteDb::vacuumInto(const QString &filePath) +{ + return executeExOk("VACUUM INTO ?1;", { filePath }); +} + bool SqliteDb::execute(const char *sql) { return sqlite3_exec(m_db, sql, nullptr, nullptr, nullptr) == SQLITE_OK; @@ -148,6 +149,13 @@ QVariant SqliteDb::executeEx(const char *sql, const QVariantList &vars, int resu return (listSize == 0) ? QVariant() : (listSize == 1 ? list.at(0) : list); } +bool SqliteDb::executeExOk(const char *sql, const QVariantList &vars) +{ + bool ok = false; + executeEx(sql, vars, 0, &ok); + return ok; +} + bool SqliteDb::prepare(SqliteStmt &stmt, const char *sql, const QVariantList &vars) { if (!stmt.prepare(db(), sql)) diff --git a/src/ui/3rdparty/sqlite/sqlitedb.h b/src/ui/3rdparty/sqlite/sqlitedb.h index fabc4c0a..a5841a93 100644 --- a/src/ui/3rdparty/sqlite/sqlitedb.h +++ b/src/ui/3rdparty/sqlite/sqlitedb.h @@ -73,6 +73,7 @@ public: bool detach(const QString &schemaName); bool vacuum(); + bool vacuumInto(const QString &filePath); bool execute(const char *sql); bool executeStr(const QString &sql); @@ -80,6 +81,8 @@ public: QVariant executeEx(const char *sql, const QVariantList &vars = {}, int resultCount = 1, bool *ok = nullptr); + bool executeExOk(const char *sql, const QVariantList &vars = {}); + bool prepare(SqliteStmt &stmt, const char *sql, const QVariantList &vars = {}); bool prepare(SqliteStmt &stmt, const QString &sql, const QVariantList &vars = {}); bool done(SqliteStmt *stmt); diff --git a/src/ui/FortFirewallUI.pro b/src/ui/FortFirewallUI.pro index fe64dcbb..f52b9329 100644 --- a/src/ui/FortFirewallUI.pro +++ b/src/ui/FortFirewallUI.pro @@ -20,6 +20,7 @@ SOURCES += \ conf/addressgroup.cpp \ conf/app.cpp \ conf/appgroup.cpp \ + conf/confappmanager.cpp \ conf/confmanager.cpp \ conf/firewallconf.cpp \ conf/inioptions.cpp \ @@ -216,6 +217,7 @@ HEADERS += \ conf/addressgroup.h \ conf/app.h \ conf/appgroup.h \ + conf/confappmanager.h \ conf/confmanager.h \ conf/firewallconf.h \ conf/inioptions.h \ diff --git a/src/ui/conf/confappmanager.cpp b/src/ui/conf/confappmanager.cpp new file mode 100644 index 00000000..6e2e068f --- /dev/null +++ b/src/ui/conf/confappmanager.cpp @@ -0,0 +1,3 @@ +#include "confappmanager.h" + +ConfAppManager::ConfAppManager(QObject *parent) : QObject { parent } { } diff --git a/src/ui/conf/confappmanager.h b/src/ui/conf/confappmanager.h new file mode 100644 index 00000000..bedccef4 --- /dev/null +++ b/src/ui/conf/confappmanager.h @@ -0,0 +1,16 @@ +#ifndef CONFAPPMANAGER_H +#define CONFAPPMANAGER_H + +#include + +class ConfAppManager : public QObject +{ + Q_OBJECT + +public: + explicit ConfAppManager(QObject *parent = nullptr); + +signals: +}; + +#endif // CONFAPPMANAGER_H diff --git a/src/ui/conf/confmanager.cpp b/src/ui/conf/confmanager.cpp index 11b64423..95e9ea86 100644 --- a/src/ui/conf/confmanager.cpp +++ b/src/ui/conf/confmanager.cpp @@ -376,9 +376,7 @@ bool saveAddressGroup(SqliteDb *db, AddressGroup *addrGroup, int orderIndex) const char *sql = rowExists ? sqlUpdateAddressGroup : sqlInsertAddressGroup; - bool ok; - db->executeEx(sql, vars, 0, &ok); - if (!ok) + if (!db->executeExOk(sql, vars)) return false; if (!rowExists) { @@ -456,9 +454,7 @@ bool saveAppGroup(SqliteDb *db, AppGroup *appGroup, int orderIndex) const char *sql = rowExists ? sqlUpdateAppGroup : sqlInsertAppGroup; - bool ok; - db->executeEx(sql, vars, 0, &ok); - if (!ok) + if (!db->executeExOk(sql, vars)) return false; if (!rowExists) { @@ -485,12 +481,9 @@ bool removeAppGroupsInDb(SqliteDb *db, const FirewallConf &conf) const auto defaultAppGroupId = conf.appGroups().at(0)->id(); for (const qint64 appGroupId : conf.removedAppGroupIdList()) { - bool ok; - db->executeEx(sqlUpdateAppResetGroup, { appGroupId, defaultAppGroupId }, 0); - db->executeEx(sqlDeleteAppGroup, { appGroupId }, 0, &ok); - if (!ok) + if (!db->executeExOk(sqlDeleteAppGroup, { appGroupId })) return false; } @@ -863,6 +856,58 @@ bool ConfManager::saveTasks(const QList &taskInfos) return commitTransaction(ok); } +bool ConfManager::exportBackup(const QString &path) +{ + FileUtil::makePath(path); + + const QString outPath = FileUtil::pathSlash(path); + + // Export Db + { + const QString fileName = FileUtil::fileName(sqliteDb()->filePath()); + const QString destPath = outPath + fileName; + + FileUtil::removeFile(destPath); + if (!sqliteDb()->vacuumInto(destPath)) { + qCWarning(LC) << "Export Db error:" << sqliteDb()->errorMessage() << "to:" << destPath; + return false; + } + } + + // Export Ini + { + const QString iniPath = conf()->ini().settings()->filePath(); + const QString fileName = FileUtil::fileName(iniPath); + const QString destPath = outPath + fileName; + + FileUtil::removeFile(destPath); + if (!FileUtil::copyFile(iniPath, outPath + fileName)) { + qCWarning(LC) << "Copy Ini error from:" << iniPath << "to:" << destPath; + return false; + } + } + + // Export User Ini + { + const QString iniPath = iniUser().settings()->filePath(); + const QString fileName = FileUtil::fileName(iniPath); + const QString destPath = outPath + fileName; + + FileUtil::removeFile(destPath); + if (!FileUtil::copyFile(iniPath, outPath + fileName)) { + qCWarning(LC) << "Copy User Ini error from:" << iniPath << "to:" << destPath; + return false; + } + } + + return true; +} + +bool ConfManager::importBackup(const QString &path) +{ + return true; +} + void ConfManager::logBlockedApp(const LogEntryBlocked &logEntry) { const QString appOriginPath = logEntry.path(); diff --git a/src/ui/conf/confmanager.h b/src/ui/conf/confmanager.h index a3db7c54..24b28730 100644 --- a/src/ui/conf/confmanager.h +++ b/src/ui/conf/confmanager.h @@ -61,6 +61,9 @@ public: bool loadTasks(const QList &taskInfos); bool saveTasks(const QList &taskInfos); + virtual bool exportBackup(const QString &path); + virtual bool importBackup(const QString &path); + void logBlockedApp(const LogEntryBlocked &logEntry); qint64 appIdByPath(const QString &appPath); diff --git a/src/ui/control/control.cpp b/src/ui/control/control.cpp index c41e0ff9..69bde209 100644 --- a/src/ui/control/control.cpp +++ b/src/ui/control/control.cpp @@ -21,6 +21,8 @@ const char *const commandString(Command cmd) CASE_STRING(Rpc_AppInfoManager_checkLookupInfoFinished) CASE_STRING(Rpc_ConfManager_saveVariant) + CASE_STRING(Rpc_ConfManager_exportBackup) + CASE_STRING(Rpc_ConfManager_importBackup) CASE_STRING(Rpc_ConfManager_addApp) CASE_STRING(Rpc_ConfManager_deleteApps) CASE_STRING(Rpc_ConfManager_purgeApps) @@ -105,6 +107,8 @@ RpcManager managerByCommand(Command cmd) Rpc_AppInfoManager, // Rpc_AppInfoManager_checkLookupFinished, Rpc_ConfManager, // Rpc_ConfManager_saveVariant, + Rpc_ConfManager, // Rpc_ConfManager_exportBackup, + Rpc_ConfManager, // Rpc_ConfManager_importBackup, Rpc_ConfManager, // Rpc_ConfManager_addApp, Rpc_ConfManager, // Rpc_ConfManager_deleteApps, Rpc_ConfManager, // Rpc_ConfManager_purgeApps, @@ -172,6 +176,8 @@ bool commandRequiresValidation(Command cmd) 0, // Rpc_AppInfoManager_checkLookupFinished, true, // Rpc_ConfManager_saveVariant, + true, // Rpc_ConfManager_exportBackup, + true, // Rpc_ConfManager_importBackup, true, // Rpc_ConfManager_addApp, true, // Rpc_ConfManager_deleteApps, true, // Rpc_ConfManager_purgeApps, diff --git a/src/ui/control/control.h b/src/ui/control/control.h index 4215e8f5..9a8e36b6 100644 --- a/src/ui/control/control.h +++ b/src/ui/control/control.h @@ -20,6 +20,8 @@ enum Command : qint8 { Rpc_AppInfoManager_checkLookupInfoFinished, Rpc_ConfManager_saveVariant, + Rpc_ConfManager_exportBackup, + Rpc_ConfManager_importBackup, Rpc_ConfManager_addApp, Rpc_ConfManager_deleteApps, Rpc_ConfManager_purgeApps, diff --git a/src/ui/form/dialog/dialogutil.cpp b/src/ui/form/dialog/dialogutil.cpp index cf207e12..aa656db2 100644 --- a/src/ui/form/dialog/dialogutil.cpp +++ b/src/ui/form/dialog/dialogutil.cpp @@ -21,6 +21,11 @@ QString DialogUtil::getSaveFileName(const QString &title, const QString &filter) nullptr, title, QString(), filter, nullptr, QFileDialog::ReadOnly); } +QString DialogUtil::getExistingDir(const QString &title) +{ + return QFileDialog::getExistingDirectory(nullptr, title); +} + QColor DialogUtil::getColor(const QColor &initial, const QString &title) { return QColorDialog::getColor(initial, nullptr, title); diff --git a/src/ui/form/dialog/dialogutil.h b/src/ui/form/dialog/dialogutil.h index e0358464..751ff979 100644 --- a/src/ui/form/dialog/dialogutil.h +++ b/src/ui/form/dialog/dialogutil.h @@ -13,6 +13,7 @@ public: const QString &title = QString(), const QString &filter = QString()); static QString getSaveFileName( const QString &title = QString(), const QString &filter = QString()); + static QString getExistingDir(const QString &title = QString()); static QColor getColor(const QColor &initial = Qt::white, const QString &title = QString()); }; diff --git a/src/ui/form/opt/optionscontroller.cpp b/src/ui/form/opt/optionscontroller.cpp index d59a5147..5c5a4724 100644 --- a/src/ui/form/opt/optionscontroller.cpp +++ b/src/ui/form/opt/optionscontroller.cpp @@ -4,10 +4,12 @@ #include #include +#include
#include #include #include #include +#include #include namespace { @@ -154,6 +156,32 @@ void OptionsController::initConfManagerToEdit() confManager()->initIniUserToEdit(); } +void OptionsController::exportBackup() +{ + const auto path = DialogUtil::getExistingDir(tr("Export Options")); + if (path.isEmpty()) + return; + + if (confManager()->exportBackup(path)) { + windowManager()->showInfoDialog(tr("Options Exported Successfully")); + } else { + windowManager()->showErrorBox(tr("Cannot Export Options")); + } +} + +void OptionsController::importBackup() +{ + const auto path = DialogUtil::getExistingDir(tr("Import Options")); + if (path.isEmpty()) + return; + + if (confManager()->importBackup(path)) { + windowManager()->showInfoDialog(tr("Options Imported Successfully")); + } else { + windowManager()->showErrorBox(tr("Cannot Import Options")); + } +} + void OptionsController::closeWindow() { windowManager()->closeOptionsWindow(); diff --git a/src/ui/form/opt/optionscontroller.h b/src/ui/form/opt/optionscontroller.h index 224c5fff..975ac8ed 100644 --- a/src/ui/form/opt/optionscontroller.h +++ b/src/ui/form/opt/optionscontroller.h @@ -46,6 +46,9 @@ public slots: void saveChanges() { save(/*closeOnSuccess=*/true); } void applyChanges() { save(/*closeOnSuccess=*/false); } + void exportBackup(); + void importBackup(); + void closeWindow(); private: diff --git a/src/ui/form/opt/pages/optmainpage.cpp b/src/ui/form/opt/pages/optmainpage.cpp index 357e979e..f51e8fc4 100644 --- a/src/ui/form/opt/pages/optmainpage.cpp +++ b/src/ui/form/opt/pages/optmainpage.cpp @@ -1,6 +1,7 @@ #include "optmainpage.h" #include +#include #include #include #include @@ -41,6 +42,10 @@ void OptMainPage::onRetranslateUi() m_tabWidget->setTabText(4, tr("Traffic Graph")); m_tabWidget->setTabText(5, tr("Schedule")); + m_btBackup->setText(tr("Backup")); + m_actExport->setText(tr("Export")); + m_actImport->setText(tr("Import")); + m_btOk->setText(tr("OK")); m_btApply->setText(tr("Apply")); m_btCancel->setText(tr("Cancel")); @@ -95,9 +100,7 @@ void OptMainPage::setupTabBar() QLayout *OptMainPage::setupDialogButtons() { - auto layout = new QHBoxLayout(); - - layout->addStretch(); + setupBackup(); m_btOk = new QPushButton(); m_btApply = new QPushButton(); @@ -109,6 +112,9 @@ QLayout *OptMainPage::setupDialogButtons() setupApplyCancelButtons(); + auto layout = new QHBoxLayout(); + layout->addWidget(m_btBackup); + layout->addStretch(); layout->addWidget(m_btOk); layout->addWidget(m_btApply); layout->addWidget(m_btCancel); @@ -116,6 +122,20 @@ QLayout *OptMainPage::setupDialogButtons() return layout; } +void OptMainPage::setupBackup() +{ + auto backupMenu = ControlUtil::createMenu(this); + + m_actExport = backupMenu->addAction(IconCache::icon(":/icons/disk.png"), QString()); + m_actImport = backupMenu->addAction(IconCache::icon(":/icons/folder.png"), QString()); + + connect(m_actExport, &QAction::triggered, ctrl(), &OptionsController::exportBackup); + connect(m_actImport, &QAction::triggered, ctrl(), &OptionsController::importBackup); + + m_btBackup = new QPushButton(); + m_btBackup->setMenu(backupMenu); +} + void OptMainPage::setupApplyCancelButtons() { const auto refreshButtons = [&](bool anyEdited) { diff --git a/src/ui/form/opt/pages/optmainpage.h b/src/ui/form/opt/pages/optmainpage.h index e6b7b6f3..6ffd72c7 100644 --- a/src/ui/form/opt/pages/optmainpage.h +++ b/src/ui/form/opt/pages/optmainpage.h @@ -21,6 +21,7 @@ private: void setupUi(); void setupTabBar(); QLayout *setupDialogButtons(); + void setupBackup(); void setupApplyCancelButtons(); private: @@ -28,6 +29,9 @@ private: QPushButton *m_btMenu = nullptr; + QPushButton *m_btBackup = nullptr; + QAction *m_actExport = nullptr; + QAction *m_actImport = nullptr; QPushButton *m_btOk = nullptr; QPushButton *m_btApply = nullptr; QPushButton *m_btCancel = nullptr; diff --git a/src/ui/fort_icons.qrc b/src/ui/fort_icons.qrc index a5303d7c..fa4d0a1c 100644 --- a/src/ui/fort_icons.qrc +++ b/src/ui/fort_icons.qrc @@ -22,6 +22,7 @@ icons/cross.png icons/delete.png icons/deny.png + icons/disk.png icons/download_for_windows.png icons/error.png icons/folder.png diff --git a/src/ui/icons/disk.png b/src/ui/icons/disk.png new file mode 100644 index 0000000000000000000000000000000000000000..be56dc73e22ec2c550aca8c1a51884a8f472fbb1 GIT binary patch literal 1385 zcmV-v1(y1WP)K;U)LL3PrNw0 z*E>DL`& zvWjo~tgL)CwWnN_9AmEJ9CN2eL;%c95=e+q3ucSaizk7bQyktEfQZi?v%tWEFJmy?)JvGFE1`?wlRFRI00Wu^Z878Mo z7(sYUNO}O^r6Adc83|B;pcu&+A~j%20&5Mbi~IuZ{vak}YP8lkG3Z=%>TQCIa)I_e5WyG(3=LZ0Y$W(dtJKl=~Js^|L-utr`K_WWP0}wS02n(gg z=4Zf#BdUYD@CL1uP(T2^0Ze*{4#B>C&qEB=Et74q`571*RDlZ?96t54zjF60&;JMC zg5*f9YG6TXFf{=nZ-HR38qfIhR-XLD_>T-!Q*uc{0gcTJbf|e{K;#&RfKL2-1`rZy zBmnEFv5A3z>cRvfe`nN#p^F~zFYaDcntAy*QI+~}gv0VyjH zku?#>%2$s$L)KF z2&8>C0s)c2xCseFYD_l}1l5E{w>b^~FV5CY#S}Eg-=#)~ie71=JX+Hx>jp+vHR14ThfF#LpJ>=?c zL^s?WiR=-bgF?xXWdexQ*klA`0+0#hIMRR_2Dp1xC@3X+`HbK|1Rzl-2>>Esx&bg| zia`V|f|_xOno)q|u7!+@UXVs2bbxqDA@V!m!Z)t)lo6=6ou&ANmS-U%69DS~%+!K_ z)&_?4_2jYW7%)=`5gY)6#Nupaxf+)GVyr>z+4fl=U}9kX4^O!FJ)RpM{8V^Z1u}s> z>z$)6d=2)DIzL3LT==4={_U?j)P@n;FMj>&edXIfJY{H|;NS-SFk`&v6F+2m#>fPK z*!9ORZh7v}X8?Z#5F{#aap1DRG9V7bUx96qs{>2GDlp4Gj{(>L{0?#*!~_*s1ZFrm rMx=O>2=cu-!1?D9x$_Cn1&_Z2FviJi@?|BR00000NkvXXu0mjfSXh7$ literal 0 HcmV?d00001 diff --git a/src/ui/rpc/confmanagerrpc.cpp b/src/ui/rpc/confmanagerrpc.cpp index 6162e3ff..90ce23c4 100644 --- a/src/ui/rpc/confmanagerrpc.cpp +++ b/src/ui/rpc/confmanagerrpc.cpp @@ -16,6 +16,16 @@ ConfManagerRpc::ConfManagerRpc(const QString &filePath, QObject *parent) : { } +bool ConfManagerRpc::exportBackup(const QString &path) +{ + return IoC()->doOnServer(Control::Rpc_ConfManager_exportBackup, { path }); +} + +bool ConfManagerRpc::importBackup(const QString &path) +{ + return IoC()->doOnServer(Control::Rpc_ConfManager_importBackup, { path }); +} + bool ConfManagerRpc::addApp(const App &app) { return IoC()->doOnServer(Control::Rpc_ConfManager_addApp, appToVarList(app)); diff --git a/src/ui/rpc/confmanagerrpc.h b/src/ui/rpc/confmanagerrpc.h index 62f22507..29a3fe67 100644 --- a/src/ui/rpc/confmanagerrpc.h +++ b/src/ui/rpc/confmanagerrpc.h @@ -13,6 +13,9 @@ class ConfManagerRpc : public ConfManager public: explicit ConfManagerRpc(const QString &filePath, QObject *parent = nullptr); + bool exportBackup(const QString &path) override; + bool importBackup(const QString &path) override; + bool addApp(const App &app) override; void deleteApps(const QVector &appIdList) override; bool purgeApps() override; diff --git a/src/ui/rpc/rpcmanager.cpp b/src/ui/rpc/rpcmanager.cpp index d69bd147..5959754a 100644 --- a/src/ui/rpc/rpcmanager.cpp +++ b/src/ui/rpc/rpcmanager.cpp @@ -74,6 +74,18 @@ bool processConfManager_addApp( return confManager->addApp(ConfManagerRpc::varListToApp(p.args)); } +bool processConfManager_exportBackup( + ConfManager *confManager, const ProcessCommandArgs &p, QVariantList & /*resArgs*/) +{ + return confManager->exportBackup(p.args.value(0).toString()); +} + +bool processConfManager_importBackup( + ConfManager *confManager, const ProcessCommandArgs &p, QVariantList & /*resArgs*/) +{ + return confManager->importBackup(p.args.value(0).toString()); +} + bool processConfManager_deleteApps( ConfManager *confManager, const ProcessCommandArgs &p, QVariantList & /*resArgs*/) { @@ -174,6 +186,8 @@ using processConfManager_func = bool (*)( static processConfManager_func processConfManager_funcList[] = { &processConfManager_saveVariant, // Rpc_ConfManager_saveVariant, + &processConfManager_exportBackup, // Rpc_ConfManager_exportBackup, + &processConfManager_importBackup, // Rpc_ConfManager_importBackup, &processConfManager_addApp, // Rpc_ConfManager_addApp, &processConfManager_deleteApps, // Rpc_ConfManager_deleteApps, &processConfManager_purgeApps, // Rpc_ConfManager_purgeApps, diff --git a/src/ui/util/ini/settings.h b/src/ui/util/ini/settings.h index 100c3b41..f491bf51 100644 --- a/src/ui/util/ini/settings.h +++ b/src/ui/util/ini/settings.h @@ -16,6 +16,8 @@ public: bool hasError() const; QString errorMessage() const; + QString filePath() const { return ini()->fileName(); } + void clearCache(); protected: