refactor: more refactors 2

This commit is contained in:
Qv2ray-dev 2020-06-14 17:58:18 +08:00
parent 09ef7cea3a
commit 0289f72ecf
7 changed files with 182 additions and 153 deletions

View File

@ -1 +1 @@
5584
5585

View File

@ -3,7 +3,14 @@
#include "base/Qv2rayBase.hpp"
#include "common/QvHelpers.hpp"
#include "common/QvTranslator.hpp"
#include "core/handler/ConfigHandler.hpp"
#include "core/handler/RouteHandler.hpp"
#include "core/settings/SettingsBackend.hpp"
#include "ui/styles/StyleManager.hpp"
#include "ui/windows/w_MainWindow.hpp"
#include <QUrl>
#include <QUrlQuery>
namespace Qv2ray
{
@ -47,14 +54,38 @@ namespace Qv2ray
{
case Qv2rayProcessArguments::EXIT: ExitQv2ray(); break;
case Qv2rayProcessArguments::NORMAL:
{
mainWindow->show();
mainWindow->raise();
mainWindow->activateWindow();
break;
}
case Qv2rayProcessArguments::RECONNECT:
{
ConnectionManager->RestartConnection();
break;
}
case Qv2rayProcessArguments::DISCONNECT:
case Qv2rayProcessArguments::QV2RAY_LINK: break;
{
ConnectionManager->StopConnection();
break;
}
case Qv2rayProcessArguments::QV2RAY_LINK:
{
break;
}
}
}
}
bool Qv2rayApplication::InitilizeConfigurations()
int Qv2rayApplication::RunQv2ray()
{
// Show MainWindow
mainWindow = new MainWindow();
return exec();
}
bool Qv2rayApplication::FindAndCreateInitialConfiguration()
{
if (initilized)
{
@ -71,7 +102,6 @@ namespace Qv2ray
//
//
// Some built-in search paths for Qv2ray to find configs. (load the first one if possible).
//
QStringList configFilePaths;
const auto useManualConfigPath = qEnvironmentVariableIsSet(QV2RAY_CONFIG_PATH_ENV_NAME);
const auto manualConfigPath = qEnvironmentVariable(QV2RAY_CONFIG_PATH_ENV_NAME);
@ -199,78 +229,73 @@ namespace Qv2ray
QDir().mkdir(QV2RAY_GENERATED_DIR);
LOG(MODULE_INIT, "Created config generation dir at: " + QV2RAY_GENERATED_DIR)
}
return true;
} // namespace Qv2ray
}
bool Qv2rayApplication::CheckSettingsPathAvailability(const QString &_path, bool checkExistingConfig)
bool Qv2rayApplication::LoadConfiguration()
{
auto path = _path;
if (!path.endsWith("/"))
path.append("/");
// Does not exist.
if (!QDir(path).exists())
return false;
// Load the config for upgrade, but do not parse it to the struct.
auto conf = JsonFromString(StringFromFile(QV2RAY_CONFIG_FILE));
const auto configVersion = conf["config_version"].toInt();
if (configVersion > QV2RAY_CONFIG_VERSION)
{
// A temp file used to test file permissions in that folder.
QFile testFile(path + ".qv2ray_test_file" + QSTRN(QTime::currentTime().msecsSinceStartOfDay()));
if (!testFile.open(QFile::OpenModeFlag::ReadWrite))
{
LOG(MODULE_SETTINGS, "Directory at: " + path + " cannot be used as a valid config file path.")
LOG(MODULE_SETTINGS, "---> Cannot create a new file or open a file for writing.")
return false;
}
testFile.write("Qv2ray test file, feel free to remove.");
testFile.flush();
testFile.close();
if (!testFile.remove())
{
// This is rare, as we can create a file but failed to remove it.
LOG(MODULE_SETTINGS, "Directory at: " + path + " cannot be used as a valid config file path.")
LOG(MODULE_SETTINGS, "---> Cannot remove a file.")
return false;
}
}
if (!checkExistingConfig)
{
// Just pass the test
return true;
}
// Check if an existing config is found.
QFile configFile(path + "Qv2ray.conf");
// No such config file.
if (!configFile.exists())
return false;
if (!configFile.open(QIODevice::ReadWrite))
{
LOG(MODULE_SETTINGS, "File: " + configFile.fileName() + " cannot be opened!")
// Config version is larger than the current version...
// This is rare but it may happen....
QvMessageBoxWarn(nullptr, tr("Qv2ray Cannot Continue"), //
tr("You are running a lower version of Qv2ray compared to the current config file.") + NEWLINE + //
tr("Please check if there's an issue explaining about it.") + NEWLINE + //
tr("Or submit a new issue if you think this is an error.") + NEWLINE + NEWLINE + //
tr("Qv2ray will now exit."));
return false;
}
const auto err = VerifyJsonString(StringFromFile(configFile));
if (!err.isEmpty())
if (configVersion < QV2RAY_CONFIG_VERSION)
{
LOG(MODULE_INIT, "Json parse returns: " + err)
return false;
// That is, config file needs to be upgraded.
conf = Qv2ray::UpgradeSettingsVersion(configVersion, QV2RAY_CONFIG_VERSION, conf);
}
// If the file format is valid.
const auto conf = JsonFromString(StringFromFile(configFile));
LOG(MODULE_SETTINGS, "Found a config file, v=" + conf["config_version"].toString() + " path=" + path)
configFile.close();
// Load config object from upgraded config QJsonObject
auto confObject = Qv2rayConfigObject::fromJson(conf);
if (confObject.uiConfig.language.isEmpty())
{
// Prevent empty.
LOG(MODULE_UI, "Setting default UI language to system locale.")
confObject.uiConfig.language = QLocale::system().name();
}
if (!Qv2rayTranslator->InstallTranslation(confObject.uiConfig.language))
{
QvMessageBoxWarn(nullptr, "Translation Failed",
"Cannot load translation for " + confObject.uiConfig.language + NEWLINE + //
"English is now used." + NEWLINE + NEWLINE + //
"Please go to Preferences Window to change language or open an Issue");
}
// Let's save the config.
SaveGlobalSettings(confObject);
return true;
}
void Qv2rayApplication::InitilizeGlobalVariables()
{
StyleManager = new QvStyleManager();
PluginHost = new QvPluginHost();
RouteManager = new RouteHandler();
ConnectionManager = new QvConfigHandler();
StyleManager->ApplyStyle(GlobalConfig.uiConfig.theme);
}
void Qv2rayApplication::DeallocateGlobalVariables()
{
delete ConnectionManager;
delete RouteManager;
delete PluginHost;
delete StyleManager;
}
bool Qv2rayApplication::PreInitilize(int argc, char *argv[])
{
QString errorMessage;

View File

@ -4,6 +4,8 @@
#include <SingleApplication>
class MainWindow;
namespace Qv2ray
{
struct Qv2rayProcessArguments
@ -39,15 +41,18 @@ namespace Qv2ray
public:
static bool PreInitilize(int argc, char *argv[]);
explicit Qv2rayApplication(int &argc, char *argv[]);
//
bool SetupQv2ray();
bool InitilizeConfigurations();
bool CheckSettingsPathAvailability(const QString &_path, bool checkExistingConfig);
bool FindAndCreateInitialConfiguration();
bool LoadConfiguration();
void InitilizeGlobalVariables();
int RunQv2ray();
void DeallocateGlobalVariables();
private slots:
void onMessageReceived(quint32 clientID, QByteArray msg);
private:
MainWindow *mainWindow;
static commandline_status ParseCommandLine(QString *errorMessage);
bool initilized = false;
};

View File

@ -26,6 +26,74 @@ namespace Qv2ray::core::config
}
}
bool CheckSettingsPathAvailability(const QString &_path, bool checkExistingConfig)
{
auto path = _path;
if (!path.endsWith("/"))
path.append("/");
// Does not exist.
if (!QDir(path).exists())
return false;
{
// A temp file used to test file permissions in that folder.
QFile testFile(path + ".qv2ray_test_file" + QSTRN(QTime::currentTime().msecsSinceStartOfDay()));
if (!testFile.open(QFile::OpenModeFlag::ReadWrite))
{
LOG(MODULE_SETTINGS, "Directory at: " + path + " cannot be used as a valid config file path.")
LOG(MODULE_SETTINGS, "---> Cannot create a new file or open a file for writing.")
return false;
}
testFile.write("Qv2ray test file, feel free to remove.");
testFile.flush();
testFile.close();
if (!testFile.remove())
{
// This is rare, as we can create a file but failed to remove it.
LOG(MODULE_SETTINGS, "Directory at: " + path + " cannot be used as a valid config file path.")
LOG(MODULE_SETTINGS, "---> Cannot remove a file.")
return false;
}
}
if (!checkExistingConfig)
{
// Just pass the test
return true;
}
// Check if an existing config is found.
QFile configFile(path + "Qv2ray.conf");
// No such config file.
if (!configFile.exists())
return false;
if (!configFile.open(QIODevice::ReadWrite))
{
LOG(MODULE_SETTINGS, "File: " + configFile.fileName() + " cannot be opened!")
return false;
}
const auto err = VerifyJsonString(StringFromFile(configFile));
if (!err.isEmpty())
{
LOG(MODULE_INIT, "Json parse returns: " + err)
return false;
}
// If the file format is valid.
const auto conf = JsonFromString(StringFromFile(configFile));
LOG(MODULE_SETTINGS, "Found a config file, v=" + conf["config_version"].toString() + " path=" + path)
configFile.close();
return true;
}
} // namespace Qv2ray::core::config
using namespace Qv2ray::core::config;

View File

@ -6,6 +6,7 @@ namespace Qv2ray::core::config
void SaveGlobalSettings();
void SaveGlobalSettings(const Qv2rayConfigObject &conf);
void SetConfigDirPath(const QString &path);
bool CheckSettingsPathAvailability(const QString &_path, bool checkExistingConfig);
} // namespace Qv2ray::core::config
namespace Qv2ray

View File

@ -1,19 +1,14 @@
#include "Qv2rayApplication.hpp"
#include "common/QvHelpers.hpp"
#include "common/QvTranslator.hpp"
#include "components/plugins/QvPluginHost.hpp"
#include "core/handler/ConfigHandler.hpp"
#include "core/handler/RouteHandler.hpp"
#include "core/settings/SettingsBackend.hpp"
#include "ui/styles/StyleManager.hpp"
#include "ui/windows/w_MainWindow.hpp"
#include <QApplication>
#include <QFileInfo>
#include <QLocale>
#include <QObject>
#include <QSslSocket>
#include <QStandardPaths>
#include <QTranslator>
#include <csignal>
#include <memory>
@ -82,57 +77,17 @@ int main(int argc, char *argv[])
#endif
//
// Qv2ray Initialize, find possible config paths and verify them.
if (!app.InitilizeConfigurations())
if (!app.FindAndCreateInitialConfiguration())
{
LOG(MODULE_INIT, "Failed to initialise Qv2ray, exiting.")
LOG(MODULE_INIT, "Cannot find or create initial configuration file.")
return -1;
}
// Load the config for upgrade, but do not parse it to the struct.
auto conf = JsonFromString(StringFromFile(QV2RAY_CONFIG_FILE));
const auto configVersion = conf["config_version"].toInt();
if (configVersion > QV2RAY_CONFIG_VERSION)
if (!app.LoadConfiguration())
{
// Config version is larger than the current version...
// This is rare but it may happen....
QvMessageBoxWarn(nullptr, QObject::tr("Qv2ray Cannot Continue"),
QObject::tr("You are running a lower version of Qv2ray compared to the current config file.") + NEWLINE +
QObject::tr("Please check if there's an issue explaining about it.") + NEWLINE +
QObject::tr("Or submit a new issue if you think this is an error.") + NEWLINE + NEWLINE +
QObject::tr("Qv2ray will now exit."));
LOG(MODULE_INIT, "Cannot load existing configuration file.")
return -2;
}
if (configVersion < QV2RAY_CONFIG_VERSION)
{
// That is, config file needs to be upgraded.
conf = Qv2ray::UpgradeSettingsVersion(configVersion, QV2RAY_CONFIG_VERSION, conf);
}
{
// Load config object from upgraded config QJsonObject
auto confObject = Qv2rayConfigObject::fromJson(conf);
if (confObject.uiConfig.language.isEmpty())
{
// Prevent empty.
LOG(MODULE_UI, "Setting default UI language to system locale.")
confObject.uiConfig.language = QLocale::system().name();
}
if (!Qv2rayTranslator->InstallTranslation(confObject.uiConfig.language))
{
QvMessageBoxWarn(nullptr, "Translation Failed",
"Cannot load translation for " + confObject.uiConfig.language + NEWLINE + //
"English is now used." + NEWLINE + NEWLINE + //
"Please go to Preferences Window to change language or open an Issue");
}
// Let's save the config.
SaveGlobalSettings(confObject);
}
//
// Check OpenSSL version for auto-update and subscriptions
auto osslReqVersion = QSslSocket::sslLibraryBuildVersionString();
auto osslCurVersion = QSslSocket::sslLibraryVersionString();
@ -151,6 +106,8 @@ int main(int argc, char *argv[])
return -3;
}
app.InitilizeGlobalVariables();
#ifdef Q_OS_WIN
// Set special font in Windows
QFont font;
@ -158,48 +115,20 @@ int main(int argc, char *argv[])
font.setFamily("Microsoft YaHei");
app.setFont(font);
#endif
StyleManager = new QvStyleManager(qvApp);
StyleManager->ApplyStyle(GlobalConfig.uiConfig.theme);
try
{
// Initialise Connection Handler
PluginHost = new QvPluginHost();
ConnectionManager = new QvConfigHandler();
RouteManager = new RouteHandler();
#ifndef Q_OS_WIN
signal(SIGUSR1, [](int) { ConnectionManager->RestartConnection(); });
signal(SIGUSR2, [](int) { ConnectionManager->StopConnection(); });
signal(SIGUSR1, [](int) { ConnectionManager->RestartConnection(); });
signal(SIGUSR2, [](int) { ConnectionManager->StopConnection(); });
#endif
#ifdef Q_OS_LINUX
qvApp->setFallbackSessionManagementEnabled(false);
QObject::connect(qvApp, &QGuiApplication::commitDataRequest, [] {
ConnectionManager->SaveConnectionConfig();
LOG(MODULE_INIT, "Quit triggered by session manager.")
});
qvApp->setFallbackSessionManagementEnabled(false);
QObject::connect(qvApp, &QGuiApplication::commitDataRequest, [] {
ConnectionManager->SaveConnectionConfig();
LOG(MODULE_INIT, "Quit triggered by session manager.")
});
#endif
// Show MainWindow
MainWindow w;
QObject::connect(qvApp, &SingleApplication::receivedMessage, [&](quint32, QByteArray) {
// When a second instance is connected, show the mainwindow.
w.show();
w.raise();
w.activateWindow();
});
auto rcode = app.exec();
delete ConnectionManager;
delete RouteManager;
delete PluginHost;
LOG(MODULE_INIT, "Quitting normally")
return rcode;
}
catch (std::exception e)
{
QvMessageBoxWarn(nullptr, "ERROR", "There's something wrong happened and Qv2ray will quit now.");
LOG(MODULE_INIT, "EXCEPTION THROWN: " + QString(e.what()))
return -99;
}
auto rcode = app.RunQv2ray();
app.DeallocateGlobalVariables();
return rcode;
}

View File

@ -36,6 +36,7 @@ class MainWindow
void StartConnection() const;
void StopConnection() const;
void RestartConnection() const;
void ProcessCommand(const QStringList &command, const QMap<QString, QString> &args);
private:
QvMessageBusSlotDecl;