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 "base/Qv2rayBase.hpp"
#include "common/QvHelpers.hpp" #include "common/QvHelpers.hpp"
#include "common/QvTranslator.hpp" #include "common/QvTranslator.hpp"
#include "core/handler/ConfigHandler.hpp"
#include "core/handler/RouteHandler.hpp"
#include "core/settings/SettingsBackend.hpp" #include "core/settings/SettingsBackend.hpp"
#include "ui/styles/StyleManager.hpp"
#include "ui/windows/w_MainWindow.hpp"
#include <QUrl>
#include <QUrlQuery>
namespace Qv2ray namespace Qv2ray
{ {
@ -47,14 +54,38 @@ namespace Qv2ray
{ {
case Qv2rayProcessArguments::EXIT: ExitQv2ray(); break; case Qv2rayProcessArguments::EXIT: ExitQv2ray(); break;
case Qv2rayProcessArguments::NORMAL: case Qv2rayProcessArguments::NORMAL:
{
mainWindow->show();
mainWindow->raise();
mainWindow->activateWindow();
break;
}
case Qv2rayProcessArguments::RECONNECT: case Qv2rayProcessArguments::RECONNECT:
{
ConnectionManager->RestartConnection();
break;
}
case Qv2rayProcessArguments::DISCONNECT: 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) if (initilized)
{ {
@ -71,7 +102,6 @@ namespace Qv2ray
// //
// //
// Some built-in search paths for Qv2ray to find configs. (load the first one if possible). // Some built-in search paths for Qv2ray to find configs. (load the first one if possible).
//
QStringList configFilePaths; QStringList configFilePaths;
const auto useManualConfigPath = qEnvironmentVariableIsSet(QV2RAY_CONFIG_PATH_ENV_NAME); const auto useManualConfigPath = qEnvironmentVariableIsSet(QV2RAY_CONFIG_PATH_ENV_NAME);
const auto manualConfigPath = qEnvironmentVariable(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); QDir().mkdir(QV2RAY_GENERATED_DIR);
LOG(MODULE_INIT, "Created config generation dir at: " + QV2RAY_GENERATED_DIR) LOG(MODULE_INIT, "Created config generation dir at: " + QV2RAY_GENERATED_DIR)
} }
return true; return true;
} // namespace Qv2ray }
bool Qv2rayApplication::CheckSettingsPathAvailability(const QString &_path, bool checkExistingConfig) bool Qv2rayApplication::LoadConfiguration()
{ {
auto path = _path; // Load the config for upgrade, but do not parse it to the struct.
auto conf = JsonFromString(StringFromFile(QV2RAY_CONFIG_FILE));
if (!path.endsWith("/")) const auto configVersion = conf["config_version"].toInt();
path.append("/");
// Does not exist.
if (!QDir(path).exists())
return false;
if (configVersion > QV2RAY_CONFIG_VERSION)
{ {
// A temp file used to test file permissions in that folder. // Config version is larger than the current version...
QFile testFile(path + ".qv2ray_test_file" + QSTRN(QTime::currentTime().msecsSinceStartOfDay())); // This is rare but it may happen....
QvMessageBoxWarn(nullptr, tr("Qv2ray Cannot Continue"), //
if (!testFile.open(QFile::OpenModeFlag::ReadWrite)) 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 + //
LOG(MODULE_SETTINGS, "Directory at: " + path + " cannot be used as a valid config file path.") tr("Or submit a new issue if you think this is an error.") + NEWLINE + NEWLINE + //
LOG(MODULE_SETTINGS, "---> Cannot create a new file or open a file for writing.") tr("Qv2ray will now exit."));
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; return false;
} }
const auto err = VerifyJsonString(StringFromFile(configFile)); if (configVersion < QV2RAY_CONFIG_VERSION)
if (!err.isEmpty())
{ {
LOG(MODULE_INIT, "Json parse returns: " + err) // That is, config file needs to be upgraded.
return false; conf = Qv2ray::UpgradeSettingsVersion(configVersion, QV2RAY_CONFIG_VERSION, conf);
} }
// If the file format is valid. // Load config object from upgraded config QJsonObject
const auto conf = JsonFromString(StringFromFile(configFile)); auto confObject = Qv2rayConfigObject::fromJson(conf);
LOG(MODULE_SETTINGS, "Found a config file, v=" + conf["config_version"].toString() + " path=" + path)
configFile.close(); 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; 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[]) bool Qv2rayApplication::PreInitilize(int argc, char *argv[])
{ {
QString errorMessage; QString errorMessage;

View File

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

View File

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

View File

@ -1,19 +1,14 @@
#include "Qv2rayApplication.hpp" #include "Qv2rayApplication.hpp"
#include "common/QvHelpers.hpp" #include "common/QvHelpers.hpp"
#include "common/QvTranslator.hpp"
#include "components/plugins/QvPluginHost.hpp"
#include "core/handler/ConfigHandler.hpp" #include "core/handler/ConfigHandler.hpp"
#include "core/handler/RouteHandler.hpp"
#include "core/settings/SettingsBackend.hpp" #include "core/settings/SettingsBackend.hpp"
#include "ui/styles/StyleManager.hpp"
#include "ui/windows/w_MainWindow.hpp"
#include <QApplication> #include <QApplication>
#include <QFileInfo> #include <QFileInfo>
#include <QLocale> #include <QLocale>
#include <QObject> #include <QObject>
#include <QSslSocket>
#include <QStandardPaths> #include <QStandardPaths>
#include <QTranslator>
#include <csignal> #include <csignal>
#include <memory> #include <memory>
@ -82,57 +77,17 @@ int main(int argc, char *argv[])
#endif #endif
// //
// Qv2ray Initialize, find possible config paths and verify them. // 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; return -1;
} }
if (!app.LoadConfiguration())
// 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)
{ {
// Config version is larger than the current version... LOG(MODULE_INIT, "Cannot load existing configuration file.")
// 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."));
return -2; 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 // Check OpenSSL version for auto-update and subscriptions
auto osslReqVersion = QSslSocket::sslLibraryBuildVersionString(); auto osslReqVersion = QSslSocket::sslLibraryBuildVersionString();
auto osslCurVersion = QSslSocket::sslLibraryVersionString(); auto osslCurVersion = QSslSocket::sslLibraryVersionString();
@ -151,6 +106,8 @@ int main(int argc, char *argv[])
return -3; return -3;
} }
app.InitilizeGlobalVariables();
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
// Set special font in Windows // Set special font in Windows
QFont font; QFont font;
@ -158,48 +115,20 @@ int main(int argc, char *argv[])
font.setFamily("Microsoft YaHei"); font.setFamily("Microsoft YaHei");
app.setFont(font); app.setFont(font);
#endif #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 #ifndef Q_OS_WIN
signal(SIGUSR1, [](int) { ConnectionManager->RestartConnection(); }); signal(SIGUSR1, [](int) { ConnectionManager->RestartConnection(); });
signal(SIGUSR2, [](int) { ConnectionManager->StopConnection(); }); signal(SIGUSR2, [](int) { ConnectionManager->StopConnection(); });
#endif #endif
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
qvApp->setFallbackSessionManagementEnabled(false); qvApp->setFallbackSessionManagementEnabled(false);
QObject::connect(qvApp, &QGuiApplication::commitDataRequest, [] { QObject::connect(qvApp, &QGuiApplication::commitDataRequest, [] {
ConnectionManager->SaveConnectionConfig(); ConnectionManager->SaveConnectionConfig();
LOG(MODULE_INIT, "Quit triggered by session manager.") LOG(MODULE_INIT, "Quit triggered by session manager.")
}); });
#endif #endif
auto rcode = app.RunQv2ray();
// Show MainWindow app.DeallocateGlobalVariables();
MainWindow w; return rcode;
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;
}
} }

View File

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