refactor: main.cpp refactor

This commit is contained in:
Qv2ray-dev 2020-06-13 21:51:28 +08:00
parent cefd4e3ee0
commit fce84ece23
8 changed files with 170 additions and 238 deletions

View File

@ -15,8 +15,6 @@ set(QV2RAY_BASE_HEADERS
set(QV2RAY_LIB_SOURCES
# headers
${CMAKE_SOURCE_DIR}/src/base/Qv2rayLog.cpp
${CMAKE_SOURCE_DIR}/src/common/CommandArgs.cpp
${CMAKE_SOURCE_DIR}/src/common/CommandArgs.hpp
${CMAKE_SOURCE_DIR}/src/common/HTTPRequestHelper.cpp
${CMAKE_SOURCE_DIR}/src/common/HTTPRequestHelper.hpp
${CMAKE_SOURCE_DIR}/src/common/QJsonModel.cpp

View File

@ -1 +1 @@
5578
5579

View File

@ -9,11 +9,11 @@ namespace Qv2ray
Qv2rayApplication::Qv2rayApplication(int &argc, char *argv[])
: SingleApplication(argc, argv, true, User | ExcludeAppPath | ExcludeAppVersion)
{
LOG("QV2RAY_BUILD_INFO", QV2RAY_BUILD_INFO)
LOG("QV2RAY_BUILD_EXTRA_INFO", QV2RAY_BUILD_EXTRA_INFO)
LOG("QV2RAY_BUILD_NUMBER", QSTRN(QV2RAY_VERSION_BUILD))
LOG(MODULE_INIT, "Qv2ray " QV2RAY_VERSION_STRING " on " + QSysInfo::prettyProductName() + " " + QSysInfo::currentCpuArchitecture())
LOG(MODULE_INIT, "Qv2ray Start Time: " + QSTRN(QTime::currentTime().msecsSinceStartOfDay()))
LOG(MODULE_INIT, "Qv2ray " QV2RAY_VERSION_STRING " on " + QSysInfo::prettyProductName() + " " + QSysInfo::currentCpuArchitecture())
DEBUG("QV2RAY_BUILD_INFO", QV2RAY_BUILD_INFO)
DEBUG("QV2RAY_BUILD_EXTRA_INFO", QV2RAY_BUILD_EXTRA_INFO)
DEBUG("QV2RAY_BUILD_NUMBER", QSTRN(QV2RAY_VERSION_BUILD))
}
bool Qv2rayApplication::SetupQv2ray()
@ -21,8 +21,7 @@ namespace Qv2ray
connect(this, &SingleApplication::receivedMessage, this, &Qv2rayApplication::onMessageReceived);
if (isSecondary())
{
const auto argument = arguments().join(' ');
sendMessage(argument.toUtf8());
sendMessage(JsonToString(Qv2rayProcessArgument.toJson()).toUtf8());
return true;
}
return false;
@ -31,25 +30,7 @@ namespace Qv2ray
void Qv2rayApplication::onMessageReceived(quint32 clientId, QByteArray msg)
{
LOG(MODULE_INIT, "Client ID: " + QSTRN(clientId) + " message received.")
const auto args = Qv2rayInterProcessArguments::fromJson(JsonFromString(msg));
}
void Qv2rayApplication::SetHiDPIEnableState(bool enabled)
{
if (enabled)
{
LOG(MODULE_INIT, "High DPI scaling is enabled.")
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif
}
else
{
LOG(MODULE_INIT, "Force set QT_SCALE_FACTOR to 1.")
LOG(MODULE_UI, "Original QT_SCALE_FACTOR was: " + qEnvironmentVariable("QT_SCALE_FACTOR"))
qputenv("QT_SCALE_FACTOR", "1");
}
const auto args = Qv2rayProcessArguments::fromJson(JsonFromString(msg));
}
bool Qv2rayApplication::InitilizeConfigurations()
@ -122,17 +103,16 @@ namespace Qv2ray
// Check if the dirs are write-able
if (!hasPossibleNewLocation)
{
//
// None of the path above can be used as a dir for storing config.
// Even the last folder failed to pass the check.
LOG(MODULE_INIT, "FATAL")
LOG(MODULE_INIT, " ---> CANNOT find a proper place to store Qv2ray config files.")
QvMessageBoxWarn(nullptr, QObject::tr("Cannot Start Qv2ray"),
QObject::tr("Cannot find a place to store config files.") + NEWLINE +
QObject::tr("Qv2ray has searched these paths below:") + NEWLINE + NEWLINE + //
configFilePaths.join(NEWLINE) + NEWLINE +
QObject::tr("It usually means you don't have the write permission to all of those locations.") +
QObject::tr("Qv2ray will now exit."));
QvMessageBoxWarn(nullptr, tr("Cannot Start Qv2ray"),
tr("Cannot find a place to store config files.") + NEWLINE + //
tr("Qv2ray has searched these paths below:") + NEWLINE + NEWLINE + //
configFilePaths.join(NEWLINE) + NEWLINE + //
tr("It usually means you don't have the write permission to all of those locations.") + NEWLINE + //
tr("Qv2ray will now exit.")); //
return false;
}
// Found a valid config dir, with write permission, but assume no config is located in it.
@ -151,13 +131,13 @@ namespace Qv2ray
// Otherwise Qv2ray would have loaded this config already instead of notifying to create a new config in this folder.
//
LOG(MODULE_INIT, "This should not occur: Qv2ray config exists but failed to load.")
QvMessageBoxWarn(nullptr, QObject::tr("Failed to initialise Qv2ray"),
QObject::tr("Failed to determine the location of config file:") + NEWLINE + //
QObject::tr("Qv2ray has found a config file, but it failed to be loaded due to some errors.") + NEWLINE + //
QObject::tr("A workaround is to remove the this file and restart Qv2ray:") + NEWLINE + //
QV2RAY_CONFIG_FILE + NEWLINE + //
QObject::tr("Qv2ray will now exit.") + NEWLINE + //
QObject::tr("Please report if you think it's a bug.")); //
QvMessageBoxWarn(nullptr, tr("Failed to initialise Qv2ray"),
tr("Failed to determine the location of config file:") + NEWLINE + //
tr("Qv2ray has found a config file, but it failed to be loaded due to some errors.") + NEWLINE + //
tr("A workaround is to remove the this file and restart Qv2ray:") + NEWLINE + //
QV2RAY_CONFIG_FILE + NEWLINE + //
tr("Qv2ray will now exit.") + NEWLINE + //
tr("Please report if you think it's a bug.")); //
return false;
}
@ -272,8 +252,7 @@ namespace Qv2ray
{
LOG(MODULE_SETTINGS, "Exception raised when checking config: " + configFile.fileName())
// LOG(INIT, e->what())
QvMessageBoxWarn(nullptr, QObject::tr("Warning"),
QObject::tr("Qv2ray cannot load the config file from here:") + NEWLINE + configFile.fileName());
QvMessageBoxWarn(nullptr, tr("Warning"), tr("Qv2ray cannot load the config file from here:") + NEWLINE + configFile.fileName());
return false;
}
}
@ -282,4 +261,111 @@ namespace Qv2ray
return true;
}
}
bool Qv2rayApplication::PreInitilize(int argc, char *argv[])
{
QCoreApplication consoleApp(argc, argv);
QString errorMessage;
const auto &args = consoleApp.arguments();
Qv2rayProcessArgument.path = args.first();
Qv2rayProcessArgument.version = QV2RAY_VERSION_STRING;
Qv2rayProcessArgument.data = args.join(" ");
switch (ParseCommandLine(&errorMessage))
{
case QUIT:
{
return false;
}
case ERROR:
{
LOG(MODULE_INIT, errorMessage)
return false;
}
case CONTINUE:
{
break;
}
}
// noScaleFactors = disable HiDPI
if (StartupOption.noScaleFactor)
{
LOG(MODULE_INIT, "Force set QT_SCALE_FACTOR to 1.")
LOG(MODULE_UI, "Original QT_SCALE_FACTOR was: " + qEnvironmentVariable("QT_SCALE_FACTOR"))
qputenv("QT_SCALE_FACTOR", "1");
}
else
{
LOG(MODULE_INIT, "High DPI scaling is enabled.")
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif
}
return true;
}
Qv2rayApplication::commandline_status Qv2rayApplication::ParseCommandLine(QString *errorMessage)
{
QCommandLineParser parser;
QCommandLineOption noAPIOption("noAPI", tr("Disable gRPC API subsystem."));
QCommandLineOption noPluginsOption("noPlugin", tr("Disable plugins feature"));
QCommandLineOption noScaleFactorOption("noScaleFactor", tr("Disable Qt UI scale factor"));
QCommandLineOption debugOption("debug", tr("Enable debug output"));
parser.setApplicationDescription(tr("Qv2ray - A cross-platform Qt frontend for V2ray."));
parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
//
parser.addOption(noAPIOption);
parser.addOption(noPluginsOption);
parser.addOption(noScaleFactorOption);
parser.addOption(debugOption);
auto helpOption = parser.addHelpOption();
auto versionOption = parser.addVersionOption();
if (!parser.parse(arguments()))
{
*errorMessage = parser.errorText();
return ERROR;
}
if (parser.isSet(versionOption))
{
parser.showVersion();
return QUIT;
}
if (parser.isSet(helpOption))
{
parser.showHelp();
return QUIT;
}
if (parser.isSet(noAPIOption))
{
DEBUG(MODULE_INIT, "noAPIOption is set.")
StartupOption.noAPI = true;
}
if (parser.isSet(debugOption))
{
DEBUG(MODULE_INIT, "debugOption is set.")
StartupOption.debugLog = true;
}
if (parser.isSet(noScaleFactorOption))
{
DEBUG(MODULE_INIT, "noScaleFactorOption is set.")
StartupOption.noScaleFactor = true;
}
if (parser.isSet(noPluginsOption))
{
DEBUG(MODULE_INIT, "noPluginOption is set.")
StartupOption.noPlugins = true;
}
return CONTINUE;
}
} // namespace Qv2ray

