UI: Options: Add Backup Export/Import

This commit is contained in:
Nodir Temirkhodjaev 2023-12-25 08:11:31 +03:00
parent b153a9364f
commit bd6b1165d7
21 changed files with 198 additions and 19 deletions

View File

@ -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))

View File

@ -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);

View File

@ -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 \

View File

@ -0,0 +1,3 @@
#include "confappmanager.h"
ConfAppManager::ConfAppManager(QObject *parent) : QObject { parent } { }

View File

@ -0,0 +1,16 @@
#ifndef CONFAPPMANAGER_H
#define CONFAPPMANAGER_H
#include <QObject>
class ConfAppManager : public QObject
{
Q_OBJECT
public:
explicit ConfAppManager(QObject *parent = nullptr);
signals:
};
#endif // CONFAPPMANAGER_H

View File

@ -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<TaskInfo *> &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();

View File

@ -61,6 +61,9 @@ public:
bool loadTasks(const QList<TaskInfo *> &taskInfos);
bool saveTasks(const QList<TaskInfo *> &taskInfos);
virtual bool exportBackup(const QString &path);
virtual bool importBackup(const QString &path);
void logBlockedApp(const LogEntryBlocked &logEntry);
qint64 appIdByPath(const QString &appPath);

View File

@ -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,

View File

@ -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,

View File

@ -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);

View File

@ -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());
};

View File

@ -4,10 +4,12 @@
#include <conf/confmanager.h>
#include <conf/firewallconf.h>
#include <form/dialog/dialogutil.h>
#include <fortsettings.h>
#include <manager/windowmanager.h>
#include <model/zonelistmodel.h>
#include <user/iniuser.h>
#include <util/fileutil.h>
#include <util/ioc/ioccontainer.h>
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();

View File

@ -46,6 +46,9 @@ public slots:
void saveChanges() { save(/*closeOnSuccess=*/true); }
void applyChanges() { save(/*closeOnSuccess=*/false); }
void exportBackup();
void importBackup();
void closeWindow();
private:

View File

@ -1,6 +1,7 @@
#include "optmainpage.h"
#include <QIcon>
#include <QMenu>
#include <QPushButton>
#include <QScrollArea>
#include <QTabWidget>
@ -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) {

View File

@ -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;

View File

@ -22,6 +22,7 @@
<file>icons/cross.png</file>
<file>icons/delete.png</file>
<file>icons/deny.png</file>
<file>icons/disk.png</file>
<file>icons/download_for_windows.png</file>
<file>icons/error.png</file>
<file>icons/folder.png</file>

BIN
src/ui/icons/disk.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -16,6 +16,16 @@ ConfManagerRpc::ConfManagerRpc(const QString &filePath, QObject *parent) :
{
}
bool ConfManagerRpc::exportBackup(const QString &path)
{
return IoC<RpcManager>()->doOnServer(Control::Rpc_ConfManager_exportBackup, { path });
}
bool ConfManagerRpc::importBackup(const QString &path)
{
return IoC<RpcManager>()->doOnServer(Control::Rpc_ConfManager_importBackup, { path });
}
bool ConfManagerRpc::addApp(const App &app)
{
return IoC<RpcManager>()->doOnServer(Control::Rpc_ConfManager_addApp, appToVarList(app));

View File

@ -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<qint64> &appIdList) override;
bool purgeApps() override;

View File

@ -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,

View File

@ -16,6 +16,8 @@ public:
bool hasError() const;
QString errorMessage() const;
QString filePath() const { return ini()->fileName(); }
void clearCache();
protected: