add: added new version auto restart

This commit is contained in:
Qv2ray-dev 2020-06-19 14:00:39 +08:00
parent 601bb116f3
commit b7d7079ea6
5 changed files with 119 additions and 69 deletions

View File

@ -1 +1 @@
5619
5620

View File

@ -1,5 +1,6 @@
#include "Qv2rayApplication.hpp"
#include "3rdparty/libsemver/version.hpp"
#include "base/Qv2rayBase.hpp"
#include "common/QvHelpers.hpp"
#include "common/QvTranslator.hpp"
@ -23,13 +24,12 @@ namespace Qv2ray
Qv2rayApplication::Qv2rayApplication(int &argc, char *argv[])
: 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())
DEBUG(MODULE_INIT, "Qv2ray Start Time: " + QSTRN(QTime::currentTime().msecsSinceStartOfDay()))
DEBUG("QV2RAY_BUILD_INFO", QV2RAY_BUILD_INFO)
DEBUG("QV2RAY_BUILD_EXTRA_INFO", QV2RAY_BUILD_EXTRA_INFO)
DEBUG("QV2RAY_BUILD_NUMBER", QSTRN(QV2RAY_VERSION_BUILD))
//
hTray = new QSystemTrayIcon(this);
hTray = new QSystemTrayIcon();
}
bool Qv2rayApplication::SetupQv2ray()
@ -37,6 +37,7 @@ namespace Qv2ray
#ifdef Q_OS_WIN
SetCurrentDirectory(applicationDirPath().toStdWString().c_str());
#endif
// Install a default translater. From the OS/DE
Qv2rayTranslator = std::make_unique<QvTranslator>();
const auto &systemLang = QLocale::system().name();
@ -45,19 +46,72 @@ namespace Qv2ray
//
setQuitOnLastWindowClosed(false);
connect(this, &SingleApplication::receivedMessage, this, &Qv2rayApplication::onMessageReceived);
connect(this, &SingleApplication::aboutToQuit, this, &Qv2rayApplication::aboutToQuitSlot);
if (isSecondary())
{
sendMessage(JsonToString(Qv2rayProcessArgument.toJson(), QJsonDocument::Compact).toUtf8());
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;
}
void Qv2rayApplication::aboutToQuitSlot()
{
delete mainWindow;
delete hTray;
delete ConnectionManager;
delete RouteManager;
delete PluginHost;
delete StyleManager;
}
void Qv2rayApplication::onMessageReceived(quint32 clientId, QByteArray _msg)
{
const auto msg = Qv2rayProcessArguments::fromJson(JsonFromString(_msg));
LOG(MODULE_INIT, "Client ID: " + QSTRN(clientId) + ", message received, version: " + msg.version)
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)
{
switch (argument)
@ -112,7 +166,15 @@ namespace Qv2ray
{
// Show MainWindow
mainWindow = new MainWindow();
return exec();
exec();
if (Qv2rayProcessArgument._qvNewVersionPath.isEmpty())
{
return 0;
}
else
{
return QV2RAY_EXITCODE_NEWVERSION;
}
}
bool Qv2rayApplication::FindAndCreateInitialConfiguration()
@ -318,15 +380,6 @@ namespace Qv2ray
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[])
{
QString errorMessage;
@ -336,15 +389,15 @@ namespace Qv2ray
const auto &args = coreApp.arguments();
Qv2rayProcessArgument.version = QV2RAY_VERSION_STRING;
Qv2rayProcessArgument.fullArgs = args;
switch (ParseCommandLine(&errorMessage))
switch (ParseCommandLine(&errorMessage, args))
{
case QV2RAY_QUIT: return false;
case QV2RAY_ERROR: LOG(MODULE_INIT, errorMessage) return false;
default: break;
}
#ifdef Q_OS_WIN
const auto urlScheme = applicationName();
const auto appPath = QDir::toNativeSeparators(applicationFilePath());
const auto urlScheme = coreApp.applicationName();
const auto appPath = QDir::toNativeSeparators(coreApp.applicationFilePath());
const auto regPath = "HKEY_CURRENT_USER\\Software\\Classes\\" + urlScheme;
QSettings reg(regPath, QSettings::NativeFormat);
@ -381,7 +434,7 @@ namespace Qv2ray
return true;
}
Qv2rayApplication::commandline_status Qv2rayApplication::ParseCommandLine(QString *errorMessage)
Qv2rayApplication::commandline_status Qv2rayApplication::ParseCommandLine(QString *errorMessage, const QStringList &args)
{
QCommandLineParser parser;
//
@ -407,7 +460,7 @@ namespace Qv2ray
auto helpOption = parser.addHelpOption();
auto versionOption = parser.addVersionOption();
if (!parser.parse(arguments()))
if (!parser.parse(args))
{
*errorMessage = parser.errorText();
return QV2RAY_ERROR;

View File

@ -24,7 +24,9 @@ namespace Qv2ray
QString data;
QList<QString> links;
QList<QString> fullArgs;
//
int _exitCode;
QString _qvNewVersionPath;
JSONSTRUCT_REGISTER(Qv2rayProcessArguments, F(arguments, version, data, links, fullArgs))
};
@ -48,7 +50,6 @@ namespace Qv2ray
bool LoadConfiguration();
void InitilizeGlobalVariables();
int RunQv2ray();
void DeallocateGlobalVariables();
public:
QSystemTrayIcon **GetTrayIcon()
@ -65,12 +66,13 @@ namespace Qv2ray
}
private slots:
void aboutToQuitSlot();
void onMessageReceived(quint32 clientID, QByteArray msg);
private:
QSystemTrayIcon *hTray;
MainWindow *mainWindow;
static commandline_status ParseCommandLine(QString *errorMessage);
static commandline_status ParseCommandLine(QString *errorMessage, const QStringList &args);
bool initilized = false;
};
} // namespace Qv2ray

View File

@ -112,15 +112,17 @@ using namespace Qv2ray::base::objects::transfer;
namespace Qv2ray
{
constexpr auto QV2RAY_EXITCODE_NORMAL = 0;
constexpr auto QV2RAY_EXITCODE_NEWVERSION = -9;
// Qv2ray runtime config
inline bool isExiting = false;
inline QString Qv2rayConfigPath = "";
inline base::config::Qv2rayConfigObject GlobalConfig = base::config::Qv2rayConfigObject();
//
inline void ExitQv2ray()
inline void ExitQv2ray(int retcode = QV2RAY_EXITCODE_NORMAL)
{
isExiting = true;
QCoreApplication::quit();
QCoreApplication::exit(retcode);
}
inline QStringList Qv2rayAssetsPaths(const QString &dirName)

View File

@ -1,14 +1,11 @@
#include "Qv2rayApplication.hpp"
#include "common/QvHelpers.hpp"
#include "core/handler/ConfigHandler.hpp"
#include "core/settings/SettingsBackend.hpp"
#include <QApplication>
#include <QFileInfo>
#include <QLocale>
#include <QObject>
#include <QProcess>
#include <QSslSocket>
#include <QStandardPaths>
#include <csignal>
#include <memory>
@ -19,32 +16,8 @@ void signalHandler(int signum)
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);
if (!app.SetupQv2ray())
@ -108,27 +81,47 @@ int main(int argc, char *argv[])
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
signal(SIGUSR1, [](int) { ConnectionManager->RestartConnection(); });
signal(SIGUSR2, [](int) { ConnectionManager->StopConnection(); });
#endif
return app.RunQv2ray();
}
#ifdef Q_OS_LINUX
qvApp->setFallbackSessionManagementEnabled(false);
QObject::connect(qvApp, &QGuiApplication::commitDataRequest, [] {
ConnectionManager->SaveConnectionConfig();
LOG(MODULE_INIT, "Quit triggered by session manager.")
});
int main(int argc, char *argv[])
{
#ifndef Q_OS_WIN
// Register signal handlers.
signal(SIGINT, signalHandler);
signal(SIGHUP, signalHandler);
signal(SIGKILL, signalHandler);
signal(SIGTERM, signalHandler);
#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;
}