mirror of
https://github.com/Qv2ray/Qv2ray.git
synced 2025-05-20 19:00:22 +08:00
[Added] Import config from file.
This commit is contained in:
parent
e16466ffe9
commit
220f202c61
@ -10,6 +10,8 @@
|
|||||||
#define DROOT QJsonObject root;
|
#define DROOT QJsonObject root;
|
||||||
#define RROOT return root;
|
#define RROOT return root;
|
||||||
|
|
||||||
|
#define JSON_ROOT_TRY_REMOVE(obj) if (root.contains(obj)) { root.remove(obj); }
|
||||||
|
|
||||||
namespace Qv2ray
|
namespace Qv2ray
|
||||||
{
|
{
|
||||||
namespace ConfigOperations
|
namespace ConfigOperations
|
||||||
@ -32,15 +34,24 @@ namespace Qv2ray
|
|||||||
//
|
//
|
||||||
// Misc
|
// Misc
|
||||||
template<typename T>
|
template<typename T>
|
||||||
QJsonObject GetRootObject(T out);
|
QJsonObject GetRootObject(T t)
|
||||||
|
{
|
||||||
|
auto json = StructToJSON(t);
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(QByteArray::fromStdString(json.toStdString()));
|
||||||
|
return doc.object();
|
||||||
|
}
|
||||||
|
template QJsonObject GetRootObject<StreamSettingsObject>(StreamSettingsObject t);
|
||||||
|
template QJsonObject GetRootObject<VMessOut>(VMessOut t);
|
||||||
//
|
//
|
||||||
// -------------------------- BEGIN CONFIG VALIDATIONS ---------------------------------------------
|
// -------------------------- BEGIN CONFIG VALIDATIONS ---------------------------------------------
|
||||||
int VerifyVMessProtocolString(QString vmess);
|
int VerifyVMessProtocolString(QString vmess);
|
||||||
|
//
|
||||||
// -------------------------- BEGIN CONFIG CONVERSIONS ---------------------------------------------
|
// -------------------------- BEGIN CONFIG CONVERSIONS ---------------------------------------------
|
||||||
// Save Connection Config
|
// Save Connection Config
|
||||||
int SaveConnectionConfig(QJsonObject obj, const QString *alias);
|
int SaveConnectionConfig(QJsonObject obj, const QString *alias);
|
||||||
// VMess Protocol
|
// VMess Protocol
|
||||||
QJsonObject ConvertOutboundFromVMessString(QString vmess);
|
QJsonObject ConvertConfigFromVMessString(QString vmess);
|
||||||
|
QJsonObject ConvertConfigFromFile(QString sourceFilePath, bool overrideInbounds);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,5 +17,112 @@ namespace Qv2ray
|
|||||||
SaveStringToFile(doc.toJson(), &config);
|
SaveStringToFile(doc.toJson(), &config);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This generates an "OutBoundObject"
|
||||||
|
QJsonObject ConvertConfigFromVMessString(QString str)
|
||||||
|
{
|
||||||
|
DROOT
|
||||||
|
QStringRef vmessJsonB64(&str, 8, str.length() - 8);
|
||||||
|
auto vmessConf = StructFromJSON<VMessProtocolConfigObject>(Base64Decode(vmessJsonB64.toString()).toStdString());
|
||||||
|
VMessOut vConf;
|
||||||
|
VMessOut::ServerObject serv;
|
||||||
|
serv.port = stoi(vmessConf.port);
|
||||||
|
serv.address = vmessConf.add;
|
||||||
|
// User
|
||||||
|
VMessOut::ServerObject::UserObject user;
|
||||||
|
user.id = vmessConf.id;
|
||||||
|
user.alterId = stoi(vmessConf.aid);
|
||||||
|
// Server
|
||||||
|
serv.users.push_back(user);
|
||||||
|
// VMess root config
|
||||||
|
vConf.vnext.push_back(serv);
|
||||||
|
//
|
||||||
|
// Stream Settings
|
||||||
|
StreamSettingsObject streaming;
|
||||||
|
|
||||||
|
// Fill hosts for HTTP
|
||||||
|
foreach (auto host, QString::fromStdString(vmessConf.host).split(',')) {
|
||||||
|
streaming.httpSettings.host.push_back(host.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// hosts for ws, h2 and security for QUIC
|
||||||
|
streaming.wsSettings.headers.insert(make_pair("Host", vmessConf.host));
|
||||||
|
streaming.quicSettings.security = vmessConf.host;
|
||||||
|
//
|
||||||
|
// Fake type for tcp, kcp and QUIC
|
||||||
|
streaming.tcpSettings.header.type = vmessConf.type;
|
||||||
|
streaming.kcpSettings.header.type = vmessConf.type;
|
||||||
|
streaming.quicSettings.header.type = vmessConf.type;
|
||||||
|
//
|
||||||
|
// Path for ws, h2, Quic
|
||||||
|
streaming.wsSettings.path = vmessConf.path;
|
||||||
|
streaming.httpSettings.path = vmessConf.path;
|
||||||
|
streaming.quicSettings.key = vmessConf.path;
|
||||||
|
streaming.security = vmessConf.tls;
|
||||||
|
//
|
||||||
|
// Network type
|
||||||
|
streaming.network = vmessConf.net;
|
||||||
|
//
|
||||||
|
// Root
|
||||||
|
root.insert("sendThrough", "0.0.0.0");
|
||||||
|
root.insert("protocol", "vmess");
|
||||||
|
root.insert("settings", GetRootObject(vConf));
|
||||||
|
root.insert("tag", OUTBOUND_TAG_PROXY);
|
||||||
|
root.insert("streamSettings", GetRootObject(streaming));
|
||||||
|
root.insert("QV2RAY_ALIAS", QString::fromStdString(vmessConf.ps));
|
||||||
|
RROOT
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject ConvertConfigFromFile(QString sourceFilePath, bool overrideInbounds)
|
||||||
|
{
|
||||||
|
auto globalConf = GetGlobalConfig();
|
||||||
|
QFile configFile(sourceFilePath);
|
||||||
|
configFile.open(QIODevice::ReadOnly | QIODevice::ExistingOnly);
|
||||||
|
QByteArray allData = configFile.readAll();
|
||||||
|
configFile.close();
|
||||||
|
QJsonDocument v2conf = QJsonDocument::fromJson(allData);
|
||||||
|
QJsonObject root = v2conf.object();
|
||||||
|
|
||||||
|
if (overrideInbounds) {
|
||||||
|
JSON_ROOT_TRY_REMOVE("inbounds")
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
JSON_ROOT_TRY_REMOVE("log")
|
||||||
|
JSON_ROOT_TRY_REMOVE("api")
|
||||||
|
JSON_ROOT_TRY_REMOVE("stats")
|
||||||
|
JSON_ROOT_TRY_REMOVE("policy")
|
||||||
|
JSON_ROOT_TRY_REMOVE("dns")
|
||||||
|
//
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* {
|
||||||
|
QFile configFile(path);
|
||||||
|
|
||||||
|
if (!configFile.open(QIODevice::ReadOnly)) {
|
||||||
|
QvMessageBox(this, tr("ImportConfig"), tr("CannotOpenFile"));
|
||||||
|
qDebug() << "ImportConfig::CannotOpenFile";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray allData = configFile.readAll();
|
||||||
|
configFile.close();
|
||||||
|
QJsonDocument v2conf(QJsonDocument::fromJson(allData));
|
||||||
|
QJsonObject rootobj = v2conf.object();
|
||||||
|
QJsonObject outbound;
|
||||||
|
|
||||||
|
if (rootobj.contains("outbounds")) {
|
||||||
|
outbound = rootobj.value("outbounds").toArray().first().toObject();
|
||||||
|
} else {
|
||||||
|
outbound = rootobj.value("outbound").toObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!QFile::copy(path, "newFile")) {
|
||||||
|
QvMessageBox(this, tr("ImportConfig"), tr("CannotCopyCustomConfig"));
|
||||||
|
qDebug() << "ImportConfig::CannotCopyCustomConfig";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,14 +62,6 @@ namespace Qv2ray
|
|||||||
RROOT
|
RROOT
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
QJsonObject GetRootObject(T out)
|
|
||||||
{
|
|
||||||
auto json = StructToJSON(out);
|
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(QByteArray::fromStdString(json.toStdString()));
|
|
||||||
return doc.object();
|
|
||||||
}
|
|
||||||
|
|
||||||
QJsonObject GenerateShadowSocksServerOUT(QString email, QString address, int port, QString method, QString password, bool ota, int level)
|
QJsonObject GenerateShadowSocksServerOUT(QString email, QString address, int port, QString method, QString password, bool ota, int level)
|
||||||
{
|
{
|
||||||
DROOT
|
DROOT
|
||||||
@ -122,62 +114,6 @@ namespace Qv2ray
|
|||||||
JADD(auth, accounts, udp, ip, userLevel)
|
JADD(auth, accounts, udp, ip, userLevel)
|
||||||
RROOT
|
RROOT
|
||||||
}
|
}
|
||||||
|
|
||||||
// This generates an "OutBoundObject"
|
|
||||||
QJsonObject ConvertOutboundFromVMessString(QString str)
|
|
||||||
{
|
|
||||||
DROOT
|
|
||||||
QStringRef vmessJsonB64(&str, 8, str.length() - 8);
|
|
||||||
auto vmessConf = StructFromJSON<VMessProtocolConfigObject>(Base64Decode(vmessJsonB64.toString()).toStdString());
|
|
||||||
VMessOut vConf;
|
|
||||||
VMessOut::ServerObject serv;
|
|
||||||
serv.port = stoi(vmessConf.port);
|
|
||||||
serv.address = vmessConf.add;
|
|
||||||
// User
|
|
||||||
VMessOut::ServerObject::UserObject user;
|
|
||||||
user.id = vmessConf.id;
|
|
||||||
user.alterId = stoi(vmessConf.aid);
|
|
||||||
// Server
|
|
||||||
serv.users.push_back(user);
|
|
||||||
// VMess root config
|
|
||||||
vConf.vnext.push_back(serv);
|
|
||||||
//
|
|
||||||
// Stream Settings
|
|
||||||
StreamSettingsObject streaming;
|
|
||||||
|
|
||||||
// Fill hosts for HTTP
|
|
||||||
foreach (auto host, QString::fromStdString(vmessConf.host).split(',')) {
|
|
||||||
streaming.httpSettings.host.push_back(host.toStdString());
|
|
||||||
}
|
|
||||||
|
|
||||||
// hosts for ws, h2 and security for QUIC
|
|
||||||
streaming.wsSettings.headers.insert(make_pair("Host", vmessConf.host));
|
|
||||||
streaming.quicSettings.security = vmessConf.host;
|
|
||||||
//
|
|
||||||
// Fake type for tcp, kcp and QUIC
|
|
||||||
streaming.tcpSettings.header.type = vmessConf.type;
|
|
||||||
streaming.kcpSettings.header.type = vmessConf.type;
|
|
||||||
streaming.quicSettings.header.type = vmessConf.type;
|
|
||||||
//
|
|
||||||
// Path for ws, h2, Quic
|
|
||||||
streaming.wsSettings.path = vmessConf.path;
|
|
||||||
streaming.httpSettings.path = vmessConf.path;
|
|
||||||
streaming.quicSettings.key = vmessConf.path;
|
|
||||||
streaming.security = vmessConf.tls;
|
|
||||||
//
|
|
||||||
// Network type
|
|
||||||
streaming.network = vmessConf.net;
|
|
||||||
//
|
|
||||||
// Root
|
|
||||||
root.insert("sendThrough", "0.0.0.0");
|
|
||||||
root.insert("protocol", "vmess");
|
|
||||||
root.insert("settings", GetRootObject(vConf));
|
|
||||||
root.insert("tag", OUTBOUND_TAG_PROXY);
|
|
||||||
root.insert("streamSettings", GetRootObject(streaming));
|
|
||||||
root.insert("QV2RAY_ALIAS", QString::fromStdString(vmessConf.ps));
|
|
||||||
RROOT
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------- END CONFIG GENERATIONS ------------------------------------------------------------------------------
|
// -------------------------- END CONFIG GENERATIONS ------------------------------------------------------------------------------
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,14 @@
|
|||||||
|
|
||||||
namespace Qv2ray
|
namespace Qv2ray
|
||||||
{
|
{
|
||||||
bool Qv2Instance::checkConfigFile(const QString path)
|
bool Qv2Instance::VerifyVConfigFile(const QString path)
|
||||||
{
|
{
|
||||||
if (checkCoreExe()) {
|
if (ValidateV2rayCoreExe()) {
|
||||||
|
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||||
|
env.insert("V2RAY_LOCATION_ASSET", QString::fromStdString(GetGlobalConfig().v2AssetsPath));
|
||||||
QProcess process;
|
QProcess process;
|
||||||
process.start(QString::fromStdString(Utils::GetGlobalConfig().v2Path), QStringList() << "-test"
|
process.setProcessEnvironment(env);
|
||||||
|
process.start(QString::fromStdString(Utils::GetGlobalConfig().v2CorePath), QStringList() << "-test"
|
||||||
<< "-config" << path,
|
<< "-config" << path,
|
||||||
QIODevice::ReadWrite | QIODevice::Text);
|
QIODevice::ReadWrite | QIODevice::Text);
|
||||||
|
|
||||||
@ -37,9 +40,9 @@ namespace Qv2ray
|
|||||||
Status = STOPPED;
|
Status = STOPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Qv2Instance::checkCoreExe()
|
bool Qv2Instance::ValidateV2rayCoreExe()
|
||||||
{
|
{
|
||||||
auto path = QString::fromStdString(Utils::GetGlobalConfig().v2Path);
|
auto path = QString::fromStdString(Utils::GetGlobalConfig().v2CorePath);
|
||||||
|
|
||||||
if (!QFile::exists(path)) {
|
if (!QFile::exists(path)) {
|
||||||
Utils::QvMessageBox(nullptr, QObject::tr("CoreNotFound"), QObject::tr("CoreFileNotFoundExplainationAt:") + path);
|
Utils::QvMessageBox(nullptr, QObject::tr("CoreNotFound"), QObject::tr("CoreFileNotFoundExplainationAt:") + path);
|
||||||
@ -47,7 +50,7 @@ namespace Qv2ray
|
|||||||
} else return true;
|
} else return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Qv2Instance::start()
|
bool Qv2Instance::Start()
|
||||||
{
|
{
|
||||||
if (Status != STOPPED) {
|
if (Status != STOPPED) {
|
||||||
return false;
|
return false;
|
||||||
@ -55,11 +58,12 @@ namespace Qv2ray
|
|||||||
|
|
||||||
Status = STARTING;
|
Status = STARTING;
|
||||||
|
|
||||||
if (checkCoreExe()) {
|
if (ValidateV2rayCoreExe()) {
|
||||||
if (checkConfigFile(QV2RAY_GENERATED_CONFIG_DIRPATH + "config.json")) {
|
if (VerifyVConfigFile(QV2RAY_GENERATED_CONFIG_DIRPATH + "config.json")) {
|
||||||
}
|
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||||
|
env.insert("V2RAY_LOCATION_ASSET", QString::fromStdString(GetGlobalConfig().v2AssetsPath));
|
||||||
vProcess->start(QString::fromStdString(_config.v2Path), QStringList() << "-config"
|
vProcess->setProcessEnvironment(env);
|
||||||
|
vProcess->start(QString::fromStdString(_config.v2CorePath), QStringList() << "-config"
|
||||||
<< QV2RAY_GENERATED_CONFIG_DIRPATH + "config.json",
|
<< QV2RAY_GENERATED_CONFIG_DIRPATH + "config.json",
|
||||||
QIODevice::ReadWrite | QIODevice::Text);
|
QIODevice::ReadWrite | QIODevice::Text);
|
||||||
vProcess->waitForStarted();
|
vProcess->waitForStarted();
|
||||||
@ -69,9 +73,13 @@ namespace Qv2ray
|
|||||||
Status = STOPPED;
|
Status = STOPPED;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Status = STOPPED;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Qv2Instance::stop()
|
void Qv2Instance::Stop()
|
||||||
{
|
{
|
||||||
vProcess->close();
|
vProcess->close();
|
||||||
Status = STOPPED;
|
Status = STOPPED;
|
||||||
@ -84,7 +92,7 @@ namespace Qv2ray
|
|||||||
|
|
||||||
Qv2Instance::~Qv2Instance()
|
Qv2Instance::~Qv2Instance()
|
||||||
{
|
{
|
||||||
stop();
|
Stop();
|
||||||
delete vProcess;
|
delete vProcess;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,13 +17,13 @@ namespace Qv2ray
|
|||||||
public:
|
public:
|
||||||
explicit Qv2Instance(QWidget *parent = nullptr);
|
explicit Qv2Instance(QWidget *parent = nullptr);
|
||||||
|
|
||||||
bool start();
|
bool Start();
|
||||||
void stop();
|
void Stop();
|
||||||
|
|
||||||
QString readOutput();
|
QString readOutput();
|
||||||
V2RAY_INSTANCE_STARTUP_STATUS Status;
|
V2RAY_INSTANCE_STARTUP_STATUS Status;
|
||||||
static bool checkConfigFile(QString path);
|
static bool VerifyVConfigFile(QString path);
|
||||||
static bool checkCoreExe();
|
static bool ValidateV2rayCoreExe();
|
||||||
|
|
||||||
~Qv2Instance();
|
~Qv2Instance();
|
||||||
private:
|
private:
|
||||||
|
@ -41,22 +41,24 @@ namespace Qv2ray
|
|||||||
struct Qv2Config {
|
struct Qv2Config {
|
||||||
string language;
|
string language;
|
||||||
bool runAsRoot;
|
bool runAsRoot;
|
||||||
string logLevel;
|
int logLevel;
|
||||||
string v2Path;
|
string v2CorePath;
|
||||||
|
string v2AssetsPath;
|
||||||
QvInbondSetting httpSetting;
|
QvInbondSetting httpSetting;
|
||||||
QvInbondSetting socksSetting;
|
QvInbondSetting socksSetting;
|
||||||
list<string> configs;
|
list<string> configs;
|
||||||
Qv2Config(): language(), runAsRoot(), logLevel(), httpSetting(), socksSetting(), configs() { }
|
Qv2Config(): httpSetting(), socksSetting(), configs() { }
|
||||||
Qv2Config(string lang, string exePath, string log, QvInbondSetting httpIn, QvInbondSetting socksIN): Qv2Config()
|
Qv2Config(string lang, string exePath, string assetsPath, int log, QvInbondSetting httpIn, QvInbondSetting socksIN): Qv2Config()
|
||||||
{
|
{
|
||||||
v2Path = exePath;
|
|
||||||
language = lang;
|
language = lang;
|
||||||
|
v2CorePath = exePath;
|
||||||
|
v2AssetsPath = assetsPath;
|
||||||
logLevel = log;
|
logLevel = log;
|
||||||
httpSetting = httpIn;
|
httpSetting = httpIn;
|
||||||
socksSetting = socksIN;
|
socksSetting = socksIN;
|
||||||
runAsRoot = false;
|
runAsRoot = false;
|
||||||
}
|
}
|
||||||
XTOSTRUCT(O(language, v2Path, runAsRoot, logLevel, httpSetting, socksSetting, configs))
|
XTOSTRUCT(O(language, v2CorePath, v2AssetsPath, runAsRoot, logLevel, httpSetting, socksSetting, configs))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,14 +78,17 @@ namespace Qv2ray
|
|||||||
{
|
{
|
||||||
return dir->entryList(QStringList() << "*" << "*.*", QDir::Hidden | QDir::Files);
|
return dir->entryList(QStringList() << "*" << "*.*", QDir::Hidden | QDir::Files);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckFile(QDir *dir, QString fileName)
|
bool CheckFile(QDir *dir, QString fileName)
|
||||||
{
|
{
|
||||||
return GetFileList(dir).indexOf(fileName) >= 0;
|
return GetFileList(dir).indexOf(fileName) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QvMessageBox(QWidget *parent, QString title, QString text)
|
void QvMessageBox(QWidget *parent, QString title, QString text)
|
||||||
{
|
{
|
||||||
QMessageBox::warning(parent, title, text, QMessageBox::Ok | QMessageBox::Default, 0);
|
QMessageBox::warning(parent, title, text, QMessageBox::Ok | QMessageBox::Default, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
QTranslator *getTranslator(QString lang)
|
QTranslator *getTranslator(QString lang)
|
||||||
{
|
{
|
||||||
QTranslator *translator = new QTranslator();
|
QTranslator *translator = new QTranslator();
|
||||||
|
11
src/main.cpp
11
src/main.cpp
@ -16,17 +16,20 @@ bool initializeQv()
|
|||||||
/// Qv2ray Config Path and ends with "/"
|
/// Qv2ray Config Path and ends with "/"
|
||||||
QString configPath = "";
|
QString configPath = "";
|
||||||
QString exeDefaultPath = "";
|
QString exeDefaultPath = "";
|
||||||
|
QString v2AssetsPath = "";
|
||||||
#if defined(__WIN32) || defined(__APPLE__)
|
#if defined(__WIN32) || defined(__APPLE__)
|
||||||
// For Windows and MacOS, there's no such 'installation' of a software
|
// For Windows and MacOS, there's no such 'installation' of a software
|
||||||
// package, So as what ShadowSocks and v2rayX does, save config files next to
|
// package, So as what ShadowSocks and v2rayX does, save config files next to
|
||||||
// the executable.
|
// the executable.
|
||||||
configPath = "./qv2ray.conf.d";
|
configPath = "./qv2ray.d";
|
||||||
exeDefaultPath = "./v2ray";
|
exeDefaultPath = "./qv2ray.d/v2ray";
|
||||||
|
v2AssetsPath = "./qv2ray.d";
|
||||||
#else
|
#else
|
||||||
// However, for linux, this software can be and/or will be provided as a
|
// However, for linux, this software can be and/or will be provided as a
|
||||||
// package and install to whatever /usr/bin or /usr/local/bin or even /opt/
|
// package and install to whatever /usr/bin or /usr/local/bin or even /opt/
|
||||||
// Thus we save config files in the user's home directory.
|
// Thus we save config files in the user's home directory.
|
||||||
configPath = QDir::homePath() + "/.qv2ray/";
|
configPath = QDir::homePath() + "/.qv2ray";
|
||||||
|
v2AssetsPath = "/etc/v2ray";
|
||||||
exeDefaultPath = "/bin/v2ray";
|
exeDefaultPath = "/bin/v2ray";
|
||||||
#endif
|
#endif
|
||||||
SetConfigDirPath(configPath);
|
SetConfigDirPath(configPath);
|
||||||
@ -60,7 +63,7 @@ bool initializeQv()
|
|||||||
// These below genenrated very basic global config.
|
// These below genenrated very basic global config.
|
||||||
QvInbondSetting inHttp = QvInbondSetting(true, "127.0.0.1", 8080);
|
QvInbondSetting inHttp = QvInbondSetting(true, "127.0.0.1", 8080);
|
||||||
QvInbondSetting inSocks = QvInbondSetting(true, "127.0.0.1", 1080);
|
QvInbondSetting inSocks = QvInbondSetting(true, "127.0.0.1", 1080);
|
||||||
Qv2Config conf = Qv2Config("zh-CN", exeDefaultPath.toStdString(), "info", inHttp, inSocks);
|
Qv2Config conf = Qv2Config("zh-CN", exeDefaultPath.toStdString(), v2AssetsPath.toStdString(), 2, inHttp, inSocks);
|
||||||
//
|
//
|
||||||
// Save initial config.
|
// Save initial config.
|
||||||
SetGlobalConfig(conf);
|
SetGlobalConfig(conf);
|
||||||
|
@ -25,84 +25,56 @@ ImportConfigWindow::~ImportConfigWindow()
|
|||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImportConfigWindow::on_pushButton_clicked()
|
void ImportConfigWindow::on_importSourceCombo_currentIndexChanged(int index)
|
||||||
|
{
|
||||||
|
ui->stackedWidget->setCurrentIndex(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImportConfigWindow::on_selectFileBtn_clicked()
|
||||||
{
|
{
|
||||||
QString dir = QFileDialog::getOpenFileName(this, tr("OpenConfigFile"), "~/");
|
QString dir = QFileDialog::getOpenFileName(this, tr("OpenConfigFile"), "~/");
|
||||||
ui->fileLineTxt->setText(dir);
|
ui->fileLineTxt->setText(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImportConfigWindow::savefromFile(QString path, QString alias)
|
void ImportConfigWindow::on_buttonBox_clicked(QAbstractButton *button)
|
||||||
{
|
{
|
||||||
Q_UNUSED(path)
|
QString alias = ui->nameTxt->text();
|
||||||
Q_UNUSED(alias)
|
QJsonObject config;
|
||||||
QFile configFile(path);
|
|
||||||
|
|
||||||
if (!configFile.open(QIODevice::ReadOnly)) {
|
if (ui->importSourceCombo->currentIndex() == 0) { // From File...
|
||||||
QvMessageBox(this, tr("ImportConfig"), tr("CannotOpenFile"));
|
bool overrideInBound = ui->keepInboundCheckBox->isChecked();
|
||||||
qDebug() << "ImportConfig::CannotOpenFile";
|
|
||||||
|
if (!Qv2Instance::VerifyVConfigFile(ui->fileLineTxt->text())) {
|
||||||
|
QvMessageBox(this, tr("#InvalidConfigFile"), tr("ConfigFileCheckFailed"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray allData = configFile.readAll();
|
|
||||||
configFile.close();
|
|
||||||
QJsonDocument v2conf(QJsonDocument::fromJson(allData));
|
|
||||||
QJsonObject rootobj = v2conf.object();
|
|
||||||
QJsonObject outbound;
|
|
||||||
|
|
||||||
if (rootobj.contains("outbounds")) {
|
|
||||||
outbound = rootobj.value("outbounds").toArray().first().toObject();
|
|
||||||
} else {
|
|
||||||
outbound = rootobj.value("outbound").toObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!QFile::copy(path, "newFile")) {
|
|
||||||
QvMessageBox(this, tr("ImportConfig"), tr("CannotCopyCustomConfig"));
|
|
||||||
qDebug() << "ImportConfig::CannotCopyCustomConfig";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImportConfigWindow::on_buttonBox_accepted()
|
|
||||||
{
|
|
||||||
QString alias = ui->nameTxt->text();
|
|
||||||
|
|
||||||
if (ui->importSourceCombo->currentIndex() == 0) { // From File...
|
|
||||||
bool overrideInBound = ui->useCurrentSettingRidBtn->isChecked();
|
|
||||||
on_verifyFileBtn_clicked();
|
|
||||||
QString path = ui->fileLineTxt->text();
|
QString path = ui->fileLineTxt->text();
|
||||||
savefromFile(path, alias);
|
config = ConvertConfigFromFile(path, overrideInBound);
|
||||||
// !!! TODO
|
|
||||||
} else {
|
} else {
|
||||||
on_verifyVMessBtn_clicked();
|
QString vmess = ui->vmessConnectionStringTxt->toPlainText();
|
||||||
auto config = ConvertOutboundFromVMessString(ui->vmessConnectionStringTxt->toPlainText());
|
int result = VerifyVMessProtocolString(vmess);
|
||||||
|
|
||||||
|
if (result == 0) {
|
||||||
|
//QvMessageBox(this, tr("#VMessCheck"), tr("#AbleToImportConfig"));
|
||||||
|
} else if (result == -1) {
|
||||||
|
QvMessageBox(this, tr("#VMessCheck"), tr("#NotValidVMessProtocolString"));
|
||||||
|
done(0);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
QvMessageBox(this, tr("#VMessCheck"), tr("#INTERNAL_ERROR"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
config = ConvertConfigFromVMessString(ui->vmessConnectionStringTxt->toPlainText());
|
||||||
|
//
|
||||||
alias = alias != "" ? alias : config["QV2RAY_ALIAS"].toString();
|
alias = alias != "" ? alias : config["QV2RAY_ALIAS"].toString();
|
||||||
config.remove("QV2RAY_ALIAS");
|
config.remove("QV2RAY_ALIAS");
|
||||||
|
}
|
||||||
|
|
||||||
Qv2Config conf = GetGlobalConfig();
|
Qv2Config conf = GetGlobalConfig();
|
||||||
conf.configs.push_back(alias.toStdString());
|
conf.configs.push_back(alias.toStdString());
|
||||||
SetGlobalConfig(conf);
|
SetGlobalConfig(conf);
|
||||||
SaveConnectionConfig(config, &alias);
|
SaveConnectionConfig(config, &alias);
|
||||||
emit s_reload_config();
|
emit s_reload_config();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImportConfigWindow::on_verifyVMessBtn_clicked()
|
|
||||||
{
|
|
||||||
QString vmess = ui->vmessConnectionStringTxt->toPlainText();
|
|
||||||
int result = VerifyVMessProtocolString(vmess);
|
|
||||||
|
|
||||||
if (result == 0) {
|
|
||||||
QvMessageBox(this, tr("#VMessCheck"), tr("#AbleToImportConfig"));
|
|
||||||
} else if (result == -1) {
|
|
||||||
QvMessageBox(this, tr("#VMessCheck"), tr("#NotValidVMessProtocolString"));
|
|
||||||
} else {
|
|
||||||
QvMessageBox(this, tr("#VMessCheck"), tr("#INTERNAL_ERROR"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImportConfigWindow::on_verifyFileBtn_clicked()
|
|
||||||
{
|
|
||||||
if (!Qv2Instance::checkConfigFile(ui->fileLineTxt->text())) {
|
|
||||||
QvMessageBox(this, tr("#InvalidConfigFile"), tr("ConfigFileCheckFailed"));
|
|
||||||
} else {
|
|
||||||
QvMessageBox(this, tr("#VConfigFileCheckPassed"), tr("#AbleToImportConfig"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,18 +15,19 @@ class ImportConfigWindow : public QDialog
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ImportConfigWindow(QWidget *parent = nullptr);
|
explicit ImportConfigWindow(QWidget *parent = nullptr);
|
||||||
void savefromFile(QString path, QString alias);
|
|
||||||
~ImportConfigWindow();
|
~ImportConfigWindow();
|
||||||
signals:
|
signals:
|
||||||
void s_reload_config();
|
void s_reload_config();
|
||||||
private slots:
|
private slots:
|
||||||
void on_pushButton_clicked();
|
void on_importSourceCombo_currentIndexChanged(int index);
|
||||||
void on_buttonBox_accepted();
|
|
||||||
void on_verifyVMessBtn_clicked();
|
void on_selectFileBtn_clicked();
|
||||||
void on_verifyFileBtn_clicked();
|
|
||||||
|
void on_buttonBox_clicked(QAbstractButton *button);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::ImportConfigWindow *ui;
|
Ui::ImportConfigWindow *ui;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // IMPORTCONF_H
|
#endif // IMPORTCONF_H
|
||||||
|
@ -6,86 +6,85 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>650</width>
|
<width>370</width>
|
||||||
<height>350</height>
|
<height>420</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>650</width>
|
<width>370</width>
|
||||||
<height>350</height>
|
<height>420</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>370</width>
|
||||||
|
<height>420</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Import file</string>
|
<string>Import file</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0" columnstretch="1,1">
|
<property name="sizeGripEnabled">
|
||||||
<item row="0" column="0" colspan="2">
|
<bool>false</bool>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,6">
|
</property>
|
||||||
|
<property name="modal">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
<item>
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout_2">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="aliasLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>#Name</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="nameTxt"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>#ImportFrom</string>
|
<string>#ImportFrom</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QComboBox" name="importSourceCombo">
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Existing File</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>VMess Connection String</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QGroupBox" name="fromVMessGroupBox">
|
<widget class="QComboBox" name="importSourceCombo">
|
||||||
<property name="title">
|
<property name="sizePolicy">
|
||||||
<string>#From VMess Connection String</string>
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>#VMess Connection String</string>
|
<string>#ExistingFile</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTextEdit" name="vmessConnectionStringTxt"/>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="verifyVMessBtn">
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Verify</string>
|
<string>#VMessConnectionString</string>
|
||||||
</property>
|
</property>
|
||||||
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item>
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
<widget class="QGroupBox" name="groupBox">
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QGroupBox" name="fromFileGroupBox">
|
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>#FromFile</string>
|
<string>#Import</string>
|
||||||
</property>
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QStackedWidget" name="stackedWidget">
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="page">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QFormLayout" name="formLayout">
|
<layout class="QFormLayout" name="formLayout">
|
||||||
@ -115,65 +114,57 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="aliasLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>#Name</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QLineEdit" name="nameTxt"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QLabel" name="label_2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>#Inbound</string>
|
<string>#Inbound</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="1" column="1">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<widget class="QCheckBox" name="keepInboundCheckBox">
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="useCurrentSettingRidBtn">
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>#UseCurrent</string>
|
<string>#KeepImportedInbounds</string>
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="useImportedRidBtn">
|
|
||||||
<property name="text">
|
|
||||||
<string>#UseImported</string>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</widget>
|
||||||
|
<widget class="QWidget" name="page_2">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="verifyFileBtn">
|
<widget class="QLabel" name="label_3">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Verify</string>
|
<string>#VMess Connection String</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTextEdit" name="vmessConnectionStringTxt"/>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Discard|QDialogButtonBox::Save</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>importSourceCombo</tabstop>
|
|
||||||
<tabstop>fileLineTxt</tabstop>
|
<tabstop>fileLineTxt</tabstop>
|
||||||
<tabstop>selectFileBtn</tabstop>
|
<tabstop>selectFileBtn</tabstop>
|
||||||
<tabstop>nameTxt</tabstop>
|
|
||||||
<tabstop>useCurrentSettingRidBtn</tabstop>
|
|
||||||
<tabstop>useImportedRidBtn</tabstop>
|
|
||||||
<tabstop>vmessConnectionStringTxt</tabstop>
|
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections>
|
||||||
|
@ -101,7 +101,7 @@ void MainWindow::UpdateLog()
|
|||||||
void MainWindow::on_startButton_clicked()
|
void MainWindow::on_startButton_clicked()
|
||||||
{
|
{
|
||||||
ui->logText->clear();
|
ui->logText->clear();
|
||||||
bool startFlag = this->vinstance->start();
|
bool startFlag = this->vinstance->Start();
|
||||||
trayMenu->actions()[2]->setEnabled(!startFlag);
|
trayMenu->actions()[2]->setEnabled(!startFlag);
|
||||||
trayMenu->actions()[3]->setEnabled(startFlag);
|
trayMenu->actions()[3]->setEnabled(startFlag);
|
||||||
trayMenu->actions()[4]->setEnabled(startFlag);
|
trayMenu->actions()[4]->setEnabled(startFlag);
|
||||||
@ -109,7 +109,7 @@ void MainWindow::on_startButton_clicked()
|
|||||||
|
|
||||||
void MainWindow::on_stopButton_clicked()
|
void MainWindow::on_stopButton_clicked()
|
||||||
{
|
{
|
||||||
this->vinstance->stop();
|
this->vinstance->Stop();
|
||||||
ui->logText->clear();
|
ui->logText->clear();
|
||||||
trayMenu->actions()[2]->setEnabled(true);
|
trayMenu->actions()[2]->setEnabled(true);
|
||||||
trayMenu->actions()[3]->setEnabled(false);
|
trayMenu->actions()[3]->setEnabled(false);
|
||||||
|
@ -14,7 +14,7 @@ PrefrencesWindow::PrefrencesWindow(QWidget *parent) : QDialog(parent),
|
|||||||
CurrentConfig = GetGlobalConfig();
|
CurrentConfig = GetGlobalConfig();
|
||||||
ui->languageComboBox->setCurrentText(QString::fromStdString(CurrentConfig.language));
|
ui->languageComboBox->setCurrentText(QString::fromStdString(CurrentConfig.language));
|
||||||
ui->runAsRootCheckBox->setChecked(CurrentConfig.runAsRoot);
|
ui->runAsRootCheckBox->setChecked(CurrentConfig.runAsRoot);
|
||||||
ui->logLevelCheckBox->setCurrentText(QString::fromStdString(CurrentConfig.logLevel));
|
ui->logLevelComboBox->setCurrentIndex(CurrentConfig.logLevel);
|
||||||
//
|
//
|
||||||
ui->httpCB->setChecked(CurrentConfig.httpSetting.enabled);
|
ui->httpCB->setChecked(CurrentConfig.httpSetting.enabled);
|
||||||
ui->httpPortLE->setText(QString::fromStdString(to_string(CurrentConfig.httpSetting.port)));
|
ui->httpPortLE->setText(QString::fromStdString(to_string(CurrentConfig.httpSetting.port)));
|
||||||
@ -29,7 +29,7 @@ PrefrencesWindow::PrefrencesWindow(QWidget *parent) : QDialog(parent),
|
|||||||
ui->socksAuthUsernameTxt->setText(QString::fromStdString(CurrentConfig.socksSetting.authUsername));
|
ui->socksAuthUsernameTxt->setText(QString::fromStdString(CurrentConfig.socksSetting.authUsername));
|
||||||
ui->socksAuthPasswordTxt->setText(QString::fromStdString(CurrentConfig.socksSetting.authPassword));
|
ui->socksAuthPasswordTxt->setText(QString::fromStdString(CurrentConfig.socksSetting.authPassword));
|
||||||
//
|
//
|
||||||
ui->vCoreExePathTxt->setText(QString::fromStdString(CurrentConfig.v2Path));
|
ui->vCoreExePathTxt->setText(QString::fromStdString(CurrentConfig.v2CorePath));
|
||||||
//
|
//
|
||||||
ui->httpPortLE->setValidator(new QIntValidator());
|
ui->httpPortLE->setValidator(new QIntValidator());
|
||||||
ui->socksPortLE->setValidator(new QIntValidator());
|
ui->socksPortLE->setValidator(new QIntValidator());
|
||||||
@ -98,7 +98,7 @@ void PrefrencesWindow::on_runAsRootCheckBox_stateChanged(int arg1)
|
|||||||
{
|
{
|
||||||
Q_UNUSED(arg1)
|
Q_UNUSED(arg1)
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
showWarnMessageBox(this, tr("Prefrences"), tr("RunAsRootNotOnWindows"));
|
QvMessageBox(this, tr("Prefrences"), tr("RunAsRootNotOnWindows"));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QComboBox" name="logLevelCheckBox">
|
<widget class="QComboBox" name="logLevelComboBox">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@ -336,7 +336,7 @@
|
|||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>languageComboBox</tabstop>
|
<tabstop>languageComboBox</tabstop>
|
||||||
<tabstop>runAsRootCheckBox</tabstop>
|
<tabstop>runAsRootCheckBox</tabstop>
|
||||||
<tabstop>logLevelCheckBox</tabstop>
|
<tabstop>logLevelComboBox</tabstop>
|
||||||
<tabstop>muxEnabledCB</tabstop>
|
<tabstop>muxEnabledCB</tabstop>
|
||||||
<tabstop>muxConcurrencyTxt</tabstop>
|
<tabstop>muxConcurrencyTxt</tabstop>
|
||||||
<tabstop>httpCB</tabstop>
|
<tabstop>httpCB</tabstop>
|
||||||
|
@ -262,135 +262,91 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>ImportConfigWindow</name>
|
<name>ImportConfigWindow</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.ui" line="20"/>
|
<location filename="../src/w_ImportConfig.ui" line="26"/>
|
||||||
<source>Import file</source>
|
<source>Import file</source>
|
||||||
<translation>Import file</translation>
|
<translation>Import file</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.ui" line="28"/>
|
<location filename="../src/w_ImportConfig.ui" line="50"/>
|
||||||
<source>#ImportFrom</source>
|
<source>#ImportFrom</source>
|
||||||
<translation>Import From</translation>
|
<translation>Import From</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.ui" line="36"/>
|
<location filename="../src/w_ImportConfig.ui" line="94"/>
|
||||||
<source>Existing File</source>
|
|
||||||
<translation>Existing File</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.ui" line="41"/>
|
|
||||||
<source>VMess Connection String</source>
|
|
||||||
<translation>VMess Connection String</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.ui" line="67"/>
|
|
||||||
<location filename="../src/w_ImportConfig.ui" line="160"/>
|
|
||||||
<source>Verify</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.ui" line="87"/>
|
|
||||||
<source>#FromFile</source>
|
|
||||||
<translation>From file</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.ui" line="95"/>
|
|
||||||
<source>#Path</source>
|
<source>#Path</source>
|
||||||
<translation>Path</translation>
|
<translation>Path</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.ui" line="111"/>
|
<location filename="../src/w_ImportConfig.ui" line="110"/>
|
||||||
<source>#SelectFile</source>
|
<source>#SelectFile</source>
|
||||||
<translation>Select File</translation>
|
<translation>Select File</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.ui" line="120"/>
|
<location filename="../src/w_ImportConfig.ui" line="40"/>
|
||||||
<source>#Name</source>
|
<source>#Name</source>
|
||||||
<translation>Name</translation>
|
<translation>Name</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.ui" line="130"/>
|
<location filename="../src/w_ImportConfig.ui" line="64"/>
|
||||||
|
<source>#ExistingFile</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/w_ImportConfig.ui" line="69"/>
|
||||||
|
<source>#VMessConnectionString</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/w_ImportConfig.ui" line="79"/>
|
||||||
|
<source>#Import</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/w_ImportConfig.ui" line="119"/>
|
||||||
<source>#Inbound</source>
|
<source>#Inbound</source>
|
||||||
<translation>Inbound Settings</translation>
|
<translation>Inbound Settings</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/w_ImportConfig.ui" line="126"/>
|
||||||
|
<source>#KeepImportedInbounds</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.ui" line="139"/>
|
<location filename="../src/w_ImportConfig.ui" line="139"/>
|
||||||
<source>#UseCurrent</source>
|
|
||||||
<translation>Use Current Settings</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.ui" line="149"/>
|
|
||||||
<source>#UseImported</source>
|
|
||||||
<translation>Use Imported Inbound Settings</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.ui" line="51"/>
|
|
||||||
<source>#From VMess Connection String</source>
|
|
||||||
<translation>From VMess Connection String</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.ui" line="57"/>
|
|
||||||
<source>#VMess Connection String</source>
|
<source>#VMess Connection String</source>
|
||||||
<translation>VMess Connection String</translation>
|
<translation>VMess Connection String</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="30"/>
|
<location filename="../src/w_ImportConfig.cpp" line="35"/>
|
||||||
<source>OpenConfigFile</source>
|
<source>OpenConfigFile</source>
|
||||||
<translation type="unfinished">Open Config File</translation>
|
<translation type="unfinished">Open Config File</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="41"/>
|
<location filename="../src/w_ImportConfig.cpp" line="61"/>
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="59"/>
|
|
||||||
<source>ImportConfig</source>
|
|
||||||
<translation type="unfinished">Import Config</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="41"/>
|
|
||||||
<source>CannotOpenFile</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="59"/>
|
|
||||||
<source>CannotCopyCustomConfig</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="95"/>
|
|
||||||
<source>#NotValidVMessProtocolString</source>
|
<source>#NotValidVMessProtocolString</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="93"/>
|
<location filename="../src/w_ImportConfig.cpp" line="61"/>
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="106"/>
|
<location filename="../src/w_ImportConfig.cpp" line="65"/>
|
||||||
<source>#AbleToImportConfig</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="93"/>
|
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="95"/>
|
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="97"/>
|
|
||||||
<source>#VMessCheck</source>
|
<source>#VMessCheck</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="97"/>
|
<location filename="../src/w_ImportConfig.cpp" line="65"/>
|
||||||
<source>#INTERNAL_ERROR</source>
|
<source>#INTERNAL_ERROR</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="104"/>
|
<location filename="../src/w_ImportConfig.cpp" line="48"/>
|
||||||
<source>#InvalidConfigFile</source>
|
<source>#InvalidConfigFile</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="104"/>
|
<location filename="../src/w_ImportConfig.cpp" line="48"/>
|
||||||
<source>ConfigFileCheckFailed</source>
|
<source>ConfigFileCheckFailed</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="106"/>
|
|
||||||
<source>#VConfigFileCheckPassed</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>MainWindow</name>
|
<name>MainWindow</name>
|
||||||
@ -666,27 +622,27 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>QObject</name>
|
<name>QObject</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/main.cpp" line="89"/>
|
<location filename="../src/main.cpp" line="92"/>
|
||||||
<source>AnotherInstanceRunning</source>
|
<source>AnotherInstanceRunning</source>
|
||||||
<translation>Another instance is already running</translation>
|
<translation>Another instance is already running</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/main.cpp" line="89"/>
|
<location filename="../src/main.cpp" line="92"/>
|
||||||
<source>Qv2ray</source>
|
<source>Qv2ray</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/QvCoreInteractions.cpp" line="45"/>
|
<location filename="../src/QvCoreInteractions.cpp" line="48"/>
|
||||||
<source>CoreNotFound</source>
|
<source>CoreNotFound</source>
|
||||||
<translation>Core files are not found</translation>
|
<translation>Core files are not found</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/QvCoreInteractions.cpp" line="45"/>
|
<location filename="../src/QvCoreInteractions.cpp" line="48"/>
|
||||||
<source>CoreFileNotFoundExplainationAt:</source>
|
<source>CoreFileNotFoundExplainationAt:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/QvCoreInteractions.cpp" line="24"/>
|
<location filename="../src/QvCoreInteractions.cpp" line="27"/>
|
||||||
<source>ConfigurationError</source>
|
<source>ConfigurationError</source>
|
||||||
<translation>Configuration Error</translation>
|
<translation>Configuration Error</translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -262,135 +262,91 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>ImportConfigWindow</name>
|
<name>ImportConfigWindow</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.ui" line="20"/>
|
<location filename="../src/w_ImportConfig.ui" line="26"/>
|
||||||
<source>Import file</source>
|
<source>Import file</source>
|
||||||
<translation>导入文件</translation>
|
<translation>导入文件</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.ui" line="28"/>
|
<location filename="../src/w_ImportConfig.ui" line="50"/>
|
||||||
<source>#ImportFrom</source>
|
<source>#ImportFrom</source>
|
||||||
<translation>导入源</translation>
|
<translation>导入源</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.ui" line="36"/>
|
<location filename="../src/w_ImportConfig.ui" line="94"/>
|
||||||
<source>Existing File</source>
|
|
||||||
<translation>现有文件</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.ui" line="41"/>
|
|
||||||
<source>VMess Connection String</source>
|
|
||||||
<translation>VMess 连接字符串</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.ui" line="67"/>
|
|
||||||
<location filename="../src/w_ImportConfig.ui" line="160"/>
|
|
||||||
<source>Verify</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.ui" line="87"/>
|
|
||||||
<source>#FromFile</source>
|
|
||||||
<translation>从文件</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.ui" line="95"/>
|
|
||||||
<source>#Path</source>
|
<source>#Path</source>
|
||||||
<translation>路径</translation>
|
<translation>路径</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.ui" line="111"/>
|
<location filename="../src/w_ImportConfig.ui" line="110"/>
|
||||||
<source>#SelectFile</source>
|
<source>#SelectFile</source>
|
||||||
<translation>选择文件</translation>
|
<translation>选择文件</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.ui" line="120"/>
|
<location filename="../src/w_ImportConfig.ui" line="40"/>
|
||||||
<source>#Name</source>
|
<source>#Name</source>
|
||||||
<translation>名称</translation>
|
<translation>名称</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.ui" line="130"/>
|
<location filename="../src/w_ImportConfig.ui" line="64"/>
|
||||||
|
<source>#ExistingFile</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/w_ImportConfig.ui" line="69"/>
|
||||||
|
<source>#VMessConnectionString</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/w_ImportConfig.ui" line="79"/>
|
||||||
|
<source>#Import</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/w_ImportConfig.ui" line="119"/>
|
||||||
<source>#Inbound</source>
|
<source>#Inbound</source>
|
||||||
<translation>入站设置</translation>
|
<translation>入站设置</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../src/w_ImportConfig.ui" line="126"/>
|
||||||
|
<source>#KeepImportedInbounds</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.ui" line="139"/>
|
<location filename="../src/w_ImportConfig.ui" line="139"/>
|
||||||
<source>#UseCurrent</source>
|
|
||||||
<translation>使用现有设置</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.ui" line="149"/>
|
|
||||||
<source>#UseImported</source>
|
|
||||||
<translation>使用导入的设置</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.ui" line="51"/>
|
|
||||||
<source>#From VMess Connection String</source>
|
|
||||||
<translation>从 VMess 连接字符串</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.ui" line="57"/>
|
|
||||||
<source>#VMess Connection String</source>
|
<source>#VMess Connection String</source>
|
||||||
<translation>VMess 连接字符串</translation>
|
<translation>VMess 连接字符串</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="30"/>
|
<location filename="../src/w_ImportConfig.cpp" line="35"/>
|
||||||
<source>OpenConfigFile</source>
|
<source>OpenConfigFile</source>
|
||||||
<translation type="unfinished">打开配置文件</translation>
|
<translation type="unfinished">打开配置文件</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="41"/>
|
<location filename="../src/w_ImportConfig.cpp" line="61"/>
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="59"/>
|
|
||||||
<source>ImportConfig</source>
|
|
||||||
<translation type="unfinished">导入配置</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="41"/>
|
|
||||||
<source>CannotOpenFile</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="59"/>
|
|
||||||
<source>CannotCopyCustomConfig</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="95"/>
|
|
||||||
<source>#NotValidVMessProtocolString</source>
|
<source>#NotValidVMessProtocolString</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="93"/>
|
<location filename="../src/w_ImportConfig.cpp" line="61"/>
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="106"/>
|
<location filename="../src/w_ImportConfig.cpp" line="65"/>
|
||||||
<source>#AbleToImportConfig</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="93"/>
|
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="95"/>
|
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="97"/>
|
|
||||||
<source>#VMessCheck</source>
|
<source>#VMessCheck</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="97"/>
|
<location filename="../src/w_ImportConfig.cpp" line="65"/>
|
||||||
<source>#INTERNAL_ERROR</source>
|
<source>#INTERNAL_ERROR</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="104"/>
|
<location filename="../src/w_ImportConfig.cpp" line="48"/>
|
||||||
<source>#InvalidConfigFile</source>
|
<source>#InvalidConfigFile</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="104"/>
|
<location filename="../src/w_ImportConfig.cpp" line="48"/>
|
||||||
<source>ConfigFileCheckFailed</source>
|
<source>ConfigFileCheckFailed</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
|
||||||
<location filename="../src/w_ImportConfig.cpp" line="106"/>
|
|
||||||
<source>#VConfigFileCheckPassed</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>MainWindow</name>
|
<name>MainWindow</name>
|
||||||
@ -666,27 +622,27 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>QObject</name>
|
<name>QObject</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/main.cpp" line="89"/>
|
<location filename="../src/main.cpp" line="92"/>
|
||||||
<source>AnotherInstanceRunning</source>
|
<source>AnotherInstanceRunning</source>
|
||||||
<translation>另一个实例正在运行</translation>
|
<translation>另一个实例正在运行</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/main.cpp" line="89"/>
|
<location filename="../src/main.cpp" line="92"/>
|
||||||
<source>Qv2ray</source>
|
<source>Qv2ray</source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/QvCoreInteractions.cpp" line="45"/>
|
<location filename="../src/QvCoreInteractions.cpp" line="48"/>
|
||||||
<source>CoreNotFound</source>
|
<source>CoreNotFound</source>
|
||||||
<translation>核心文件未找到</translation>
|
<translation>核心文件未找到</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/QvCoreInteractions.cpp" line="45"/>
|
<location filename="../src/QvCoreInteractions.cpp" line="48"/>
|
||||||
<source>CoreFileNotFoundExplainationAt:</source>
|
<source>CoreFileNotFoundExplainationAt:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../src/QvCoreInteractions.cpp" line="24"/>
|
<location filename="../src/QvCoreInteractions.cpp" line="27"/>
|
||||||
<source>ConfigurationError</source>
|
<source>ConfigurationError</source>
|
||||||
<translation>配置出错</translation>
|
<translation>配置出错</translation>
|
||||||
</message>
|
</message>
|
||||||
|
Loading…
Reference in New Issue
Block a user