View File

@ -6,33 +6,46 @@
namespace Qv2ray
{
struct Qv2rayInterProcessArguments
struct Qv2rayProcessArguments
{
enum Argument
{
SHOWWINDOW = 0,
PROTOCOLHANDLER = 1,
EXITQV2RAY = 2,
NORMAL = 0,
QV2RAY_LINK = 1,
EXIT = 2
};
Argument argument;
QString version;
QString path;
QString data;
JSONSTRUCT_REGISTER(Qv2rayInterProcessArguments, F(argument, data))
JSONSTRUCT_REGISTER(Qv2rayProcessArguments, F(argument, version, path, data))
};
inline Qv2rayProcessArguments Qv2rayProcessArgument;
class Qv2rayApplication : public SingleApplication
{
enum commandline_status
{
ERROR,
QUIT,
CONTINUE
};
Q_OBJECT
public:
static bool PreInitilize(int argc, char *argv[]);
explicit Qv2rayApplication(int &argc, char *argv[]);
//
bool SetupQv2ray();
bool InitilizeConfigurations();
static void SetHiDPIEnableState(bool enabled);
bool CheckSettingsPathAvailability(const QString &_path, bool checkExistingConfig);
private slots:
void onMessageReceived(quint32 clientID, QByteArray msg);
private:
static commandline_status ParseCommandLine(QString *errorMessage);
bool initilized = false;
};
} // namespace Qv2ray

