[Added][Changed][UI] Added SOCKS, connection renaming, connect selected, and a new tiny log module. Redesigned MainWindow UI

Former-commit-id: 5dfc667a9c
This commit is contained in:
Leroy.H.Y 2019-08-17 00:23:18 +08:00
parent 8efae6b7ed
commit 5db9f5d78d
27 changed files with 1247 additions and 815 deletions

View File

@ -40,12 +40,13 @@ SOURCES += \
HEADERS += \
ignored_cpp_structs.hpp \
src/QJsonObjectInsertMacros.h \
src/Qv2rayBase.h \
src/QvCoreConfigObjects.h \
src/QvCoreConfigOperations.h \
src/QvCoreInteractions.h \
src/QvGUIConfigObjects.h \
src/QvHTTPRequestHelper.h \
src/QvRunguard.h \
src/QvTinyLog.h \
src/QvUtils.h \
src/w_MainWindow.h \
src/w_ConnectionEditWindow.h \

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -3,5 +3,9 @@
<file>translations/zh-CN.qm</file>
<file>translations/en-US.qm</file>
<file>icons/Qv2ray.ico</file>
<file>icons/add_connection_btn.png</file>
<file>icons/import_connection_btn.png</file>
<file>icons/remove_connection_btn.png</file>
<file>icons/edit_connection_btn.png</file>
</qresource>
</RCC>

View File

@ -2,14 +2,11 @@
#define HCONFIGOBJECTS_H
#include <QtCore>
#include <iostream>
#include "QvTinyLog.h"
#include "QvCoreConfigObjects.h"
using namespace std;
#define LOG(arg) cout << arg << endl;
#define QV2RAY_VERSION 1
#define QV2RAY_VERSION_STRING "v1.3.0"
#define QV2RAY_VERSION_STRING "v1.3.2"
#define QV2RAY_CONFIG_VERSION "1.1"
#define QV2RAY_CONFIG_PATH (Qv2ray::Utils::GetConfigDirPath() + "/")
#define QV2RAY_GUI_CONFIG_PATH (QV2RAY_CONFIG_PATH + "Qv2ray.conf")
#define QV2RAY_GENERATED_CONFIG_FILE_PATH (QV2RAY_CONFIG_PATH + "generated/config.gen.json")
@ -22,14 +19,16 @@ using namespace std;
// GUI TOOLS
#define RED(obj) \
auto p = ui->obj->palette(); \
p.setColor(QPalette::Text, Qt::red); \
ui->obj->setPalette(p);
auto _p = ui->obj->palette(); \
_p.setColor(QPalette::Text, Qt::red); \
ui->obj->setPalette(_p);
#define BLACK(obj) \
auto p = ui->obj->palette(); \
p.setColor(QPalette::Text, Qt::black); \
ui->obj->setPalette(p);
auto _p = ui->obj->palette(); \
_p.setColor(QPalette::Text, Qt::black); \
ui->obj->setPalette(_p);
#define QSTRING(std_string) QString::fromStdString(std_string)
#ifdef __WIN32
#define NEWLINE "\r\n"
@ -66,7 +65,7 @@ namespace Qv2ray
};
struct Qv2Config {
string v = "1.1";
string config_version;
bool runAsRoot;
int logLevel;
//
@ -86,7 +85,7 @@ namespace Qv2ray
list<string> configs;
map<string, string> subscribes;
MuxObject mux;
Qv2Config(): runAsRoot(false), logLevel(), proxyDefault(), proxyCN(), withLocalDNS(), inBoundSettings(), configs(), subscribes(), mux() { }
Qv2Config(): config_version(QV2RAY_CONFIG_VERSION), runAsRoot(false), logLevel(), proxyDefault(), proxyCN(), withLocalDNS(), inBoundSettings(), configs(), subscribes(), mux() { }
Qv2Config(string lang, string exePath, string assetsPath, int log, QvBasicInboundSetting _inBoundSettings): Qv2Config()
{
ignoredVersion = "";
@ -105,7 +104,7 @@ namespace Qv2ray
proxyDefault = true;
withLocalDNS = true;
}
XTOSTRUCT(O(v, runAsRoot, logLevel, language, autoStartConfig, ignoredVersion, v2CorePath, v2AssetsPath, proxyDefault, proxyCN, withLocalDNS, dnsList, inBoundSettings, mux, configs, subscribes))
XTOSTRUCT(O(config_version, runAsRoot, logLevel, language, autoStartConfig, ignoredVersion, v2CorePath, v2AssetsPath, proxyDefault, proxyCN, withLocalDNS, dnsList, inBoundSettings, mux, configs, subscribes))
};
}
}

View File

@ -2,13 +2,15 @@
#include <string>
#include <x2struct/x2struct.hpp>
using namespace x2struct;
#ifndef V2CONFIG_H
#define V2CONFIG_H
using namespace x2struct;
using namespace std;
/*------------------------------------------------------------------------------------------------------------*/
/* ----------------------------------------- * ---------------------
* --------------------- * ----------------------------------------- */
namespace Qv2ray
{
@ -18,29 +20,31 @@ namespace Qv2ray
string v, ps, add, port, id, aid, net, type, host, path, tls;
XTOSTRUCT(O(v, ps, add, port, id, aid, net, type, host, path, tls))
};
/// Used in config generation
//
// Used in config generation
struct AccountObject {
string user;
string pass;
XTOSTRUCT(O(user, pass))
};
//
//
struct ApiObject {
string tag = "api";
string tag;
list<string> services;
ApiObject() : tag(), services() {}
ApiObject() : tag("api"), services() {}
XTOSTRUCT(O(tag, services))
};
//
//
struct SystemPolicyObject {
bool statsInboundUplink;
bool statsInboundDownlink;
SystemPolicyObject() : statsInboundUplink(), statsInboundDownlink() {}
XTOSTRUCT(O(statsInboundUplink, statsInboundDownlink))
};
//
//
struct LevelPolicyObject {
int handshake;
int connIdle;
@ -52,33 +56,38 @@ namespace Qv2ray
LevelPolicyObject(): handshake(), connIdle(), uplinkOnly(), downlinkOnly(), statsUserUplink(), statsUserDownlink(), bufferSize() {}
XTOSTRUCT(O(handshake, connIdle, uplinkOnly, downlinkOnly, statsUserUplink, statsUserDownlink, bufferSize))
};
//
//
struct PolicyObject {
map<string, LevelPolicyObject> level;
list<SystemPolicyObject> system;
PolicyObject(): level(), system() {}
XTOSTRUCT(O(level, system))
};
//
//
namespace TransferSettingObjects
{
struct HTTPRequestObject {
string version ;
string method ;
string version;
string method;
list<string> path;
map<string, list<string>> headers;
HTTPRequestObject(): version("1.1"), method("GET"), path(), headers() {}
XTOSTRUCT(O(version, method, path, headers))
};
//
//
struct HTTPResponseObject {
string version;
string status ;
string reason ;
string status;
string reason;
map<string, list<string>> headers;
HTTPResponseObject(): version("1.1"), status("200"), reason("OK"), headers() {}
XTOSTRUCT(O(version, status, reason, headers))
};
//
//
struct TCPHeader_M_Object {
string type;
HTTPRequestObject request;
@ -86,20 +95,22 @@ namespace Qv2ray
TCPHeader_M_Object(): type("none"), request(), response() {}
XTOSTRUCT(O(type, request, response))
};
//
//
struct HeaderObject {
string type;
HeaderObject(): type("none") {}
XTOSTRUCT(O(type))
};
//
//
struct TCPObject {
TCPHeader_M_Object header;
TCPObject(): header() {}
XTOSTRUCT(O(header))
};
//
//
struct KCPObject {
int mtu = 1350;
int tti = 20;
@ -112,27 +123,31 @@ namespace Qv2ray
KCPObject(): header() {}
XTOSTRUCT(O(mtu, tti, uplinkCapacity, downlinkCapacity, congestion, readBufferSize, writeBufferSize, header))
};
//
//
struct WebSocketObject {
string path;
map<string, string> headers;
WebSocketObject(): path("/"), headers() {}
XTOSTRUCT(O(path, headers))
};
//
//
struct HttpObject {
list<string> host;
string path;
HttpObject() : host(), path("/") {}
XTOSTRUCT(O(host, path))
};
//
//
struct DomainSocketObject {
string path;
DomainSocketObject(): path("/") {}
XTOSTRUCT(O(path))
};
//
//
struct QuicObject {
string security;
string key;
@ -140,7 +155,8 @@ namespace Qv2ray
QuicObject(): security(""), key(""), header() {}
XTOSTRUCT(O(security, key, header))
};
//
//
struct SockoptObject {
int mark;
bool tcpFastOpen;
@ -148,7 +164,8 @@ namespace Qv2ray
SockoptObject(): mark(0), tcpFastOpen(false), tproxy("off") {}
XTOSTRUCT(O(mark, tcpFastOpen, tproxy))
};
//
//
struct CertificateObject {
string usage;
string certificateFile;
@ -158,7 +175,8 @@ namespace Qv2ray
CertificateObject(): usage(), certificateFile(), keyFile(), certificate(), key() {}
XTOSTRUCT(O(usage, certificateFile, keyFile, certificate, key))
};
//
//
struct TLSObject {
string serverName;
bool allowInsecure;
@ -170,14 +188,15 @@ namespace Qv2ray
};
}
//
//
struct SniffingObject {
bool enabled = false;
list<string> destOverride;
SniffingObject(): enabled(), destOverride() {}
XTOSTRUCT(O(enabled, destOverride))
};
//
//
struct StreamSettingsObject {
string network;
string security;
@ -192,61 +211,58 @@ namespace Qv2ray
StreamSettingsObject(): network("tcp"), security(), sockopt(), tlsSettings(), tcpSettings(), kcpSettings(), wsSettings(), httpSettings(), dsSettings(), quicSettings() {}
XTOSTRUCT(O(network, security, sockopt, tcpSettings, tlsSettings, kcpSettings, wsSettings, httpSettings, dsSettings, quicSettings))
};
//
//
struct MuxObject {
bool enabled;
int concurrency;
MuxObject(): enabled(), concurrency() {}
XTOSTRUCT(O(enabled, concurrency))
};
/// Some protocols from: https://v2ray.com/chapter_02/02_protocols.html
//
// Some protocols from: https://v2ray.com/chapter_02/02_protocols.html
namespace Protocols
{
struct XOutBoundsType {};
struct XInBoundsType {};
/// DNS, OutBound
struct DNSOut: XOutBoundsType {
// DNS, OutBound
struct DNSOut {
string network;
string address;
int port;
DNSOut(): network(""), address("0.0.0.0"), port(0) {}
XTOSTRUCT(O(network, address, port))
};
/// MTProto, InBound || OutBound
struct MTProtoIn: XInBoundsType, XOutBoundsType {
//
// MTProto, InBound || OutBound
struct MTProtoIn {
struct UserObject {
string email;
int level;
string secret;
UserObject() : email("user@domain.com"), level(0), secret("") {}
XTOSTRUCT(O(email, level, secret))
};
list<UserObject> users;
XTOSTRUCT(O(users))
};
/// Socks, OutBound
struct SocksOut: XOutBoundsType {
struct ServerObject {
struct UserObject {
string user;
string pass;
int level;
XTOSTRUCT(O(user, pass, level))
};
string address;
int port;
list<UserObject> users;
XTOSTRUCT(O(address, port, users))
//
// Socks, OutBound
struct SocksServerObject {
struct UserObject {
string user;
string pass;
int level;
UserObject(): user("username"), pass("password"), level(0) {}
XTOSTRUCT(O(user, pass, level))
};
list<ServerObject> servers;
XTOSTRUCT(O(servers))
};
string address;
int port;
list<UserObject> users;
SocksServerObject(): address("0.0.0.0"), port(0), users() {}
XTOSTRUCT(O(address, port, users))
};
//
// VMess Server
struct VMessServerObject {
struct UserObject {
string id;
@ -256,29 +272,30 @@ namespace Qv2ray
UserObject() : id(""), alterId(64), security("auto"), level(0) {}
XTOSTRUCT(O(id, alterId, security, level))
};
// OUTBound;
string address;
int port;
list<UserObject> users;
VMessServerObject(): address(""), port(0), users() {}
XTOSTRUCT(O(address, port, users))
};
struct ShadowSocksServerObject {
//
// ShadowSocks Server
struct ShadowSocksServer {
string email;
string address;
int port;
string method;
string password;
bool ota;
int level;
ShadowSocksServerObject(): email(""), address("0.0.0.0"), port(0), method("aes-256-cfb"), password(""), ota(false), level(0)
{}
int port;
ShadowSocksServer(): email("user@domain.com"), address("0.0.0.0"), method("aes-256-cfb"), password(""), ota(false), level(0), port(0) {}
XTOSTRUCT(O(email, address, port, method, password, ota, level))
};
}
}
}
using namespace Qv2ray::V2ConfigModels;
using namespace Qv2ray::V2ConfigModels::Protocols;

View File

@ -54,6 +54,7 @@ namespace Qv2ray
// -------------------------- BEGIN CONFIG CONVERSIONS ---------------------------------------------
// Save Connection Config
bool SaveConnectionConfig(QJsonObject obj, const QString *alias);
bool RenameConnection(QString originalName, QString newName);
// VMess Protocol
QJsonObject ConvertConfigFromVMessString(QString vmess);
QJsonObject ConvertConfigFromFile(QString sourceFilePath, bool overrideInbounds);

View File

@ -117,6 +117,11 @@ namespace Qv2ray
return list;
}
bool RenameConnection(QString originalName, QString newName)
{
return QFile(QV2RAY_CONFIG_PATH + originalName + QV2RAY_CONNECTION_FILE_EXTENSION).rename(QV2RAY_CONFIG_PATH + newName + QV2RAY_CONNECTION_FILE_EXTENSION);
}
int StartPreparation(QJsonObject fullConfig)
{
QString json = JSONToString(fullConfig);

View File

@ -18,7 +18,7 @@ namespace Qv2ray
auto vmessConf = StructFromJSONString<VMessProtocolConfigObject>(vmessString);
return 0;
} catch (exception *e) {
LOG(QObject::tr("#VMessDecodeError").toStdString() << e->what())
LOG(MODULE_CONNECTION, QObject::tr("#VMessDecodeError").toStdString() << e->what())
return -2;
}
}

