mirror of
https://github.com/Qv2ray/Qv2ray.git
synced 2025-05-20 19:00:22 +08:00
add: added new version auto restart
This commit is contained in:
parent
601bb116f3
commit
b7d7079ea6
@ -1 +1 @@
|
|||||||
5619
|
5620
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "Qv2rayApplication.hpp"
|
#include "Qv2rayApplication.hpp"
|
||||||
|
|
||||||
|
#include "3rdparty/libsemver/version.hpp"
|
||||||
#include "base/Qv2rayBase.hpp"
|
#include "base/Qv2rayBase.hpp"
|
||||||
#include "common/QvHelpers.hpp"
|
#include "common/QvHelpers.hpp"
|
||||||
#include "common/QvTranslator.hpp"
|
#include "common/QvTranslator.hpp"
|
||||||
@ -23,13 +24,12 @@ namespace Qv2ray
|
|||||||
Qv2rayApplication::Qv2rayApplication(int &argc, char *argv[])
|
Qv2rayApplication::Qv2rayApplication(int &argc, char *argv[])
|
||||||
: SingleApplication(argc, argv, true, User | ExcludeAppPath | ExcludeAppVersion)
|
: SingleApplication(argc, argv, true, User | ExcludeAppPath | ExcludeAppVersion)
|
||||||
{
|
{
|
||||||
LOG(MODULE_INIT, "Qv2ray Start Time: " + QSTRN(QTime::currentTime().msecsSinceStartOfDay()))
|
|
||||||
LOG(MODULE_INIT, "Qv2ray " QV2RAY_VERSION_STRING " on " + QSysInfo::prettyProductName() + " " + QSysInfo::currentCpuArchitecture())
|
LOG(MODULE_INIT, "Qv2ray " QV2RAY_VERSION_STRING " on " + QSysInfo::prettyProductName() + " " + QSysInfo::currentCpuArchitecture())
|
||||||
|
DEBUG(MODULE_INIT, "Qv2ray Start Time: " + QSTRN(QTime::currentTime().msecsSinceStartOfDay()))
|
||||||
DEBUG("QV2RAY_BUILD_INFO", QV2RAY_BUILD_INFO)
|
DEBUG("QV2RAY_BUILD_INFO", QV2RAY_BUILD_INFO)
|
||||||
DEBUG("QV2RAY_BUILD_EXTRA_INFO", QV2RAY_BUILD_EXTRA_INFO)
|
DEBUG("QV2RAY_BUILD_EXTRA_INFO", QV2RAY_BUILD_EXTRA_INFO)
|
||||||
DEBUG("QV2RAY_BUILD_NUMBER", QSTRN(QV2RAY_VERSION_BUILD))
|
DEBUG("QV2RAY_BUILD_NUMBER", QSTRN(QV2RAY_VERSION_BUILD))
|
||||||
//
|
hTray = new QSystemTrayIcon();
|
||||||
hTray = new QSystemTrayIcon(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Qv2rayApplication::SetupQv2ray()
|
bool Qv2rayApplication::SetupQv2ray()
|
||||||
@ -37,6 +37,7 @@ namespace Qv2ray
|
|||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
SetCurrentDirectory(applicationDirPath().toStdWString().c_str());
|
SetCurrentDirectory(applicationDirPath().toStdWString().c_str());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Install a default translater. From the OS/DE
|
// Install a default translater. From the OS/DE
|
||||||
Qv2rayTranslator = std::make_unique<QvTranslator>();
|
Qv2rayTranslator = std::make_unique<QvTranslator>();
|
||||||
const auto &systemLang = QLocale::system().name();
|
const auto &systemLang = QLocale::system().name();
|
||||||
@ -45,19 +46,72 @@ namespace Qv2ray
|
|||||||
//
|
//
|
||||||
setQuitOnLastWindowClosed(false);
|
setQuitOnLastWindowClosed(false);
|
||||||
connect(this, &SingleApplication::receivedMessage, this, &Qv2rayApplication::onMessageReceived);
|
connect(this, &SingleApplication::receivedMessage, this, &Qv2rayApplication::onMessageReceived);
|
||||||
|
connect(this, &SingleApplication::aboutToQuit, this, &Qv2rayApplication::aboutToQuitSlot);
|
||||||
if (isSecondary())
|
if (isSecondary())
|
||||||
{
|
{
|
||||||
sendMessage(JsonToString(Qv2rayProcessArgument.toJson(), QJsonDocument::Compact).toUtf8());
|
sendMessage(JsonToString(Qv2rayProcessArgument.toJson(), QJsonDocument::Compact).toUtf8());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
// Set special font in Windows
|
||||||
|
QFont font;
|
||||||
|
font.setPointSize(9);
|
||||||
|
font.setFamily("Microsoft YaHei");
|
||||||
|
app.application->setFont(font);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
setFallbackSessionManagementEnabled(false);
|
||||||
|
connect(this, &QGuiApplication::commitDataRequest, [] {
|
||||||
|
ConnectionManager->SaveConnectionConfig();
|
||||||
|
LOG(MODULE_INIT, "Quit triggered by session manager.")
|
||||||
|
});
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Qv2rayApplication::aboutToQuitSlot()
|
||||||
|
{
|
||||||
|
delete mainWindow;
|
||||||
|
delete hTray;
|
||||||
|
delete ConnectionManager;
|
||||||
|
delete RouteManager;
|
||||||
|
delete PluginHost;
|
||||||
|
delete StyleManager;
|
||||||
|
}
|
||||||
|
|
||||||
void Qv2rayApplication::onMessageReceived(quint32 clientId, QByteArray _msg)
|
void Qv2rayApplication::onMessageReceived(quint32 clientId, QByteArray _msg)
|
||||||
{
|
{
|
||||||
const auto msg = Qv2rayProcessArguments::fromJson(JsonFromString(_msg));
|
const auto msg = Qv2rayProcessArguments::fromJson(JsonFromString(_msg));
|
||||||
LOG(MODULE_INIT, "Client ID: " + QSTRN(clientId) + ", message received, version: " + msg.version)
|
LOG(MODULE_INIT, "Client ID: " + QSTRN(clientId) + ", message received, version: " + msg.version)
|
||||||
DEBUG(MODULE_INIT, _msg)
|
DEBUG(MODULE_INIT, _msg)
|
||||||
|
//
|
||||||
|
const auto currentVersion = semver::version::from_string(QV2RAY_VERSION_STRING);
|
||||||
|
const auto newVersion = semver::version::from_string(msg.version.toStdString());
|
||||||
|
//
|
||||||
|
if (newVersion > currentVersion)
|
||||||
|
{
|
||||||
|
QTimer::singleShot(0, [=]() {
|
||||||
|
const auto newPath = msg.fullArgs.first();
|
||||||
|
QString message;
|
||||||
|
message += tr("A new version of Qv2ray is attemping to start:") + NEWLINE;
|
||||||
|
message += NEWLINE;
|
||||||
|
message += tr("New version information: ") + NEWLINE;
|
||||||
|
message += tr("Qv2ray version: %1").arg(msg.version) + NEWLINE;
|
||||||
|
message += tr("Qv2ray path: %1").arg(newPath) + NEWLINE;
|
||||||
|
message += NEWLINE;
|
||||||
|
message += tr("Do you want to exit and launch that new version?");
|
||||||
|
|
||||||
|
const auto result = QvMessageBoxAsk(nullptr, tr("New version detected"), message);
|
||||||
|
if (result == QMessageBox::Yes)
|
||||||
|
{
|
||||||
|
Qv2rayProcessArgument._qvNewVersionPath = newPath;
|
||||||
|
ExitQv2ray(QV2RAY_EXITCODE_NEWVERSION);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto &argument : msg.arguments)
|
for (const auto &argument : msg.arguments)
|
||||||
{
|
{
|
||||||
switch (argument)
|
switch (argument)
|
||||||
@ -112,7 +166,15 @@ namespace Qv2ray
|
|||||||
{
|
{
|
||||||
// Show MainWindow
|
// Show MainWindow
|
||||||
mainWindow = new MainWindow();
|
mainWindow = new MainWindow();
|
||||||
return exec();
|
exec();
|
||||||
|
if (Qv2rayProcessArgument._qvNewVersionPath.isEmpty())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return QV2RAY_EXITCODE_NEWVERSION;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Qv2rayApplication::FindAndCreateInitialConfiguration()
|
bool Qv2rayApplication::FindAndCreateInitialConfiguration()
|
||||||
@ -318,15 +380,6 @@ namespace Qv2ray
|
|||||||
StyleManager->ApplyStyle(GlobalConfig.uiConfig.theme);
|
StyleManager->ApplyStyle(GlobalConfig.uiConfig.theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Qv2rayApplication::DeallocateGlobalVariables()
|
|
||||||
{
|
|
||||||
delete mainWindow;
|
|
||||||
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;
|
||||||
@ -336,15 +389,15 @@ namespace Qv2ray
|
|||||||
const auto &args = coreApp.arguments();
|
const auto &args = coreApp.arguments();
|
||||||
Qv2rayProcessArgument.version = QV2RAY_VERSION_STRING;
|
Qv2rayProcessArgument.version = QV2RAY_VERSION_STRING;
|
||||||
Qv2rayProcessArgument.fullArgs = args;
|
Qv2rayProcessArgument.fullArgs = args;
|
||||||
switch (ParseCommandLine(&errorMessage))
|
switch (ParseCommandLine(&errorMessage, args))
|
||||||
{
|
{
|
||||||
case QV2RAY_QUIT: return false;
|
case QV2RAY_QUIT: return false;
|
||||||
case QV2RAY_ERROR: LOG(MODULE_INIT, errorMessage) return false;
|
case QV2RAY_ERROR: LOG(MODULE_INIT, errorMessage) return false;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
const auto urlScheme = applicationName();
|
const auto urlScheme = coreApp.applicationName();
|
||||||
const auto appPath = QDir::toNativeSeparators(applicationFilePath());
|
const auto appPath = QDir::toNativeSeparators(coreApp.applicationFilePath());
|
||||||
const auto regPath = "HKEY_CURRENT_USER\\Software\\Classes\\" + urlScheme;
|
const auto regPath = "HKEY_CURRENT_USER\\Software\\Classes\\" + urlScheme;
|
||||||
|
|
||||||
QSettings reg(regPath, QSettings::NativeFormat);
|
QSettings reg(regPath, QSettings::NativeFormat);
|
||||||
@ -381,7 +434,7 @@ namespace Qv2ray
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Qv2rayApplication::commandline_status Qv2rayApplication::ParseCommandLine(QString *errorMessage)
|
Qv2rayApplication::commandline_status Qv2rayApplication::ParseCommandLine(QString *errorMessage, const QStringList &args)
|
||||||
{
|
{
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
//
|
//
|
||||||
@ -407,7 +460,7 @@ namespace Qv2ray
|
|||||||
auto helpOption = parser.addHelpOption();
|
auto helpOption = parser.addHelpOption();
|
||||||
auto versionOption = parser.addVersionOption();
|
auto versionOption = parser.addVersionOption();
|
||||||
|
|
||||||
if (!parser.parse(arguments()))
|
if (!parser.parse(args))
|
||||||
{
|
{
|
||||||
*errorMessage = parser.errorText();
|
*errorMessage = parser.errorText();
|
||||||
return QV2RAY_ERROR;
|
return QV2RAY_ERROR;
|
||||||
|
@ -24,7 +24,9 @@ namespace Qv2ray
|
|||||||
QString data;
|
QString data;
|
||||||
QList<QString> links;
|
QList<QString> links;
|
||||||
QList<QString> fullArgs;
|
QList<QString> fullArgs;
|
||||||
|
//
|
||||||
|
int _exitCode;
|
||||||
|
QString _qvNewVersionPath;
|
||||||
JSONSTRUCT_REGISTER(Qv2rayProcessArguments, F(arguments, version, data, links, fullArgs))
|
JSONSTRUCT_REGISTER(Qv2rayProcessArguments, F(arguments, version, data, links, fullArgs))
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -48,7 +50,6 @@ namespace Qv2ray
|
|||||||
bool LoadConfiguration();
|
bool LoadConfiguration();
|
||||||
void InitilizeGlobalVariables();
|
void InitilizeGlobalVariables();
|
||||||
int RunQv2ray();
|
int RunQv2ray();
|
||||||
void DeallocateGlobalVariables();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QSystemTrayIcon **GetTrayIcon()
|
QSystemTrayIcon **GetTrayIcon()
|
||||||
@ -65,12 +66,13 @@ namespace Qv2ray
|
|||||||
}
|
}
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void aboutToQuitSlot();
|
||||||
void onMessageReceived(quint32 clientID, QByteArray msg);
|
void onMessageReceived(quint32 clientID, QByteArray msg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSystemTrayIcon *hTray;
|
QSystemTrayIcon *hTray;
|
||||||
MainWindow *mainWindow;
|
MainWindow *mainWindow;
|
||||||
static commandline_status ParseCommandLine(QString *errorMessage);
|
static commandline_status ParseCommandLine(QString *errorMessage, const QStringList &args);
|
||||||
bool initilized = false;
|
bool initilized = false;
|
||||||
};
|
};
|
||||||
} // namespace Qv2ray
|
} // namespace Qv2ray
|
||||||
|
@ -112,15 +112,17 @@ using namespace Qv2ray::base::objects::transfer;
|
|||||||
|
|
||||||
namespace Qv2ray
|
namespace Qv2ray
|
||||||
{
|
{
|
||||||
|
constexpr auto QV2RAY_EXITCODE_NORMAL = 0;
|
||||||
|
constexpr auto QV2RAY_EXITCODE_NEWVERSION = -9;
|
||||||
// Qv2ray runtime config
|
// Qv2ray runtime config
|
||||||
inline bool isExiting = false;
|
inline bool isExiting = false;
|
||||||
inline QString Qv2rayConfigPath = "";
|
inline QString Qv2rayConfigPath = "";
|
||||||
inline base::config::Qv2rayConfigObject GlobalConfig = base::config::Qv2rayConfigObject();
|
inline base::config::Qv2rayConfigObject GlobalConfig = base::config::Qv2rayConfigObject();
|
||||||
//
|
//
|
||||||
inline void ExitQv2ray()
|
inline void ExitQv2ray(int retcode = QV2RAY_EXITCODE_NORMAL)
|
||||||
{
|
{
|
||||||
isExiting = true;
|
isExiting = true;
|
||||||
QCoreApplication::quit();
|
QCoreApplication::exit(retcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline QStringList Qv2rayAssetsPaths(const QString &dirName)
|
inline QStringList Qv2rayAssetsPaths(const QString &dirName)
|
||||||
|
83
src/main.cpp
83
src/main.cpp
@ -1,14 +1,11 @@
|
|||||||
#include "Qv2rayApplication.hpp"
|
#include "Qv2rayApplication.hpp"
|
||||||
#include "common/QvHelpers.hpp"
|
#include "common/QvHelpers.hpp"
|
||||||
#include "core/handler/ConfigHandler.hpp"
|
#include "core/handler/ConfigHandler.hpp"
|
||||||
#include "core/settings/SettingsBackend.hpp"
|
|
||||||
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
#include <QObject>
|
#include <QProcess>
|
||||||
#include <QSslSocket>
|
#include <QSslSocket>
|
||||||
#include <QStandardPaths>
|
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@ -19,32 +16,8 @@ void signalHandler(int signum)
|
|||||||
qvApp->exit(-99);
|
qvApp->exit(-99);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int RunQv2rayApplicationScoped(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
#ifndef Q_OS_WIN
|
|
||||||
// Register signal handlers.
|
|
||||||
signal(SIGINT, signalHandler);
|
|
||||||
signal(SIGHUP, signalHandler);
|
|
||||||
signal(SIGKILL, signalHandler);
|
|
||||||
signal(SIGTERM, signalHandler);
|
|
||||||
#endif
|
|
||||||
//
|
|
||||||
// This line must be called before any other ones, since we are using these
|
|
||||||
// values to identify instances.
|
|
||||||
Qv2rayApplication::setApplicationVersion(QV2RAY_VERSION_STRING);
|
|
||||||
//
|
|
||||||
#ifdef QT_DEBUG
|
|
||||||
Qv2rayApplication::setApplicationName("qv2ray_debug");
|
|
||||||
Qv2rayApplication::setApplicationDisplayName("Qv2ray - " + QObject::tr("Debug version"));
|
|
||||||
#else
|
|
||||||
Qv2rayApplication::setApplicationName("qv2ray");
|
|
||||||
Qv2rayApplication::setApplicationDisplayName("Qv2ray");
|
|
||||||
#endif
|
|
||||||
//
|
|
||||||
// parse the command line before starting as a Qt application
|
|
||||||
if (!Qv2rayApplication::PreInitilize(argc, argv))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
Qv2rayApplication app(argc, argv);
|
Qv2rayApplication app(argc, argv);
|
||||||
|
|
||||||
if (!app.SetupQv2ray())
|
if (!app.SetupQv2ray())
|
||||||
@ -108,27 +81,47 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
app.InitilizeGlobalVariables();
|
app.InitilizeGlobalVariables();
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
// Set special font in Windows
|
|
||||||
QFont font;
|
|
||||||
font.setPointSize(9);
|
|
||||||
font.setFamily("Microsoft YaHei");
|
|
||||||
app.setFont(font);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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
|
||||||
|
return app.RunQv2ray();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
int main(int argc, char *argv[])
|
||||||
qvApp->setFallbackSessionManagementEnabled(false);
|
{
|
||||||
QObject::connect(qvApp, &QGuiApplication::commitDataRequest, [] {
|
#ifndef Q_OS_WIN
|
||||||
ConnectionManager->SaveConnectionConfig();
|
// Register signal handlers.
|
||||||
LOG(MODULE_INIT, "Quit triggered by session manager.")
|
signal(SIGINT, signalHandler);
|
||||||
});
|
signal(SIGHUP, signalHandler);
|
||||||
|
signal(SIGKILL, signalHandler);
|
||||||
|
signal(SIGTERM, signalHandler);
|
||||||
#endif
|
#endif
|
||||||
auto rcode = app.RunQv2ray();
|
//
|
||||||
app.DeallocateGlobalVariables();
|
// This line must be called before any other ones, since we are using these
|
||||||
|
// values to identify instances.
|
||||||
|
QApplication::setApplicationVersion(QV2RAY_VERSION_STRING);
|
||||||
|
//
|
||||||
|
#ifdef QT_DEBUG
|
||||||
|
QApplication::setApplicationName("qv2ray_debug");
|
||||||
|
QApplication::setApplicationDisplayName("Qv2ray - " + QObject::tr("Debug version"));
|
||||||
|
#else
|
||||||
|
QApplication::setApplicationName("qv2ray");
|
||||||
|
QApplication::setApplicationDisplayName("Qv2ray");
|
||||||
|
#endif
|
||||||
|
//
|
||||||
|
// parse the command line before starting as a Qt application
|
||||||
|
if (!Qv2rayApplication::PreInitilize(argc, argv))
|
||||||
|
return -1;
|
||||||
|
const auto rcode = RunQv2rayApplicationScoped(argc, argv);
|
||||||
|
switch (rcode)
|
||||||
|
{
|
||||||
|
case QV2RAY_EXITCODE_NEWVERSION:
|
||||||
|
{
|
||||||
|
QProcess::startDetached(Qv2rayProcessArgument._qvNewVersionPath, {});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user