View File

@ -1,22 +1,26 @@
#pragma once
namespace Qv2ray
namespace Qv2ray::base
{
namespace base
struct QvStartupOptions
{
struct QvStartupOptions
{
/// No API subsystem
bool noAPI;
/// Explicitly run as root user.
bool forceRunAsRootUser;
/// Enable Debug Log.
bool debugLog;
/// Disable Qt scale factors support.
bool noScaleFactors;
/// Disable all plugin features.
bool noPlugins;
};
} // namespace base
inline base::QvStartupOptions StartupOption = base::QvStartupOptions();
} // namespace Qv2ray
/// No API subsystem
bool noAPI;
/// Enable Debug Log.
bool debugLog;
/// Disable Qt scale factors support.
bool noScaleFactor;
/// Disable all plugin features.
bool noPlugins;
/// Exit existing Qv2ray instance
bool exitQv2ray;
///
};
} // namespace Qv2ray::base
inline Qv2ray::base::QvStartupOptions StartupOption = Qv2ray::base::QvStartupOptions();

View File

@ -1,75 +0,0 @@
#include "CommandArgs.hpp"
#include "base/Qv2rayBase.hpp"
namespace Qv2ray::common
{
QvCommandArgParser::QvCommandArgParser()
: QObject(), noAPIOption("noAPI", tr("Disable gRPC API subsystems.")), //
runAsRootOption("I-just-wanna-run-with-root", tr("Explicitly run Qv2ray as root.")), //
debugOption("debug", tr("Enable Debug Output")), //
noScaleFactorOption("noScaleFactor", tr("Disable manually set QT_SCALE_FACTOR")), //
noPluginsOption("noPlugin", tr("Disable plugin feature")), //
//
helpOption("FAKE"), versionOption("FAKE")
{
parser.setApplicationDescription(QObject::tr("Qv2ray - A cross-platform Qt frontend for V2ray."));
parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
//
parser.addOption(noAPIOption);
parser.addOption(runAsRootOption);
parser.addOption(debugOption);
parser.addOption(noScaleFactorOption);
parser.addOption(noPluginsOption);
helpOption = parser.addHelpOption();
versionOption = parser.addVersionOption();
}
CommandLineParseResult QvCommandArgParser::ParseCommandLine(QString *errorMessage)
{
if (!parser.parse(QCoreApplication::arguments()))
{
*errorMessage = parser.errorText();
return CommandLineError;
}
if (parser.isSet(versionOption))
return CommandLineVersionRequested;
if (parser.isSet(helpOption))
return CommandLineHelpRequested;
if (parser.isSet(noAPIOption))
{
DEBUG(MODULE_INIT, "noAPIOption is set.")
StartupOption.noAPI = true;
}
if (parser.isSet(runAsRootOption))
{
DEBUG(MODULE_INIT, "runAsRootOption is set.")
StartupOption.forceRunAsRootUser = true;
}
if (parser.isSet(debugOption))
{
DEBUG(MODULE_INIT, "debugOption is set.")
StartupOption.debugLog = true;
}
if (parser.isSet(noScaleFactorOption))
{
DEBUG(MODULE_INIT, "noScaleFactorOption is set.")
StartupOption.noScaleFactors = true;
}
if (parser.isSet(noPluginsOption))
{
DEBUG(MODULE_INIT, "noPluginOption is set.")
StartupOption.noPlugins = true;
}
return CommandLineOk;
}
} // namespace Qv2ray::common