View File

@ -2,7 +2,7 @@
#define VINTERACT_H
#include <QProcess>
#include <QString>
#include "QvGUIConfigObjects.h"
#include "Qv2rayBase.h"
namespace Qv2ray
{

19
src/QvTinyLog.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef QVTINYLOG_H
#define QVTINYLOG_H
#include <iostream>
using namespace std;
/*
* Tiny log module.
*/
#define LOG(module, msg) cout << "[" << module << "]: " << msg << endl;
#define MODULE_INIT "INIT"
#define MODULE_UPDATE "UPDATE"
#define MODULE_VCORE "VCORE"
#define MODULE_CONNECTION_VMESS "CONNETION-VMESS"
#define MODULE_CONNECTION "CONNECTION"
#define MODULE_UI "UI"
#define MODULE_FILE "FILE"
#endif // QVTINYLOG_H

View File

@ -98,14 +98,14 @@ namespace Qv2ray
file.close();
}
QStringList GetFileList(QDir *dir)
QStringList getFileList(QDir *dir)
{
return dir->entryList(QStringList() << "*" << "*.*", QDir::Hidden | QDir::Files);
}
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)

View File

@ -1,7 +1,7 @@
#ifndef UTILS_H
#define UTILS_H
#include "QvGUIConfigObjects.h"
#include "Qv2rayBase.h"
#include <QMessageBox>
#include <QUuid>
@ -11,7 +11,7 @@ namespace Qv2ray
{
QTranslator *getTranslator(QString lang);
QStringList GetFileList(QDir *dir);
QStringList getFileList(QDir *dir);
QString Base64Encode(QString string);
QString Base64Decode(QString string);

View File

@ -3,7 +3,7 @@
#include <QTranslator>
#include "QvUtils.h"
#include "QvGUIConfigObjects.h"
#include "Qv2rayBase.h"
#include "QvRunguard.h"
#include "w_MainWindow.h"
@ -14,24 +14,16 @@ using namespace Qv2ray::QvConfigModels;
bool initializeQv()
{
/// Qv2ray Config Path and ends with "/"
QString configPath;
QString exeDefaultPath;
QString v2AssetsPath;
QString configPath = QDir::homePath() + "/.qv2ray";
QString exeDefaultPath = configPath + "/vcore/v2ray";
QString v2AssetsPath = configPath + "/vcore";
//
#if defined(__WIN32)
// For Windows, there's no such 'installation' of a software
// package, So as what ShadowSocks and v2rayX does, save config files next to
// the executable.
configPath = QDir::homePath() + "/.qv2ray";
exeDefaultPath = configPath + "/vcore/v2ray.exe";
v2AssetsPath = configPath + "/vcore";
#else // NOT WINDOWS (*nix)
// Global config dir.
configPath = QDir::homePath() + "/.qv2ray";
exeDefaultPath = configPath + "/vcore/v2ray";
v2AssetsPath = configPath + "/vcore";
#endif
#ifdef __linux__
exeDefaultPath = exeDefaultPath + ".exe";
#elif defined(__linux__)
// Special case for GNU/Linux
// Unused these values
Q_UNUSED(v2AssetsPath)
@ -39,6 +31,7 @@ bool initializeQv()
v2AssetsPath = "/etc/v2ray";
exeDefaultPath = "/bin/v2ray";
#endif
//
SetConfigDirPath(configPath);
auto ConfigDir = new QDir(configPath);
@ -46,9 +39,9 @@ bool initializeQv()
auto result = QDir().mkdir(QV2RAY_CONFIG_PATH);
if (result) {
LOG("Created Qv2ray config dir at: " + QV2RAY_CONFIG_PATH.toStdString())
LOG(MODULE_INIT, "Created Qv2ray config dir at: " + QV2RAY_CONFIG_PATH.toStdString())
} else {
LOG("Failed to create config dir at: " + QV2RAY_CONFIG_PATH.toStdString())
LOG(MODULE_INIT, "Failed to create config dir at: " + QV2RAY_CONFIG_PATH.toStdString())
return false;
}
}
@ -59,9 +52,9 @@ bool initializeQv()
auto result2 = QDir().mkdir(genPath);
if (result2) {
LOG("Created config generation dir at: " + genPath.toStdString())
LOG(MODULE_INIT, "Created config generation dir at: " + genPath.toStdString())
} else {
LOG("Failed to create config generation dir at: " + genPath.toStdString())
LOG(MODULE_INIT, "Failed to create config generation dir at: " + genPath.toStdString())
return false;
}
}
@ -77,10 +70,10 @@ bool initializeQv()
SetGlobalConfig(conf);
SaveGlobalConfig();
//
LOG("Created initial default config file.")
LOG(MODULE_INIT, "Created initial default config file.")
} else {
LoadGlobalConfig();
LOG("Loaded config file.")
LOG(MODULE_INIT, "Loaded config file.")
}
return true;
@ -88,13 +81,21 @@ bool initializeQv()
int main(int argc, char *argv[])
{
LOG("Hv2ray Copyright (C) 2019 aliyuchang33 \r\n"
"Hv2ray/Qv2ray (partial) Copyright (C) SoneWinstone (jianwenzhen@qq.com) \r\n"
"Qv2ray Copyright (C) 2019 Leroy.H.Y \r\n"
"\r\n"
"This program comes with ABSOLUTELY NO WARRANTY.\r\n"
LOG("LICENCE", "\r\nThis program comes with ABSOLUTELY NO WARRANTY.\r\n"
"This is free software, and you are welcome to redistribute it\r\n"
"under certain conditions.\r\n")
"under certain conditions.\r\n"
"\r\n"
"Hv2ray Copyright (C) 2019 aliyuchang33\r\n"
"Hv2ray/Qv2ray (partial) Copyright 2019 (C) SoneWinstone\r\n"
"Qv2ray Copyright (C) 2019 Leroy.H.Y\r\n"
"\r\n"
"Qv2ray Version: " QV2RAY_VERSION_STRING
"\r\n"
"OS: " + QSysInfo::prettyProductName().toStdString() +
"\r\n"
"Arch: " + QSysInfo::currentCpuArchitecture().toStdString())
LOG("DEBUG", "============================== This is a debug build ==============================")
//
QApplication _qApp(argc, argv);
//
// Qv2ray Initialize
@ -109,9 +110,9 @@ int main(int argc, char *argv[])
#endif
if (_qApp.installTranslator(getTranslator(QString::fromStdString(GetGlobalConfig().language)))) {
LOG("Loaded translations " + GetGlobalConfig().language)
LOG(MODULE_UI, "Loaded translations " + GetGlobalConfig().language)
} else if (_qApp.installTranslator(getTranslator("en-US"))) {
LOG("Loaded default translations")
LOG(MODULE_UI, "Loaded default translations")
} else {
QvMessageBox(
nullptr, "Failed to load translations 无法加载语言文件",
@ -119,18 +120,17 @@ int main(int argc, char *argv[])
"无法加载语言文件,用户体验可能会降级.");
}
#ifndef QT_NO_DEBUG
QvMessageBox(nullptr, "Warning", "This is a debug build.");
LOG("DEBUG BUILD!")
#else
RunGuard guard("Qv2ray-Instance-Identifier");
RunGuard guard("Qv2ray-Instance-Identifier"
#ifdef QT_DEBUG
"DEBUG_VERSION"
#endif
);
if (!guard.isSingleInstance()) {
Utils::QvMessageBox(nullptr, QObject::tr("Qv2ray"), QObject::tr("#AnotherInstanceRunning"));
Utils::QvMessageBox(nullptr, "Qv2ray", QObject::tr("#AnotherInstanceRunning"));
return -1;
}
#endif
// Show MainWindow
MainWindow w;
return _qApp.exec();

View File

@ -19,7 +19,9 @@ ConnectionEditWindow::ConnectionEditWindow(QWidget *parent)
ui->setupUi(this);
ui->portLineEdit->setValidator(new QIntValidator());
ui->alterLineEdit->setValidator(new QIntValidator());
shadowsocks = ShadowSocksServerObject();
shadowsocks = ShadowSocksServer();
socks = SocksServerObject();
socks.users.push_back(SocksServerObject::UserObject());
vmess = VMessServerObject();
vmess.users.push_back(VMessServerObject::UserObject());
stream = StreamSettingsObject();
@ -40,10 +42,20 @@ ConnectionEditWindow::ConnectionEditWindow(QJsonObject editRootObject, QString a
stream = StructFromJSONString<StreamSettingsObject>(JSONToString(outBoundRoot["streamSettings"].toObject()));
shadowsocks.port = vmess.port;
shadowsocks.address = vmess.address;
socks.address = vmess.address;
socks.port = vmess.port;
} else if (OutboundType == "shadowsocks") {
shadowsocks = StructFromJSONString<ShadowSocksServerObject>(JSONToString(outBoundRoot["settings"].toObject()["servers"].toArray().first().toObject()));
shadowsocks = StructFromJSONString<ShadowSocksServer>(JSONToString(outBoundRoot["settings"].toObject()["servers"].toArray().first().toObject()));
vmess.address = shadowsocks.address;
vmess.port = shadowsocks.port;
socks.address = shadowsocks.address;
socks.port = shadowsocks.port;
} else if (OutboundType == "socks") {
socks = StructFromJSONString<SocksServerObject>(JSONToString(outBoundRoot["settings"].toObject()["servers"].toArray().first().toObject()));
vmess.address = socks.address;
vmess.port = socks.port;
shadowsocks.address = socks.address;
shadowsocks.port = socks.port;
}
ReLoad_GUI_JSON_ModelContent();
@ -60,64 +72,70 @@ void ConnectionEditWindow::ReLoad_GUI_JSON_ModelContent()
{
if (OutboundType == "vmess") {
ui->outBoundTypeCombo->setCurrentIndex(0);
ui->ipLineEdit->setText(QString::fromStdString(vmess.address));
ui->ipLineEdit->setText(QSTRING(vmess.address));
ui->portLineEdit->setText(QString::number(vmess.port));
ui->idLineEdit->setText(QString::fromStdString(vmess.users.front().id));
ui->idLineEdit->setText(QSTRING(vmess.users.front().id));
ui->alterLineEdit->setText(QString::number(vmess.users.front().alterId));
ui->securityCombo->setCurrentText(QString::fromStdString(vmess.users.front().security));
ui->tranportCombo->setCurrentText(QString::fromStdString(stream.network));
ui->securityCombo->setCurrentText(QSTRING(vmess.users.front().security));
ui->tranportCombo->setCurrentText(QSTRING(stream.network));
ui->tlsCB->setChecked(stream.security == "tls");
// TCP
ui->tcpHeaderTypeCB->setCurrentText(QString::fromStdString(stream.tcpSettings.header.type));
ui->tcpHeaderTypeCB->setCurrentText(QSTRING(stream.tcpSettings.header.type));
ui->tcpRequestTxt->setPlainText(StructToJSONString(stream.tcpSettings.header.request));
ui->tcpRespTxt->setPlainText(StructToJSONString(stream.tcpSettings.header.response));
// HTTP
QString allHosts;
foreach (auto host, stream.httpSettings.host) {
allHosts = allHosts + QString::fromStdString(host) + "\r\n";
allHosts = allHosts + QSTRING(host) + "\r\n";
}
ui->httpHostTxt->setPlainText(allHosts);
ui->httpPathTxt->setText(QString::fromStdString(stream.httpSettings.path));
ui->httpPathTxt->setText(QSTRING(stream.httpSettings.path));
// WS
ui->wsPathTxt->setText(QString::fromStdString(stream.wsSettings.path));
ui->wsPathTxt->setText(QSTRING(stream.wsSettings.path));
QString wsHeaders;
foreach (auto _, stream.wsSettings.headers) {
wsHeaders = wsHeaders + QString::fromStdString(_.first + "|" + _.second) + "\r\n";
wsHeaders = wsHeaders + QSTRING(_.first + "|" + _.second) + "\r\n";
}
ui->wsHeadersTxt->setPlainText(wsHeaders);
// mKCP
ui->kcpMTU->setValue(stream.kcpSettings.mtu);
ui->kcpTTI->setValue(stream.kcpSettings.tti);
ui->kcpHeaderType->setCurrentText(QString::fromStdString(stream.kcpSettings.header.type));
ui->kcpHeaderType->setCurrentText(QSTRING(stream.kcpSettings.header.type));
ui->kcpCongestionCB->setChecked(stream.kcpSettings.congestion);
ui->kcpReadBufferSB->setValue(stream.kcpSettings.readBufferSize);
ui->kcpUploadCapacSB->setValue(stream.kcpSettings.uplinkCapacity);
ui->kcpDownCapacitySB->setValue(stream.kcpSettings.downlinkCapacity);
ui->kcpWriteBufferSB->setValue(stream.kcpSettings.writeBufferSize);
// DS
ui->dsPathTxt->setText(QString::fromStdString(stream.dsSettings.path));
ui->dsPathTxt->setText(QSTRING(stream.dsSettings.path));
// QUIC
ui->quicKeyTxt->setText(QString::fromStdString(stream.quicSettings.key));
ui->quicSecurityCB->setCurrentText(QString::fromStdString(stream.quicSettings.security));
ui->quicHeaderTypeCB->setCurrentText(QString::fromStdString(stream.quicSettings.header.type));
ui->quicKeyTxt->setText(QSTRING(stream.quicSettings.key));
ui->quicSecurityCB->setCurrentText(QSTRING(stream.quicSettings.security));
ui->quicHeaderTypeCB->setCurrentText(QSTRING(stream.quicSettings.header.type));
// SOCKOPT
ui->tProxyCB->setCurrentText(QString::fromStdString(stream.sockopt.tproxy));
ui->tProxyCB->setCurrentText(QSTRING(stream.sockopt.tproxy));
ui->tcpFastOpenCB->setChecked(stream.sockopt.tcpFastOpen);
ui->soMarkSpinBox->setValue(stream.sockopt.mark);
} else if (OutboundType == "shadowsocks") {
ui->outBoundTypeCombo->setCurrentIndex(1);
// ShadowSocks Configs
ui->ipLineEdit->setText(QString::fromStdString(shadowsocks.address));
ui->ipLineEdit->setText(QSTRING(shadowsocks.address));
ui->portLineEdit->setText(QString::number(shadowsocks.port));
ui->ss_emailTxt->setText(QString::fromStdString(shadowsocks.email));
ui->ss_emailTxt->setText(QSTRING(shadowsocks.email));
ui->ss_levelSpin->setValue(shadowsocks.level);
ui->ss_otaCheckBox->setChecked(shadowsocks.ota);
ui->ss_passwordTxt->setText(QString::fromStdString(shadowsocks.password));
ui->ss_encryptionMethod->setCurrentText(QString::fromStdString(shadowsocks.method));
ui->ss_passwordTxt->setText(QSTRING(shadowsocks.password));
ui->ss_encryptionMethod->setCurrentText(QSTRING(shadowsocks.method));
} else if (OutboundType == "socks") {
ui->outBoundTypeCombo->setCurrentIndex(2);
ui->ipLineEdit->setText(QSTRING(socks.address));
ui->portLineEdit->setText(QString::number(socks.port));
ui->socks_PasswordTxt->setText(QSTRING(socks.users.front().pass));
ui->socks_UserNameTxt->setText(QSTRING(socks.users.front().user));
}
}
@ -152,6 +170,7 @@ void ConnectionEditWindow::on_ipLineEdit_textEdited(const QString &arg1)
{
vmess.address = arg1.toStdString();
shadowsocks.address = arg1.toStdString();
socks.address = arg1.toStdString();
GEN_JSON
//
// No thanks.
@ -171,6 +190,7 @@ void ConnectionEditWindow::on_portLineEdit_textEdited(const QString &arg1)
if (arg1 != "") {
vmess.port = stoi(arg1.toStdString());
shadowsocks.port = stoi(arg1.toStdString());
socks.port = stoi(arg1.toStdString());
GEN_JSON
}
}
@ -318,6 +338,11 @@ QJsonObject ConnectionEditWindow::GenerateConnectionJson()
QJsonArray servers;
servers.append(GetRootObject(shadowsocks));
settings["servers"] = servers;
} else if (OutboundType == "socks") {
streaming = QJsonObject();
QJsonArray servers;
servers.append(GetRootObject(socks));
settings["servers"] = servers;
}
auto root = GenerateOutboundEntry(OutboundType, settings, streaming, mux, "0.0.0.0", OUTBOUND_TAG_PROXY);
@ -491,3 +516,15 @@ void ConnectionEditWindow::on_ss_otaCheckBox_stateChanged(int arg1)
shadowsocks.ota = arg1 == Qt::Checked;
GEN_JSON
}
void ConnectionEditWindow::on_socks_UserNameTxt_textEdited(const QString &arg1)
{
socks.users.front().user = arg1.toStdString();
GEN_JSON
}
void ConnectionEditWindow::on_socks_PasswordTxt_textEdited(const QString &arg1)
{
socks.users.front().pass = arg1.toStdString();
GEN_JSON
}

View File

@ -108,6 +108,10 @@ class ConnectionEditWindow : public QDialog
void on_ss_otaCheckBox_stateChanged(int arg1);
void on_socks_UserNameTxt_textEdited(const QString &arg1);
void on_socks_PasswordTxt_textEdited(const QString &arg1);
private:
int rootJsonCursorPos;
QString _alias;
@ -120,7 +124,8 @@ class ConnectionEditWindow : public QDialog
QString OutboundType;
StreamSettingsObject stream;
VMessServerObject vmess;
ShadowSocksServerObject shadowsocks;
ShadowSocksServer shadowsocks;
SocksServerObject socks;
//
};
#endif // CONFEDIT_H

View File

@ -6,24 +6,24 @@
<rect>
<x>0</x>
<y>0</y>
<width>960</width>
<height>750</height>
<width>911</width>
<height>770</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="MinimumExpanding">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>960</width>
<height>750</height>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>#ConnectionSettings</string>
<string>#EditConnectionSettings</string>
</property>
<property name="modal">
<bool>true</bool>
@ -80,29 +80,15 @@
<string notr="true">ShadowSocks</string>
</property>
</item>
<item>
<property name="text">
<string>Socks</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item row="0" column="1" rowspan="2">
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>#JsonPreview</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextBrowser" name="finalJson">
<property name="lineWrapMode">
<enum>QTextEdit::NoWrap</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="outboundSettingWrapper">
<property name="title">
@ -111,6 +97,12 @@
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QStackedWidget" name="outboundTypeStackView">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
</property>
@ -255,7 +247,7 @@
<number>0</number>
</property>
<widget class="QWidget" name="tcpStackPage">
<layout class="QGridLayout" name="gridLayout_7">
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0" colspan="4">
<layout class="QGridLayout" name="gridLayout_4" columnstretch="1,5">
<item row="0" column="1">
@ -288,6 +280,13 @@
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="tcpRequestPrettifyBtn">
<property name="text">
<string>#Prettify</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_3">
<property name="text">
@ -295,6 +294,13 @@
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="tcpRespPrettifyBtn">
<property name="text">
<string>#Prettify</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QPlainTextEdit" name="tcpRequestTxt">
<property name="lineWrapMode">
@ -318,34 +324,20 @@
</property>
</widget>
</item>
<item row="3" column="0">
<item row="3" column="0" colspan="2">
<widget class="QPushButton" name="tcpRequestDefBtn">
<property name="text">
<string>#InsertDefaultContent</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QPushButton" name="tcpRequestPrettifyBtn">
<property name="text">
<string>#Prettify</string>
</property>
</widget>
</item>
<item row="3" column="2">
<item row="3" column="2" colspan="2">
<widget class="QPushButton" name="tcpRespDefBtn">
<property name="text">
<string>#InsertDefaultContent</string>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QPushButton" name="tcpRespPrettifyBtn">
<property name="text">
<string>#Prettify</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="httpStackPage">
@ -577,63 +569,54 @@
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>#Header</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_16">
<item row="3" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
<string>#Type</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="kcpHeaderType">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>#Type</string>
<string notr="true">none</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="kcpHeaderType">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</item>
<item>
<property name="text">
<string notr="true">srtp</string>
</property>
<item>
<property name="text">
<string notr="true">none</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">srtp</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">utp</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">wechat-video</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">dtls</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">wireguard</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<property name="text">
<string notr="true">utp</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">wechat-video</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">dtls</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">wireguard</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
@ -693,91 +676,65 @@
</item>
</widget>
</item>
<item row="1" column="0">
<item row="2" column="0">
<widget class="QLabel" name="label_19">
<property name="text">
<string>#Key</string>
</property>
</widget>
</item>
<item row="1" column="1">
<item row="2" column="1">
<widget class="QLineEdit" name="quicKeyTxt">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<item row="3" column="0">
<widget class="QLabel" name="label_20">
<property name="text">
<string>#Headers</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QGroupBox" name="groupBox_3">
<item row="3" column="1">
<widget class="QComboBox" name="quicHeaderTypeCB">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>#Header</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_11">
<item>
<layout class="QFormLayout" name="formLayout_4">
<item row="0" column="0">
<widget class="QLabel" name="label_21">
<property name="text">
<string>#Type</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="quicHeaderTypeCB">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string notr="true">none</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">srtp</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">utp</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">wechat-video</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">dtls</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">wireguard</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
</layout>
<item>
<property name="text">
<string notr="true">none</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">srtp</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">utp</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">wechat-video</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">dtls</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">wireguard</string>
</property>
</item>
</widget>
</item>
</layout>
@ -943,12 +900,61 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="page_3">
<layout class="QFormLayout" name="formLayout">
<item row="1" column="1">
<widget class="QLineEdit" name="socks_UserNameTxt"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_31">
<property name="text">
<string>#Password</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="socks_PasswordTxt"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_21">
<property name="text">
<string>#Username</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="1">
<item row="0" column="1" rowspan="2">
<widget class="QGroupBox" name="groupBox_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>#JsonPreview</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextBrowser" name="finalJson">
<property name="lineWrapMode">
<enum>QTextEdit::NoWrap</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>