View File

@ -1,37 +0,0 @@
#pragma once
#include <QCommandLineParser>
namespace Qv2ray::common
{
enum CommandLineParseResult
{
CommandLineOk,
CommandLineError,
CommandLineVersionRequested,
CommandLineHelpRequested
};
class QvCommandArgParser : public QObject
{
Q_OBJECT
public:
QvCommandArgParser();
CommandLineParseResult ParseCommandLine(QString *errorMessage);
const QCommandLineParser *Parser()
{
return &parser;
}
private:
QCommandLineParser parser;
QCommandLineOption noAPIOption;
QCommandLineOption runAsRootOption;
QCommandLineOption debugOption;
QCommandLineOption noScaleFactorOption;
QCommandLineOption noPluginsOption;
QCommandLineOption helpOption;
QCommandLineOption versionOption;
};
} // namespace Qv2ray::common
using namespace Qv2ray::common;

View File

@ -1,5 +1,4 @@
#include "Qv2rayApplication.hpp"
#include "common/CommandArgs.hpp"
#include "common/QvHelpers.hpp"
#include "common/QvTranslator.hpp"
#include "components/plugins/QvPluginHost.hpp"
@ -18,11 +17,6 @@
#include <csignal>
#include <memory>
#ifdef Q_OS_UNIX
// For unix root user check
#include "unistd.h"
#endif
void signalHandler(int signum)
{
std::cout << "Qv2ray: Interrupt signal (" << signum << ") received." << std::endl;
@ -53,58 +47,7 @@ int main(int argc, char *argv[])
#endif
//
// parse the command line before starting as a Qt application
{
std::unique_ptr<QCoreApplication> consoleApp(new QCoreApplication(argc, argv));
//
// Install a default translator. From the OS/DE
Qv2rayTranslator = std::make_unique<QvTranslator>();
Qv2rayTranslator->InstallTranslation(QLocale::system().name());
QvCommandArgParser parser;
QString errorMessage;
switch (parser.ParseCommandLine(&errorMessage))
{
case CommandLineOk: break;
case CommandLineError:
std::cout << "Invalid command line arguments" << std::endl;
std::cout << errorMessage.toStdString() << std::endl;
std::cout << parser.Parser()->helpText().toStdString() << std::endl;
break;
case CommandLineVersionRequested:
LOG("Qv2ray", QV2RAY_VERSION_STRING)
LOG("QV2RAY_BUILD_INFO", QV2RAY_BUILD_INFO)
LOG("QV2RAY_BUILD_EXTRA_INFO", QV2RAY_BUILD_EXTRA_INFO)
return 0;
case CommandLineHelpRequested:
{
std::cout << parser.Parser()->helpText().toStdString() << std::endl;
return 0;
}
}
}
//
// finished: command line parsing
//
#ifdef Q_OS_UNIX
// Unix OS root user check.
// Do not use getuid() here since it's installed as owned by the root,
// someone may accidently setuid to it.
if (!StartupOption.forceRunAsRootUser && geteuid() == 0)
{
LOG("ERROR", QObject::tr("You cannot run Qv2ray as root, please use --I-just-wanna-run-with-root if you REALLY want to do so."))
LOG("ERROR", QObject::tr(" --> USE IT AT YOUR OWN RISK!"))
return 1;
}
#endif
//
// Early initialisation
// noScaleFactors = disable HiDPI
Qv2rayApplication::SetHiDPIEnableState(!StartupOption.noScaleFactors);
//
Qv2rayApplication::PreInitilize(argc, argv);
Qv2rayApplication app(argc, argv);
if (app.SetupQv2ray())
{