View File

@ -79,6 +79,6 @@ void ImportConfigWindow::on_buttonBox_accepted()
conf.configs.push_back(alias.toStdString());
SetGlobalConfig(conf);
auto needReload = SaveConnectionConfig(config, &alias);
LOG("WARNING: POSSIBLE LOSS OF DATA")
LOG(MODULE_CONNECTION_VMESS, "WARNING: POSSIBLE LOSS OF DATA")
emit s_reload_config(needReload);
}

View File

@ -20,41 +20,54 @@
#include "w_ConnectionEditWindow.h"
#include "w_MainWindow.h"
#define TRAY_TOOLTIP_PREFIX "Qv2ray " QV2RAY_VERSION_STRING "\r\n"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent),
HTTPRequestHelper(this),
ui(new Ui::MainWindow),
HTTPRequestHelper(this),
hTray(new QSystemTrayIcon(this)),
vinstance(new Qv2Instance(this))
{
ui->setupUi(this);
this->setWindowIcon(QIcon(":/icons/Qv2ray.ico"));
hTray->setIcon(this->windowIcon());
hTray->setToolTip(TRAY_TOOLTIP_PREFIX);
//
QAction *actionShowHide = new QAction(this->windowIcon(), tr("#Hide"), this);
QAction *actionQuit = new QAction(tr("#Quit"), this);
QAction *actionStart = new QAction(tr("#Start"), this);
QAction *actionRestart = new QAction(tr("#Restart"), this);
QAction *actionStop = new QAction(tr("#Stop"), this);
actionStart->setEnabled(true);
actionStop->setEnabled(false);
actionRestart->setEnabled(false);
trayMenu->addAction(actionShowHide);
QAction *action_Tray_ShowHide = new QAction(this->windowIcon(), tr("#Hide"), this);
QAction *action_Tray_Quit = new QAction(tr("#Quit"), this);
QAction *action_Tray_Start = new QAction(tr("#Connect"), this);
QAction *action_Tray_Restart = new QAction(tr("#Reconnect"), this);
QAction *action_Tray_Stop = new QAction(tr("#Disconnect"), this);
//
QAction *action_RCM_RenameConnection = new QAction(tr("#Rename"), this);
QAction *action_RCM_StartThis = new QAction(tr("#ConnectSelected"), this);
action_Tray_Start->setEnabled(true);
action_Tray_Stop->setEnabled(false);
action_Tray_Restart->setEnabled(false);
trayMenu->addAction(action_Tray_ShowHide);
trayMenu->addSeparator();
trayMenu->addAction(actionStart);
trayMenu->addAction(actionStop);
trayMenu->addAction(actionRestart);
trayMenu->addAction(action_Tray_Start);
trayMenu->addAction(action_Tray_Stop);
trayMenu->addAction(action_Tray_Restart);
trayMenu->addSeparator();
trayMenu->addAction(actionQuit);
connect(actionShowHide, &QAction::triggered, this, &MainWindow::ToggleVisibility);
connect(actionStart, &QAction::triggered, this, &MainWindow::on_startButton_clicked);
connect(actionStop, &QAction::triggered, this, &MainWindow::on_stopButton_clicked);
connect(actionRestart, &QAction::triggered, this, &MainWindow::on_restartButton_clicked);
connect(actionQuit, &QAction::triggered, this, &MainWindow::quit);
trayMenu->addAction(action_Tray_Quit);
connect(action_Tray_ShowHide, &QAction::triggered, this, &MainWindow::ToggleVisibility);
connect(action_Tray_Start, &QAction::triggered, this, &MainWindow::on_startButton_clicked);
connect(action_Tray_Stop, &QAction::triggered, this, &MainWindow::on_stopButton_clicked);
connect(action_Tray_Restart, &QAction::triggered, this, &MainWindow::on_restartButton_clicked);
connect(action_Tray_Quit, &QAction::triggered, this, &MainWindow::quit);
connect(hTray, &QSystemTrayIcon::activated, this, &MainWindow::on_activatedTray);
connect(ui->logText, &QTextBrowser::textChanged, this, &MainWindow::QTextScrollToBottom);
connect(action_RCM_RenameConnection, &QAction::triggered, this, &MainWindow::on_action_RenameConnection_triggered);
connect(action_RCM_StartThis, &QAction::triggered, this, &MainWindow::on_action_StartThis_triggered);
//
hTray->setContextMenu(trayMenu);
hTray->show();
//
listMenu.addAction(action_RCM_StartThis);
listMenu.addAction(action_RCM_RenameConnection);
//
LoadConnections();
QObject::connect(&HTTPRequestHelper, &QvHttpRequestHelper::httpRequestFinished, this, &MainWindow::VersionUpdate);
HTTPRequestHelper.get("https://api.github.com/repos/lhy0403/Qv2ray/releases/latest");
@ -67,8 +80,8 @@ MainWindow::MainWindow(QWidget *parent)
auto conf = GetGlobalConfig();
if (conf.autoStartConfig != "" && QList<string>::fromStdList(conf.configs).contains(conf.autoStartConfig)) {
CurrentConnectionName = QString::fromStdString(conf.autoStartConfig);
auto item = ui->connectionListWidget->findItems(QString::fromStdString(conf.autoStartConfig), Qt::MatchExactly).front();
CurrentConnectionName = QSTRING(conf.autoStartConfig);
auto item = ui->connectionListWidget->findItems(QSTRING(conf.autoStartConfig), Qt::MatchExactly).front();
item->setSelected(true);
ui->connectionListWidget->setCurrentItem(item);
on_connectionListWidget_itemClicked(item);
@ -81,6 +94,12 @@ MainWindow::MainWindow(QWidget *parent)
}
}
void MainWindow::on_action_StartThis_triggered()
{
CurrentConnectionName = ui->connectionListWidget->currentItem()->text();
on_restartButton_clicked();
}
void MainWindow::VersionUpdate(QByteArray &data)
{
auto conf = GetGlobalConfig();
@ -88,14 +107,14 @@ void MainWindow::VersionUpdate(QByteArray &data)
QJsonObject root = JSONFromString(jsonString);
//
QVersionNumber newversion = QVersionNumber::fromString(root["tag_name"].toString("").remove(0, 1));
QVersionNumber current = QVersionNumber::fromString(QString::fromStdString(QV2RAY_VERSION_STRING).remove(0, 1));
QVersionNumber ignored = QVersionNumber::fromString(QString::fromStdString(conf.ignoredVersion));
LOG("Received update info, Latest: " + newversion.toString().toStdString() + " Current: " + current.toString().toStdString() + " Ignored: " + ignored.toString().toStdString())
QVersionNumber current = QVersionNumber::fromString(QSTRING(QV2RAY_VERSION_STRING).remove(0, 1));
QVersionNumber ignored = QVersionNumber::fromString(QSTRING(conf.ignoredVersion));
LOG(MODULE_UPDATE, "Received update info, Latest: " + newversion.toString().toStdString() + " Current: " + current.toString().toStdString() + " Ignored: " + ignored.toString().toStdString())
// If the version is newer than us.
// And new version is newer than the ignored version.
if (newversion > current && newversion > ignored) {
LOG("New version detected.")
LOG(MODULE_UPDATE, "New version detected.")
auto link = root["html_url"].toString("");
auto result = QvMessageBoxAsk(this, tr("#NewReleaseVersionFound"),
tr("#NewReleaseVersionFound") + ": " + root["tag_name"].toString("") +
@ -126,11 +145,15 @@ void MainWindow::LoadConnections()
for (int i = 0; i < connections.count(); i++) {
ui->connectionListWidget->addItem(connections.keys()[i]);
}
ui->connectionListWidget->sortItems();
}
void MainWindow::save_reload_globalconfig(bool need_restart)
{
auto statusText = ui->statusLabel->text();
ui->retranslateUi(this);
ui->statusLabel->setText(statusText);
bool isRunning = vinstance->Status == STARTED;
SaveGlobalConfig();
@ -140,6 +163,7 @@ void MainWindow::save_reload_globalconfig(bool need_restart)
if (isRunning && need_restart) on_startButton_clicked();
}
MainWindow::~MainWindow()
{
hTray->hide();
@ -160,15 +184,16 @@ void MainWindow::on_startButton_clicked()
return;
}
LOG(("Now start a connection: " + CurrentConnectionName).toStdString())
LOG(MODULE_VCORE, ("Connecting to: " + CurrentConnectionName).toStdString())
ui->logText->clear();
auto full_conf = GenerateRuntimeConfig(connections.value(CurrentConnectionName));
StartPreparation(full_conf);
bool startFlag = this->vinstance->Start();
if (startFlag) {
this->hTray->showMessage(tr("Qv2ray"), tr("#ConnectedToServer ") + CurrentConnectionName);
ui->statusLabel->setText(tr("#Started") + ": " + CurrentConnectionName);
this->hTray->showMessage("Qv2ray", tr("#ConnectedToServer") + " " + CurrentConnectionName, hTray->icon());
hTray->setToolTip(TRAY_TOOLTIP_PREFIX + tr("#ConnectedToServer") + ": " + CurrentConnectionName);
ui->statusLabel->setText(tr("#Connected") + ": " + CurrentConnectionName);
}
trayMenu->actions()[2]->setEnabled(!startFlag);
@ -177,23 +202,24 @@ void MainWindow::on_startButton_clicked()
//
ui->startButton->setEnabled(!startFlag);
ui->stopButton->setEnabled(startFlag);
ui->restartButton->setEnabled(startFlag);
}
void MainWindow::on_stopButton_clicked()
{
LOG("Stop connection!")
this->vinstance->Stop();
QFile(QV2RAY_GENERATED_CONFIG_FILE_PATH).remove();
ui->statusLabel->setText(tr("#Stopped"));
ui->logText->clear();
trayMenu->actions()[2]->setEnabled(true);
trayMenu->actions()[3]->setEnabled(false);
trayMenu->actions()[4]->setEnabled(false);
//
ui->startButton->setEnabled(true);
ui->stopButton->setEnabled(false);
ui->restartButton->setEnabled(false);
if (vinstance->Status != STOPPED) {
LOG(MODULE_VCORE, "Disconnected: " + CurrentConnectionName.toStdString())
this->vinstance->Stop();
hTray->setToolTip(TRAY_TOOLTIP_PREFIX);
QFile(QV2RAY_GENERATED_CONFIG_FILE_PATH).remove();
ui->statusLabel->setText(tr("#Disconnected"));
ui->logText->clear();
trayMenu->actions()[2]->setEnabled(true);
trayMenu->actions()[3]->setEnabled(false);
trayMenu->actions()[4]->setEnabled(false);
//
ui->startButton->setEnabled(true);
ui->stopButton->setEnabled(false);
}
}
void MainWindow::on_restartButton_clicked()
@ -286,23 +312,30 @@ void MainWindow::ShowAndSetConnection(int index, bool SetConnection, bool ApplyC
if (outboundType == "vmess") {
auto Server = StructFromJSONString<VMessServerObject>(JSONToString(outBoundRoot["settings"].toObject()["vnext"].toArray().first().toObject()));
ui->_hostLabel->setText(QString::fromStdString(Server.address));
ui->_portLabel->setText(QString::fromStdString(to_string(Server.port)));
ui->_hostLabel->setText(QSTRING(Server.address));
ui->_portLabel->setText(QSTRING(to_string(Server.port)));
auto user = QList<VMessServerObject::UserObject>::fromStdList(Server.users).first();
auto _configString = tr("#UUID") + ": " + QString::fromStdString(user.id)
auto _configString = tr("#UUID") + ": " + QSTRING(user.id)
+ "\r\n"
+ tr("#AlterID") + ": " + QString::fromStdString(to_string(user.alterId))
+ tr("#AlterID") + ": " + QSTRING(to_string(user.alterId))
+ "\r\n"
+ tr("#Transport") + ": " + outBoundRoot["streamSettings"].toObject()["network"].toString();
ui->detailInfoTxt->setPlainText(_configString);
} else if (outboundType == "shadowsocks") {
auto x = JSONToString(outBoundRoot["settings"].toObject()["servers"].toArray().first().toObject());
auto Server = StructFromJSONString<ShadowSocksServerObject>(x);
ui->_hostLabel->setText(QString::fromStdString(Server.address));
ui->_portLabel->setText(QString::fromStdString(to_string(Server.port)));
auto _configString = tr("#Email") + ": " + QString::fromStdString(Server.email)
auto Server = StructFromJSONString<ShadowSocksServer>(x);
ui->_hostLabel->setText(QSTRING(Server.address));
ui->_portLabel->setText(QSTRING(to_string(Server.port)));
auto _configString = tr("#Email") + ": " + QSTRING(Server.email)
+ "\r\n"
+ tr("#Encryption") + ": " + QString::fromStdString(Server.method);
+ tr("#Encryption") + ": " + QSTRING(Server.method);
ui->detailInfoTxt->setPlainText(_configString);
} else if (outboundType == "socks") {
auto x = JSONToString(outBoundRoot["settings"].toObject()["servers"].toArray().first().toObject());
auto Server = StructFromJSONString<SocksServerObject>(x);
ui->_hostLabel->setText(QSTRING(Server.address));
ui->_portLabel->setText(QSTRING(to_string(Server.port)));
auto _configString = tr("#Username") + ": " + QSTRING(Server.users.front().user);
ui->detailInfoTxt->setPlainText(_configString);
}
@ -323,41 +356,7 @@ void MainWindow::on_connectionListWidget_itemClicked(QListWidgetItem *item)
{
Q_UNUSED(item)
int currentRow = ui->connectionListWidget->currentRow();
ShowAndSetConnection(currentRow, vinstance->Status != STARTED, false);
}
void MainWindow::on_importConfigBtn_clicked()
{
ImportConfigWindow *w = new ImportConfigWindow(this);
connect(w, &ImportConfigWindow::s_reload_config, this, &MainWindow::save_reload_globalconfig);
w->show();
}
void MainWindow::on_addConfigBtn_clicked()
{
ConnectionEditWindow *w = new ConnectionEditWindow(this);
connect(w, &ConnectionEditWindow::s_reload_config, this, &MainWindow::save_reload_globalconfig);
w->show();
}
void MainWindow::on_delConfigBtn_clicked()
{
auto conf = GetGlobalConfig();
QList<string> list = QList<string>::fromStdList(conf.configs);
auto currentSelected = ui->connectionListWidget->currentIndex().row();
if (currentSelected < 0) return;
bool isRemovingItemRunning = ui->connectionListWidget->item(currentSelected)->text() == CurrentConnectionName;
if (isRemovingItemRunning) {
CurrentConnectionName = "";
}
list.removeOne(ui->connectionListWidget->item(currentSelected)->text().toStdString());
conf.configs = list.toStdList();
SetGlobalConfig(conf);
save_reload_globalconfig(isRemovingItemRunning);
ShowAndSetConnection(currentRow, !isRenamingInProgress && (vinstance->Status != STARTED), false);
}
void MainWindow::on_prefrencesBtn_clicked()
@ -372,7 +371,116 @@ void MainWindow::on_connectionListWidget_doubleClicked(const QModelIndex &index)
ShowAndSetConnection(index.row(), true, true);
}
void MainWindow::on_editConnectionSettingsBtn_clicked()
void MainWindow::on_clearlogButton_clicked()
{
ui->logText->clear();
}
void MainWindow::on_connectionListWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
{
Q_UNUSED(previous)
isRenamingInProgress = true;
on_connectionListWidget_itemClicked(current);
}
void MainWindow::on_connectionListWidget_customContextMenuRequested(const QPoint &pos)
{
Q_UNUSED(pos)
listMenu.popup(QCursor::pos());
}
void MainWindow::on_action_RenameConnection_triggered()
{
auto item = ui->connectionListWidget->currentItem();
item->setFlags(item->flags() | Qt::ItemIsEditable);
ui->connectionListWidget->editItem(item);
originalName = item->text();
isRenamingInProgress = false;
}
void MainWindow::on_connectionListWidget_itemChanged(QListWidgetItem *item)
{
LOG(MODULE_UI, "A connection ListViewItem is changed.")
if (!isRenamingInProgress) {
// In this case it's after we entered the name.
LOG(MODULE_CONNECTION, "RENAME: " + originalName.toStdString() + " -> " + item->text().toStdString())
auto newName = item->text();
auto config = GetGlobalConfig();
auto configList = QList<string>::fromStdList(config.configs);
if (newName.trimmed().isEmpty()) {
QvMessageBox(this, tr("#RenameConnection"), tr("#CannotUseEmptyName"));
return;
}
// If I really did some changes.
LOG("RENAME", "ORIGINAL: " + originalName.toStdString() + ", NEW: " + newName.toStdString())
if (originalName != newName) {
if (configList.contains(newName.toStdString())) {
QvMessageBox(this, tr("#RenameConnection"), tr("#DuplicatedConnectionName"));
return;
}
//
// Change auto start config.
if (originalName.toStdString() == config.autoStartConfig) config.autoStartConfig = newName.toStdString();
configList[configList.indexOf(originalName.toStdString())] = newName.toStdString();
config.configs = configList.toStdList();
//
RenameConnection(originalName, newName);
//
SetGlobalConfig(config);
bool running = CurrentConnectionName == originalName;
if (running) CurrentConnectionName = newName;
save_reload_globalconfig(running);
auto newItem = ui->connectionListWidget->findItems(newName, Qt::MatchExactly).front();
ui->connectionListWidget->setCurrentItem(newItem);
}
}
}
void MainWindow::on_removeConfigButton_clicked()
{
if (QvMessageBoxAsk(this, tr("#RemoveConnection"), tr("#RemoveConnectionConfirm")) == QMessageBox::Yes) {
auto conf = GetGlobalConfig();
QList<string> list = QList<string>::fromStdList(conf.configs);
auto currentSelected = ui->connectionListWidget->currentIndex().row();
if (currentSelected < 0) return;
bool isRemovingItemRunning = ui->connectionListWidget->item(currentSelected)->text() == CurrentConnectionName;
if (isRemovingItemRunning) {
CurrentConnectionName = "";
}
list.removeOne(ui->connectionListWidget->item(currentSelected)->text().toStdString());
conf.configs = list.toStdList();
SetGlobalConfig(conf);
save_reload_globalconfig(isRemovingItemRunning);
}
}
void MainWindow::on_importConfigButton_clicked()
{
ImportConfigWindow *w = new ImportConfigWindow(this);
connect(w, &ImportConfigWindow::s_reload_config, this, &MainWindow::save_reload_globalconfig);
w->show();
}
void MainWindow::on_addConfigButton_clicked()
{
ConnectionEditWindow *w = new ConnectionEditWindow(this);
connect(w, &ConnectionEditWindow::s_reload_config, this, &MainWindow::save_reload_globalconfig);
w->show();
}
void MainWindow::on_editConfigButton_clicked()
{
// Check if we have a connection selected...
auto index = ui->connectionListWidget->currentIndex().row();
@ -386,8 +494,3 @@ void MainWindow::on_editConnectionSettingsBtn_clicked()
connect(w, &ConnectionEditWindow::s_reload_config, this, &MainWindow::save_reload_globalconfig);
w->show();
}
void MainWindow::on_clearlogButton_clicked()
{
ui->logText->clear();
}

View File

@ -25,8 +25,8 @@ class MainWindow : public QMainWindow
public slots:
void save_reload_globalconfig(bool need_restart);
void UpdateLog();
void VersionUpdate(QByteArray &data);
private slots:
void VersionUpdate(QByteArray &data);
void on_restartButton_clicked();
void on_startButton_clicked();
void on_stopButton_clicked();
@ -38,32 +38,45 @@ class MainWindow : public QMainWindow
void on_connectionListWidget_itemClicked(QListWidgetItem *item);
void on_importConfigBtn_clicked();
void on_addConfigBtn_clicked();
void on_delConfigBtn_clicked();
void on_prefrencesBtn_clicked();
void on_connectionListWidget_doubleClicked(const QModelIndex &index);
void on_editConnectionSettingsBtn_clicked();
void on_clearlogButton_clicked();
void on_connectionListWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous);
void on_connectionListWidget_customContextMenuRequested(const QPoint &pos);
void on_action_RenameConnection_triggered();
void on_action_StartThis_triggered();
void on_connectionListWidget_itemChanged(QListWidgetItem *item);
void on_removeConfigButton_clicked();
void on_importConfigButton_clicked();
void on_addConfigButton_clicked();
void on_editConfigButton_clicked();
private:
QvHttpRequestHelper HTTPRequestHelper;
void ShowAndSetConnection(int index, bool SetConnection, bool Apply);
void LoadConnections();
QString CurrentConnectionName;
Ui::MainWindow *ui;
QvHttpRequestHelper HTTPRequestHelper;
QSystemTrayIcon *hTray;
QMenu *trayMenu = new QMenu(this);
Qv2Instance *vinstance;
//
void closeEvent(QCloseEvent *);
QMenu listMenu;
QMap<QString, QJsonObject> connections;
QString CurrentConnectionName;
//
QString originalName;
bool isRenamingInProgress;
//
void ShowAndSetConnection(int index, bool SetConnection, bool Apply);
void LoadConnections();
void closeEvent(QCloseEvent *);
};
#endif // MAINWINDOW_H

View File

@ -9,8 +9,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>700</width>
<height>550</height>
<width>680</width>
<height>553</height>
</rect>
</property>
<property name="sizePolicy">
@ -19,12 +19,6 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>700</width>
<height>550</height>
</size>
</property>
<property name="windowTitle">
<string>Qv2ray</string>
</property>
@ -41,16 +35,16 @@
<height>530</height>
</size>
</property>
<layout class="QGridLayout" name="gridLayout" columnstretch="4,6" rowminimumheight="0,0,0,0,0,8">
<layout class="QGridLayout" name="gridLayout" columnstretch="2,3">
<item row="0" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1,1,1,0,0,0">
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1,1,0,0,0">
<property name="spacing">
<number>5</number>
</property>
<item>
<widget class="QPushButton" name="startButton">
<property name="text">
<string>#Start</string>
<string>#Connect</string>
</property>
</widget>
</item>
@ -60,20 +54,7 @@
<bool>false</bool>
</property>
<property name="text">
<string>#Stop</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="restartButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>#Restart</string>
</property>
<property name="flat">
<bool>false</bool>
<string>#Disconnect</string>
</property>
</widget>
</item>
@ -101,8 +82,8 @@
</property>
<property name="sizeHint" stdset="0">
<size>
<width>999999</width>
<height>20</height>
<width>999999999</width>
<height>0</height>
</size>
</property>
</spacer>
@ -123,97 +104,26 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QListWidget" name="connectionListWidget">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<property name="midLineWidth">
<number>0</number>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="defaultDropAction">
<enum>Qt::CopyAction</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="viewMode">
<enum>QListView::ListMode</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="importConfigBtn">
<property name="text">
<string>#ImportConfig</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="addConfigBtn">
<property name="text">
<string>#AddConfig</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="delConfigBtn">
<property name="text">
<string>#RemoveConfig</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="5" column="0" colspan="2">
<widget class="QTextBrowser" name="logText">
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="lineWrapMode">
<enum>QTextEdit::NoWrap</enum>
</property>
<property name="openLinks">
<bool>false</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>#Log</string>
</property>
</widget>
</item>
<item row="1" column="1" rowspan="3">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>#ConfigDetail</string>
<string>#CurrentConfigDetail</string>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<property name="verticalSpacing">
<number>10</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>#OutBoundType</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="_OutBoundTypeLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
@ -242,20 +152,6 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>#OutBoundType</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="_OutBoundTypeLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
@ -265,49 +161,178 @@
</item>
<item row="3" column="1">
<widget class="QTextBrowser" name="detailInfoTxt">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="lineWrapMode">
<enum>QTextEdit::NoWrap</enum>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>#EditConnection</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="editConnectionSettingsBtn">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>#ConnectionSettings</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QListWidget" name="connectionListWidget">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<property name="midLineWidth">
<number>0</number>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="defaultDropAction">
<enum>Qt::CopyAction</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="viewMode">
<enum>QListView::ListMode</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="addConfigButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>#AddConnection</string>
</property>
<property name="text">
<string>A</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/icons/add_connection_btn.png</normaloff>:/icons/add_connection_btn.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="importConfigButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>#ImportConnection</string>
</property>
<property name="text">
<string>I</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/icons/import_connection_btn.png</normaloff>:/icons/import_connection_btn.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="removeConfigButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>#RemoveConnection</string>
</property>
<property name="text">
<string>R</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/icons/remove_connection_btn.png</normaloff>:/icons/remove_connection_btn.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="editConfigButton">
<property name="toolTip">
<string>#EditConnection</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/icons/edit_connection_btn.png</normaloff>:/icons/edit_connection_btn.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>#Log</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QTextBrowser" name="logText">
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="lineWrapMode">
<enum>QTextEdit::NoWrap</enum>
</property>
<property name="openLinks">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QStatusBar" name="statusBar"/>
@ -351,9 +376,10 @@
<tabstops>
<tabstop>startButton</tabstop>
<tabstop>stopButton</tabstop>
<tabstop>restartButton</tabstop>
<tabstop>clearlogButton</tabstop>
</tabstops>
<resources/>
<resources>
<include location="../resources.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -182,7 +182,7 @@ void PrefrencesWindow::on_languageComboBox_currentTextChanged(const QString &arg
CurrentConfig.language = arg1.toStdString();
if (QApplication::installTranslator(getTranslator(QString::fromStdString(arg1.toStdString())))) {
LOG("Loaded translations " + arg1.toStdString())
LOG(MODULE_UI, "Loaded translations " + arg1.toStdString())
ui->retranslateUi(this);
} else {
//QvMessageBox(this, tr("#Prefrences"), tr("#SwitchTranslationError"));

View File

@ -3,7 +3,7 @@
#include <QDialog>
#include <ui_w_PrefrencesWindow.h>
#include "QvGUIConfigObjects.h"
#include "Qv2rayBase.h"
namespace Ui
{

View File

@ -4,13 +4,12 @@
<context>
<name>ConnectionEditWindow</name>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="26"/>
<source>#ConnectionSettings</source>
<translation>Connection Settings</translation>
<translation type="vanished">Connection Settings</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="37"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="366"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="358"/>
<source>#Host</source>
<translation>Host</translation>
</message>
@ -25,58 +24,64 @@
<translation>Outbound Type</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="109"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="85"/>
<source>Socks</source>
<translation>Socks</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="95"/>
<source>#OutBoundSettings</source>
<translation>OutBound Settings</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="138"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="130"/>
<source>#UUID</source>
<translation>UUID</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="155"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="147"/>
<source>#AlterID</source>
<translation>Alter ID</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="169"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="667"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="161"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="650"/>
<source>#Security</source>
<translation>Security Settings</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="200"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="192"/>
<source>#Transport</source>
<translation>Transport Settings</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="243"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="235"/>
<source>#TransportSettings</source>
<translation>Transport Settings</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="851"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="808"/>
<source>#Email</source>
<translation>Email</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="858"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="815"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="911"/>
<source>#Password</source>
<translation>Password</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="865"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="822"/>
<source>#EncryptionMethod</source>
<translation>Encryption Method</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="917"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="874"/>
<source>#Level</source>
<translation>User Level</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="927"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="884"/>
<source>#OTA</source>
<translation>One Time Auth (Outdated)</translation>
</message>
@ -85,30 +90,29 @@
<translation type="vanished">TCP</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="278"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="591"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="734"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="270"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="575"/>
<source>#Type</source>
<translation>Type</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="287"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="279"/>
<source>#Request</source>
<translation>Request</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="324"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="338"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="330"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="337"/>
<source>#InsertDefaultContent</source>
<translation>Insert Default Content</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="294"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="293"/>
<source>#Response</source>
<translation>Response</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="124"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="116"/>
<source>#UseTLS</source>
<translation>Use TLS</translation>
</message>
@ -117,8 +121,8 @@
<translation type="vanished">Generate JSON</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="331"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="345"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="286"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="300"/>
<source>#Prettify</source>
<translation>Prettify JSON</translation>
</message>
@ -127,9 +131,9 @@
<translation type="vanished">HTTP</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="356"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="382"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="647"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="348"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="374"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="630"/>
<source>#Path</source>
<translation>Path</translation>
</message>
@ -138,13 +142,13 @@
<translation type="vanished">WebSocket</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="398"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="713"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="390"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="696"/>
<source>#Headers</source>
<translation>Headers</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="405"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="397"/>
<source>#key|value format</source>
<translation>Format: KEY|VALUE</translation>
</message>
@ -153,22 +157,22 @@
<translation type="vanished">mKCP</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="421"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="413"/>
<source>#MTU</source>
<translation>MTU</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="447"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="439"/>
<source>#TTI (ms)</source>
<translation>TTI (ms)</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="473"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="465"/>
<source>#UplinkCapacity (MB/s)</source>
<translation>Uplink Capacity (MB/s)</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="496"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="488"/>
<source>#Congestion</source>
<translation>Congestion Control</translation>
</message>
@ -177,53 +181,61 @@
<translation type="vanished">SockOpt</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="790"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="747"/>
<source>#Mark</source>
<translation>Mark</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="800"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="757"/>
<source>#TCPFastOpen</source>
<translation>TCP Fast Open</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="814"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="771"/>
<source>#TProxy</source>
<translation>Transparent Proxy Mode</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="131"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="503"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="807"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="934"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="123"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="495"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="764"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="891"/>
<source>#Enabled</source>
<translation>Enabled</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="90"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="26"/>
<source>#EditConnectionSettings</source>
<translation>Edit Connection Settings</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="921"/>
<source>#Username</source>
<translation>Username</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="941"/>
<source>#JsonPreview</source>
<translation>Preview Generated JSON</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="514"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="506"/>
<source>#DownlinkCapacity (MB/s)</source>
<translation>Downlink Capacity (MB/s)</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="537"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="529"/>
<source>#ReadBufferSize (MB)</source>
<translation>Read Buffer Size (MB)</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="560"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="552"/>
<source>#WriteBufferSize (MB)</source>
<translation>Write Buffer Size (MB)</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="585"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="726"/>
<source>#Header</source>
<translation>Headers</translation>
<translation type="vanished">Headers</translation>
</message>
<message>
<source>DomainSocket</source>
@ -234,19 +246,19 @@
<translation type="vanished">QUIC</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="699"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="682"/>
<source>#Key</source>
<translation>Key</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.cpp" line="370"/>
<location filename="../src/w_ConnectionEditWindow.cpp" line="381"/>
<location filename="../src/w_ConnectionEditWindow.cpp" line="395"/>
<location filename="../src/w_ConnectionEditWindow.cpp" line="406"/>
<source>#JsonPrettify</source>
<translation>Prettify JSON</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.cpp" line="370"/>
<location filename="../src/w_ConnectionEditWindow.cpp" line="381"/>
<location filename="../src/w_ConnectionEditWindow.cpp" line="395"/>
<location filename="../src/w_ConnectionEditWindow.cpp" line="406"/>
<source>#JsonContainsError</source>
<translation>JSON is in a bad syntax</translation>
</message>
@ -358,34 +370,75 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../src/w_MainWindow.ui" line="29"/>
<location filename="../src/w_MainWindow.cpp" line="166"/>
<location filename="../src/w_MainWindow.ui" line="23"/>
<source>Qv2ray</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="53"/>
<location filename="../src/w_MainWindow.ui" line="320"/>
<location filename="../src/w_MainWindow.cpp" line="32"/>
<location filename="../src/w_MainWindow.ui" line="47"/>
<location filename="../src/w_MainWindow.cpp" line="39"/>
<source>#Connect</source>
<translation>Connect</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="57"/>
<location filename="../src/w_MainWindow.cpp" line="41"/>
<source>#Disconnect</source>
<translation>Disconnect</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="110"/>
<source>#CurrentConfigDetail</source>
<translation>Current Connection Details</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="236"/>
<source>#AddConnection</source>
<translation>Add a connection</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="239"/>
<source>A</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="259"/>
<source>I</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="276"/>
<location filename="../src/w_MainWindow.cpp" line="449"/>
<source>#RemoveConnection</source>
<translation>Remove a connection</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="279"/>
<source>R</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="293"/>
<source>...</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="361"/>
<source>#Start</source>
<translation>Start</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="63"/>
<location filename="../src/w_MainWindow.ui" line="325"/>
<location filename="../src/w_MainWindow.cpp" line="34"/>
<location filename="../src/w_MainWindow.ui" line="366"/>
<source>#Stop</source>
<translation>Stop</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="73"/>
<location filename="../src/w_MainWindow.ui" line="330"/>
<location filename="../src/w_MainWindow.cpp" line="33"/>
<location filename="../src/w_MainWindow.ui" line="371"/>
<source>#Restart</source>
<translation>Restart</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="83"/>
<location filename="../src/w_MainWindow.ui" line="64"/>
<source>#ClearLog</source>
<translation>Clear Log</translation>
</message>
@ -394,165 +447,215 @@
<translation type="vanished">Status</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="113"/>
<location filename="../src/w_MainWindow.cpp" line="184"/>
<location filename="../src/w_MainWindow.ui" line="94"/>
<source>#Stopped</source>
<translation>Stopped</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="122"/>
<location filename="../src/w_MainWindow.ui" line="103"/>
<source>#HostList</source>
<translation>Host List</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="169"/>
<location filename="../src/w_MainWindow.ui" line="158"/>
<source>#DetailInfo</source>
<translation>Detail Connection Info</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="179"/>
<location filename="../src/w_MainWindow.ui" line="290"/>
<source>#EditConnection</source>
<translation>Edit Connection</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="202"/>
<location filename="../src/w_MainWindow.ui" line="116"/>
<source>#OutBoundType</source>
<translation>Outbound Type</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="255"/>
<source>#ImportConfig</source>
<translation>Import Config</translation>
<translation type="vanished">Import Config</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="262"/>
<source>#AddConfig</source>
<translation>Add Config</translation>
<translation type="vanished">Add Config</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="269"/>
<source>#RemoveConfig</source>
<translation>Remove Config</translation>
<translation type="vanished">Remove Config</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="129"/>
<source>#ConfigDetail</source>
<translation>Detailed Config Info</translation>
<translation type="vanished">Detailed Config Info</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="141"/>
<location filename="../src/w_MainWindow.ui" line="130"/>
<source>#Host</source>
<translation>Host</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="155"/>
<location filename="../src/w_MainWindow.ui" line="144"/>
<source>#Port</source>
<translation>Port</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="284"/>
<location filename="../src/w_MainWindow.cpp" line="43"/>
<source>#Rename</source>
<translation>Rename</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="196"/>
<source>#Connected</source>
<translation>Connected</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="214"/>
<source>#Disconnected</source>
<translation>Disconnected</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="318"/>
<source>#UUID</source>
<translation>UUID</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="286"/>
<location filename="../src/w_MainWindow.cpp" line="320"/>
<source>#AlterID</source>
<translation>Alter ID</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="288"/>
<location filename="../src/w_MainWindow.cpp" line="322"/>
<source>#Transport</source>
<translation>Transport Settings</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="192"/>
<source>#ConnectionSettings</source>
<translation>Connection Settings</translation>
<translation type="vanished">Connection Settings</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="278"/>
<location filename="../src/w_MainWindow.ui" line="319"/>
<source>#Log</source>
<translation>Log</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="300"/>
<location filename="../src/w_MainWindow.ui" line="341"/>
<source>#ManuallyCreateConnection</source>
<translation>Manually Create Connection</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="305"/>
<location filename="../src/w_MainWindow.ui" line="256"/>
<location filename="../src/w_MainWindow.ui" line="346"/>
<source>#ImportConnection</source>
<translation>Import Config File</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="310"/>
<location filename="../src/w_MainWindow.ui" line="351"/>
<source>#Exit</source>
<translation>Exit</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="90"/>
<location filename="../src/w_MainWindow.ui" line="315"/>
<location filename="../src/w_MainWindow.ui" line="71"/>
<location filename="../src/w_MainWindow.ui" line="356"/>
<source>#Preferences</source>
<translation>Preferences</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="30"/>
<location filename="../src/w_MainWindow.cpp" line="244"/>
<location filename="../src/w_MainWindow.cpp" line="37"/>
<location filename="../src/w_MainWindow.cpp" line="278"/>
<source>#Hide</source>
<translation>Hide</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="31"/>
<location filename="../src/w_MainWindow.cpp" line="38"/>
<source>#Quit</source>
<translation>Quit</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="96"/>
<location filename="../src/w_MainWindow.cpp" line="97"/>
<location filename="../src/w_MainWindow.cpp" line="40"/>
<source>#Reconnect</source>
<translation>Reconnect</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="44"/>
<source>#ConnectSelected</source>
<translation>Connect selected item</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="119"/>
<location filename="../src/w_MainWindow.cpp" line="120"/>
<source>#NewReleaseVersionFound</source>
<translation>Found a newer version</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="103"/>
<location filename="../src/w_MainWindow.cpp" line="126"/>
<source>#ReleaseDownloadLink</source>
<translation>New version download link</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="155"/>
<location filename="../src/w_MainWindow.cpp" line="373"/>
<location filename="../src/w_MainWindow.cpp" line="183"/>
<location filename="../src/w_MainWindow.cpp" line="489"/>
<source>#NoConfigSelected</source>
<translation>No Config Selected</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="155"/>
<location filename="../src/w_MainWindow.cpp" line="373"/>
<location filename="../src/w_MainWindow.cpp" line="183"/>
<location filename="../src/w_MainWindow.cpp" line="489"/>
<source>#PleaseSelectAConfig</source>
<translation>Please select a config from the list</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="166"/>
<location filename="../src/w_MainWindow.cpp" line="194"/>
<location filename="../src/w_MainWindow.cpp" line="195"/>
<source>#ConnectedToServer</source>
<translation>Connected to server</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="413"/>
<location filename="../src/w_MainWindow.cpp" line="422"/>
<source>#RenameConnection</source>
<translation>Rename a connection</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="413"/>
<source>#CannotUseEmptyName</source>
<translation>You cannot use an empty connection name</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="422"/>
<source>#DuplicatedConnectionName</source>
<translation>Connection name is duplicated</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="449"/>
<source>#RemoveConnectionConfirm</source>
<translation>Are you sure want to remove this connection</translation>
</message>
<message>
<source>#ConnectedToServer </source>
<translation>Connected to server </translation>
<translation type="vanished">Connected to server </translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="167"/>
<source>#Started</source>
<translation>Started</translation>
<translation type="vanished">Started</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="295"/>
<location filename="../src/w_MainWindow.cpp" line="329"/>
<source>#Email</source>
<translation>Email</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="297"/>
<location filename="../src/w_MainWindow.cpp" line="331"/>
<source>#Encryption</source>
<translation>Encryption</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="74"/>
<location filename="../src/w_MainWindow.cpp" line="204"/>
<location filename="../src/w_MainWindow.cpp" line="247"/>
<location filename="../src/w_MainWindow.cpp" line="338"/>
<source>#Username</source>
<translation>Username</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="91"/>
<location filename="../src/w_MainWindow.cpp" line="234"/>
<location filename="../src/w_MainWindow.cpp" line="281"/>
<source>#Show</source>
<translation>Show</translation>
</message>
@ -830,12 +933,7 @@
<translation type="vanished">Another instance is already running</translation>
</message>
<message>
<location filename="../src/main.cpp" line="104"/>
<source>Qv2ray</source>
<translation></translation>
</message>
<message>
<location filename="../src/main.cpp" line="104"/>
<location filename="../src/main.cpp" line="130"/>
<source>#AnotherInstanceRunning</source>
<translation>Another instance is already running</translation>
</message>

View File

@ -4,13 +4,12 @@
<context>
<name>ConnectionEditWindow</name>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="26"/>
<source>#ConnectionSettings</source>
<translation></translation>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="37"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="366"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="358"/>
<source>#Host</source>
<translation></translation>
</message>
@ -25,58 +24,64 @@
<translation></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="109"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="85"/>
<source>Socks</source>
<translation>Socks</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="95"/>
<source>#OutBoundSettings</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="138"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="130"/>
<source>#UUID</source>
<translation>UUID</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="155"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="147"/>
<source>#AlterID</source>
<translation>Alter ID</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="169"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="667"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="161"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="650"/>
<source>#Security</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="200"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="192"/>
<source>#Transport</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="243"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="235"/>
<source>#TransportSettings</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="851"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="808"/>
<source>#Email</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="858"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="815"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="911"/>
<source>#Password</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="865"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="822"/>
<source>#EncryptionMethod</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="917"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="874"/>
<source>#Level</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="927"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="884"/>
<source>#OTA</source>
<translation> ()</translation>
</message>
@ -85,30 +90,29 @@
<translation type="vanished">TCP</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="278"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="591"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="734"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="270"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="575"/>
<source>#Type</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="287"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="279"/>
<source>#Request</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="324"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="338"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="330"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="337"/>
<source>#InsertDefaultContent</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="294"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="293"/>
<source>#Response</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="124"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="116"/>
<source>#UseTLS</source>
<translation>使 TLS</translation>
</message>
@ -117,8 +121,8 @@
<translation type="vanished"> JSON</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="331"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="345"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="286"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="300"/>
<source>#Prettify</source>
<translation> JSON</translation>
</message>
@ -127,9 +131,9 @@
<translation type="vanished">HTTP</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="356"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="382"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="647"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="348"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="374"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="630"/>
<source>#Path</source>
<translation></translation>
</message>
@ -138,13 +142,13 @@
<translation type="vanished">WebSocket</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="398"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="713"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="390"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="696"/>
<source>#Headers</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="405"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="397"/>
<source>#key|value format</source>
<translation>|</translation>
</message>
@ -153,22 +157,22 @@
<translation type="vanished">mKCP</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="421"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="413"/>
<source>#MTU</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="447"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="439"/>
<source>#TTI (ms)</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="473"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="465"/>
<source>#UplinkCapacity (MB/s)</source>
<translation> (MB/s)</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="496"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="488"/>
<source>#Congestion</source>
<translation></translation>
</message>
@ -177,53 +181,61 @@
<translation type="vanished">SockOpt</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="790"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="747"/>
<source>#Mark</source>
<translation>Mark</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="800"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="757"/>
<source>#TCPFastOpen</source>
<translation>TCP Fast Open</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="814"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="771"/>
<source>#TProxy</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="131"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="503"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="807"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="934"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="123"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="495"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="764"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="891"/>
<source>#Enabled</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="90"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="26"/>
<source>#EditConnectionSettings</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="921"/>
<source>#Username</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="941"/>
<source>#JsonPreview</source>
<translation>JSON预览</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="514"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="506"/>
<source>#DownlinkCapacity (MB/s)</source>
<translation> (MB/s)</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="537"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="529"/>
<source>#ReadBufferSize (MB)</source>
<translation> (MB)</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="560"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="552"/>
<source>#WriteBufferSize (MB)</source>
<translation> (MB)</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="585"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="726"/>
<source>#Header</source>
<translation></translation>
<translation type="vanished"></translation>
</message>
<message>
<source>DomainSocket</source>
@ -234,19 +246,19 @@
<translation type="vanished">QUIC</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.ui" line="699"/>
<location filename="../src/w_ConnectionEditWindow.ui" line="682"/>
<source>#Key</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.cpp" line="370"/>
<location filename="../src/w_ConnectionEditWindow.cpp" line="381"/>
<location filename="../src/w_ConnectionEditWindow.cpp" line="395"/>
<location filename="../src/w_ConnectionEditWindow.cpp" line="406"/>
<source>#JsonPrettify</source>
<translation> JSON</translation>
</message>
<message>
<location filename="../src/w_ConnectionEditWindow.cpp" line="370"/>
<location filename="../src/w_ConnectionEditWindow.cpp" line="381"/>
<location filename="../src/w_ConnectionEditWindow.cpp" line="395"/>
<location filename="../src/w_ConnectionEditWindow.cpp" line="406"/>
<source>#JsonContainsError</source>
<translation>JSON </translation>
</message>
@ -358,34 +370,75 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../src/w_MainWindow.ui" line="29"/>
<location filename="../src/w_MainWindow.cpp" line="166"/>
<location filename="../src/w_MainWindow.ui" line="23"/>
<source>Qv2ray</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="53"/>
<location filename="../src/w_MainWindow.ui" line="320"/>
<location filename="../src/w_MainWindow.cpp" line="32"/>
<location filename="../src/w_MainWindow.ui" line="47"/>
<location filename="../src/w_MainWindow.cpp" line="39"/>
<source>#Connect</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="57"/>
<location filename="../src/w_MainWindow.cpp" line="41"/>
<source>#Disconnect</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="110"/>
<source>#CurrentConfigDetail</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="236"/>
<source>#AddConnection</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="239"/>
<source>A</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="259"/>
<source>I</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="276"/>
<location filename="../src/w_MainWindow.cpp" line="449"/>
<source>#RemoveConnection</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="279"/>
<source>R</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="293"/>
<source>...</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="361"/>
<source>#Start</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="63"/>
<location filename="../src/w_MainWindow.ui" line="325"/>
<location filename="../src/w_MainWindow.cpp" line="34"/>
<location filename="../src/w_MainWindow.ui" line="366"/>
<source>#Stop</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="73"/>
<location filename="../src/w_MainWindow.ui" line="330"/>
<location filename="../src/w_MainWindow.cpp" line="33"/>
<location filename="../src/w_MainWindow.ui" line="371"/>
<source>#Restart</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="83"/>
<location filename="../src/w_MainWindow.ui" line="64"/>
<source>#ClearLog</source>
<translation></translation>
</message>
@ -394,165 +447,215 @@
<translation type="vanished"></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="113"/>
<location filename="../src/w_MainWindow.cpp" line="184"/>
<location filename="../src/w_MainWindow.ui" line="94"/>
<source>#Stopped</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="122"/>
<location filename="../src/w_MainWindow.ui" line="103"/>
<source>#HostList</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="169"/>
<location filename="../src/w_MainWindow.ui" line="158"/>
<source>#DetailInfo</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="179"/>
<location filename="../src/w_MainWindow.ui" line="290"/>
<source>#EditConnection</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="202"/>
<location filename="../src/w_MainWindow.ui" line="116"/>
<source>#OutBoundType</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="255"/>
<source>#ImportConfig</source>
<translation></translation>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="262"/>
<source>#AddConfig</source>
<translation></translation>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="269"/>
<source>#RemoveConfig</source>
<translation></translation>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="129"/>
<source>#ConfigDetail</source>
<translation></translation>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="141"/>
<location filename="../src/w_MainWindow.ui" line="130"/>
<source>#Host</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="155"/>
<location filename="../src/w_MainWindow.ui" line="144"/>
<source>#Port</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="284"/>
<location filename="../src/w_MainWindow.cpp" line="43"/>
<source>#Rename</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="196"/>
<source>#Connected</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="214"/>
<source>#Disconnected</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="318"/>
<source>#UUID</source>
<translation>UUID</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="286"/>
<location filename="../src/w_MainWindow.cpp" line="320"/>
<source>#AlterID</source>
<translation>Alter ID</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="288"/>
<location filename="../src/w_MainWindow.cpp" line="322"/>
<source>#Transport</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="192"/>
<source>#ConnectionSettings</source>
<translation></translation>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="278"/>
<location filename="../src/w_MainWindow.ui" line="319"/>
<source>#Log</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="300"/>
<location filename="../src/w_MainWindow.ui" line="341"/>
<source>#ManuallyCreateConnection</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="305"/>
<location filename="../src/w_MainWindow.ui" line="256"/>
<location filename="../src/w_MainWindow.ui" line="346"/>
<source>#ImportConnection</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="310"/>
<location filename="../src/w_MainWindow.ui" line="351"/>
<source>#Exit</source>
<translation>退</translation>
</message>
<message>
<location filename="../src/w_MainWindow.ui" line="90"/>
<location filename="../src/w_MainWindow.ui" line="315"/>
<location filename="../src/w_MainWindow.ui" line="71"/>
<location filename="../src/w_MainWindow.ui" line="356"/>
<source>#Preferences</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="30"/>
<location filename="../src/w_MainWindow.cpp" line="244"/>
<location filename="../src/w_MainWindow.cpp" line="37"/>
<location filename="../src/w_MainWindow.cpp" line="278"/>
<source>#Hide</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="31"/>
<location filename="../src/w_MainWindow.cpp" line="38"/>
<source>#Quit</source>
<translation>退</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="96"/>
<location filename="../src/w_MainWindow.cpp" line="97"/>
<location filename="../src/w_MainWindow.cpp" line="40"/>
<source>#Reconnect</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="44"/>
<source>#ConnectSelected</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="119"/>
<location filename="../src/w_MainWindow.cpp" line="120"/>
<source>#NewReleaseVersionFound</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="103"/>
<location filename="../src/w_MainWindow.cpp" line="126"/>
<source>#ReleaseDownloadLink</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="155"/>
<location filename="../src/w_MainWindow.cpp" line="373"/>
<location filename="../src/w_MainWindow.cpp" line="183"/>
<location filename="../src/w_MainWindow.cpp" line="489"/>
<source>#NoConfigSelected</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="155"/>
<location filename="../src/w_MainWindow.cpp" line="373"/>
<location filename="../src/w_MainWindow.cpp" line="183"/>
<location filename="../src/w_MainWindow.cpp" line="489"/>
<source>#PleaseSelectAConfig</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="166"/>
<location filename="../src/w_MainWindow.cpp" line="194"/>
<location filename="../src/w_MainWindow.cpp" line="195"/>
<source>#ConnectedToServer</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="413"/>
<location filename="../src/w_MainWindow.cpp" line="422"/>
<source>#RenameConnection</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="413"/>
<source>#CannotUseEmptyName</source>
<translation>使</translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="422"/>
<source>#DuplicatedConnectionName</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="449"/>
<source>#RemoveConnectionConfirm</source>
<translation></translation>
</message>
<message>
<source>#ConnectedToServer </source>
<translation> </translation>
<translation type="vanished"> </translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="167"/>
<source>#Started</source>
<translation></translation>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="295"/>
<location filename="../src/w_MainWindow.cpp" line="329"/>
<source>#Email</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="297"/>
<location filename="../src/w_MainWindow.cpp" line="331"/>
<source>#Encryption</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="74"/>
<location filename="../src/w_MainWindow.cpp" line="204"/>
<location filename="../src/w_MainWindow.cpp" line="247"/>
<location filename="../src/w_MainWindow.cpp" line="338"/>
<source>#Username</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_MainWindow.cpp" line="91"/>
<location filename="../src/w_MainWindow.cpp" line="234"/>
<location filename="../src/w_MainWindow.cpp" line="281"/>
<source>#Show</source>
<translation></translation>
</message>
@ -830,12 +933,7 @@
<translation type="vanished"></translation>
</message>
<message>
<location filename="../src/main.cpp" line="104"/>
<source>Qv2ray</source>
<translation></translation>
</message>
<message>
<location filename="../src/main.cpp" line="104"/>
<location filename="../src/main.cpp" line="130"/>
<source>#AnotherInstanceRunning</source>
<translation></translation>
</message>