[Added] Import config from file.

This commit is contained in:
Leroy.H.Y 2019-07-07 12:18:56 +08:00
parent e16466ffe9
commit 220f202c61
No known key found for this signature in database
GPG Key ID: 6AC1673B587DC37D
16 changed files with 402 additions and 456 deletions

View File

@ -10,6 +10,8 @@
#define DROOT QJsonObject root; #define DROOT QJsonObject root;
#define RROOT return root; #define RROOT return root;
#define JSON_ROOT_TRY_REMOVE(obj) if (root.contains(obj)) { root.remove(obj); }
namespace Qv2ray namespace Qv2ray
{ {
namespace ConfigOperations namespace ConfigOperations
@ -32,15 +34,24 @@ namespace Qv2ray
// //
// Misc // Misc
template<typename T> template<typename T>
QJsonObject GetRootObject(T out); QJsonObject GetRootObject(T t)
{
auto json = StructToJSON(t);
QJsonDocument doc = QJsonDocument::fromJson(QByteArray::fromStdString(json.toStdString()));
return doc.object();
}
template QJsonObject GetRootObject<StreamSettingsObject>(StreamSettingsObject t);
template QJsonObject GetRootObject<VMessOut>(VMessOut t);
// //
// -------------------------- BEGIN CONFIG VALIDATIONS --------------------------------------------- // -------------------------- BEGIN CONFIG VALIDATIONS ---------------------------------------------
int VerifyVMessProtocolString(QString vmess); int VerifyVMessProtocolString(QString vmess);
//
// -------------------------- BEGIN CONFIG CONVERSIONS --------------------------------------------- // -------------------------- BEGIN CONFIG CONVERSIONS ---------------------------------------------
// Save Connection Config // Save Connection Config
int SaveConnectionConfig(QJsonObject obj, const QString *alias); int SaveConnectionConfig(QJsonObject obj, const QString *alias);
// VMess Protocol // VMess Protocol
QJsonObject ConvertOutboundFromVMessString(QString vmess); QJsonObject ConvertConfigFromVMessString(QString vmess);
QJsonObject ConvertConfigFromFile(QString sourceFilePath, bool overrideInbounds);
} }
} }

View File

@ -17,5 +17,112 @@ namespace Qv2ray
SaveStringToFile(doc.toJson(), &config); SaveStringToFile(doc.toJson(), &config);
return 0; return 0;
} }
// This generates an "OutBoundObject"
QJsonObject ConvertConfigFromVMessString(QString str)
{
DROOT
QStringRef vmessJsonB64(&str, 8, str.length() - 8);
auto vmessConf = StructFromJSON<VMessProtocolConfigObject>(Base64Decode(vmessJsonB64.toString()).toStdString());
VMessOut vConf;
VMessOut::ServerObject serv;
serv.port = stoi(vmessConf.port);
serv.address = vmessConf.add;
// User
VMessOut::ServerObject::UserObject user;
user.id = vmessConf.id;
user.alterId = stoi(vmessConf.aid);
// Server
serv.users.push_back(user);
// VMess root config
vConf.vnext.push_back(serv);
//
// Stream Settings
StreamSettingsObject streaming;
// Fill hosts for HTTP
foreach (auto host, QString::fromStdString(vmessConf.host).split(',')) {
streaming.httpSettings.host.push_back(host.toStdString());
}
// hosts for ws, h2 and security for QUIC
streaming.wsSettings.headers.insert(make_pair("Host", vmessConf.host));
streaming.quicSettings.security = vmessConf.host;
//
// Fake type for tcp, kcp and QUIC
streaming.tcpSettings.header.type = vmessConf.type;
streaming.kcpSettings.header.type = vmessConf.type;
streaming.quicSettings.header.type = vmessConf.type;
//
// Path for ws, h2, Quic
streaming.wsSettings.path = vmessConf.path;
streaming.httpSettings.path = vmessConf.path;
streaming.quicSettings.key = vmessConf.path;
streaming.security = vmessConf.tls;
//
// Network type
streaming.network = vmessConf.net;
//
// Root
root.insert("sendThrough", "0.0.0.0");
root.insert("protocol", "vmess");
root.insert("settings", GetRootObject(vConf));
root.insert("tag", OUTBOUND_TAG_PROXY);
root.insert("streamSettings", GetRootObject(streaming));
root.insert("QV2RAY_ALIAS", QString::fromStdString(vmessConf.ps));
RROOT
}
QJsonObject ConvertConfigFromFile(QString sourceFilePath, bool overrideInbounds)
{
auto globalConf = GetGlobalConfig();
QFile configFile(sourceFilePath);
configFile.open(QIODevice::ReadOnly | QIODevice::ExistingOnly);
QByteArray allData = configFile.readAll();
configFile.close();
QJsonDocument v2conf = QJsonDocument::fromJson(allData);
QJsonObject root = v2conf.object();
if (overrideInbounds) {
JSON_ROOT_TRY_REMOVE("inbounds")
}
//
JSON_ROOT_TRY_REMOVE("log")
JSON_ROOT_TRY_REMOVE("api")
JSON_ROOT_TRY_REMOVE("stats")
JSON_ROOT_TRY_REMOVE("policy")
JSON_ROOT_TRY_REMOVE("dns")
//
return root;
}
/*
* {
QFile configFile(path);
if (!configFile.open(QIODevice::ReadOnly)) {
QvMessageBox(this, tr("ImportConfig"), tr("CannotOpenFile"));
qDebug() << "ImportConfig::CannotOpenFile";
return -1;
}
QByteArray allData = configFile.readAll();
configFile.close();
QJsonDocument v2conf(QJsonDocument::fromJson(allData));
QJsonObject rootobj = v2conf.object();
QJsonObject outbound;
if (rootobj.contains("outbounds")) {
outbound = rootobj.value("outbounds").toArray().first().toObject();
} else {
outbound = rootobj.value("outbound").toObject();
}
if (!QFile::copy(path, "newFile")) {
QvMessageBox(this, tr("ImportConfig"), tr("CannotCopyCustomConfig"));
qDebug() << "ImportConfig::CannotCopyCustomConfig";
}
}
*/
} }
} }

View File

@ -62,14 +62,6 @@ namespace Qv2ray
RROOT RROOT
} }
template<typename T>
QJsonObject GetRootObject(T out)
{
auto json = StructToJSON(out);
QJsonDocument doc = QJsonDocument::fromJson(QByteArray::fromStdString(json.toStdString()));
return doc.object();
}
QJsonObject GenerateShadowSocksServerOUT(QString email, QString address, int port, QString method, QString password, bool ota, int level) QJsonObject GenerateShadowSocksServerOUT(QString email, QString address, int port, QString method, QString password, bool ota, int level)
{ {
DROOT DROOT
@ -122,62 +114,6 @@ namespace Qv2ray
JADD(auth, accounts, udp, ip, userLevel) JADD(auth, accounts, udp, ip, userLevel)
RROOT RROOT
} }
// This generates an "OutBoundObject"
QJsonObject ConvertOutboundFromVMessString(QString str)
{
DROOT
QStringRef vmessJsonB64(&str, 8, str.length() - 8);
auto vmessConf = StructFromJSON<VMessProtocolConfigObject>(Base64Decode(vmessJsonB64.toString()).toStdString());
VMessOut vConf;
VMessOut::ServerObject serv;
serv.port = stoi(vmessConf.port);
serv.address = vmessConf.add;
// User
VMessOut::ServerObject::UserObject user;
user.id = vmessConf.id;
user.alterId = stoi(vmessConf.aid);
// Server
serv.users.push_back(user);
// VMess root config
vConf.vnext.push_back(serv);
//
// Stream Settings
StreamSettingsObject streaming;
// Fill hosts for HTTP
foreach (auto host, QString::fromStdString(vmessConf.host).split(',')) {
streaming.httpSettings.host.push_back(host.toStdString());
}
// hosts for ws, h2 and security for QUIC
streaming.wsSettings.headers.insert(make_pair("Host", vmessConf.host));
streaming.quicSettings.security = vmessConf.host;
//
// Fake type for tcp, kcp and QUIC
streaming.tcpSettings.header.type = vmessConf.type;
streaming.kcpSettings.header.type = vmessConf.type;
streaming.quicSettings.header.type = vmessConf.type;
//
// Path for ws, h2, Quic
streaming.wsSettings.path = vmessConf.path;
streaming.httpSettings.path = vmessConf.path;
streaming.quicSettings.key = vmessConf.path;
streaming.security = vmessConf.tls;
//
// Network type
streaming.network = vmessConf.net;
//
// Root
root.insert("sendThrough", "0.0.0.0");
root.insert("protocol", "vmess");
root.insert("settings", GetRootObject(vConf));
root.insert("tag", OUTBOUND_TAG_PROXY);
root.insert("streamSettings", GetRootObject(streaming));
root.insert("QV2RAY_ALIAS", QString::fromStdString(vmessConf.ps));
RROOT
}
// -------------------------- END CONFIG GENERATIONS ------------------------------------------------------------------------------ // -------------------------- END CONFIG GENERATIONS ------------------------------------------------------------------------------
} }
} }

View File

@ -5,11 +5,14 @@
namespace Qv2ray namespace Qv2ray
{ {
bool Qv2Instance::checkConfigFile(const QString path) bool Qv2Instance::VerifyVConfigFile(const QString path)
{ {
if (checkCoreExe()) { if (ValidateV2rayCoreExe()) {
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
env.insert("V2RAY_LOCATION_ASSET", QString::fromStdString(GetGlobalConfig().v2AssetsPath));
QProcess process; QProcess process;
process.start(QString::fromStdString(Utils::GetGlobalConfig().v2Path), QStringList() << "-test" process.setProcessEnvironment(env);
process.start(QString::fromStdString(Utils::GetGlobalConfig().v2CorePath), QStringList() << "-test"
<< "-config" << path, << "-config" << path,
QIODevice::ReadWrite | QIODevice::Text); QIODevice::ReadWrite | QIODevice::Text);
@ -37,9 +40,9 @@ namespace Qv2ray
Status = STOPPED; Status = STOPPED;
} }
bool Qv2Instance::checkCoreExe() bool Qv2Instance::ValidateV2rayCoreExe()
{ {
auto path = QString::fromStdString(Utils::GetGlobalConfig().v2Path); auto path = QString::fromStdString(Utils::GetGlobalConfig().v2CorePath);
if (!QFile::exists(path)) { if (!QFile::exists(path)) {
Utils::QvMessageBox(nullptr, QObject::tr("CoreNotFound"), QObject::tr("CoreFileNotFoundExplainationAt:") + path); Utils::QvMessageBox(nullptr, QObject::tr("CoreNotFound"), QObject::tr("CoreFileNotFoundExplainationAt:") + path);
@ -47,7 +50,7 @@ namespace Qv2ray
} else return true; } else return true;
} }
bool Qv2Instance::start() bool Qv2Instance::Start()
{ {
if (Status != STOPPED) { if (Status != STOPPED) {
return false; return false;
@ -55,23 +58,28 @@ namespace Qv2ray
Status = STARTING; Status = STARTING;
if (checkCoreExe()) { if (ValidateV2rayCoreExe()) {
if (checkConfigFile(QV2RAY_GENERATED_CONFIG_DIRPATH + "config.json")) { if (VerifyVConfigFile(QV2RAY_GENERATED_CONFIG_DIRPATH + "config.json")) {
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
env.insert("V2RAY_LOCATION_ASSET", QString::fromStdString(GetGlobalConfig().v2AssetsPath));
vProcess->setProcessEnvironment(env);
vProcess->start(QString::fromStdString(_config.v2CorePath), QStringList() << "-config"
<< QV2RAY_GENERATED_CONFIG_DIRPATH + "config.json",
QIODevice::ReadWrite | QIODevice::Text);
vProcess->waitForStarted();
Status = STARTED;
return true;
} else {
Status = STOPPED;
return false;
} }
vProcess->start(QString::fromStdString(_config.v2Path), QStringList() << "-config"
<< QV2RAY_GENERATED_CONFIG_DIRPATH + "config.json",
QIODevice::ReadWrite | QIODevice::Text);
vProcess->waitForStarted();
Status = STARTED;
return true;
} else { } else {
Status = STOPPED; Status = STOPPED;
return false; return false;
} }
} }
void Qv2Instance::stop() void Qv2Instance::Stop()
{ {
vProcess->close(); vProcess->close();
Status = STOPPED; Status = STOPPED;
@ -84,7 +92,7 @@ namespace Qv2ray
Qv2Instance::~Qv2Instance() Qv2Instance::~Qv2Instance()
{ {
stop(); Stop();
delete vProcess; delete vProcess;
} }
} }

View File

@ -17,13 +17,13 @@ namespace Qv2ray
public: public:
explicit Qv2Instance(QWidget *parent = nullptr); explicit Qv2Instance(QWidget *parent = nullptr);
bool start(); bool Start();
void stop(); void Stop();
QString readOutput(); QString readOutput();
V2RAY_INSTANCE_STARTUP_STATUS Status; V2RAY_INSTANCE_STARTUP_STATUS Status;
static bool checkConfigFile(QString path); static bool VerifyVConfigFile(QString path);
static bool checkCoreExe(); static bool ValidateV2rayCoreExe();
~Qv2Instance(); ~Qv2Instance();
private: private:

View File

@ -41,22 +41,24 @@ namespace Qv2ray
struct Qv2Config { struct Qv2Config {
string language; string language;
bool runAsRoot; bool runAsRoot;
string logLevel; int logLevel;
string v2Path; string v2CorePath;
string v2AssetsPath;
QvInbondSetting httpSetting; QvInbondSetting httpSetting;
QvInbondSetting socksSetting; QvInbondSetting socksSetting;
list<string> configs; list<string> configs;
Qv2Config(): language(), runAsRoot(), logLevel(), httpSetting(), socksSetting(), configs() { } Qv2Config(): httpSetting(), socksSetting(), configs() { }
Qv2Config(string lang, string exePath, string log, QvInbondSetting httpIn, QvInbondSetting socksIN): Qv2Config() Qv2Config(string lang, string exePath, string assetsPath, int log, QvInbondSetting httpIn, QvInbondSetting socksIN): Qv2Config()
{ {
v2Path = exePath;
language = lang; language = lang;
v2CorePath = exePath;
v2AssetsPath = assetsPath;
logLevel = log; logLevel = log;
httpSetting = httpIn; httpSetting = httpIn;
socksSetting = socksIN; socksSetting = socksIN;
runAsRoot = false; runAsRoot = false;
} }
XTOSTRUCT(O(language, v2Path, runAsRoot, logLevel, httpSetting, socksSetting, configs)) XTOSTRUCT(O(language, v2CorePath, v2AssetsPath, runAsRoot, logLevel, httpSetting, socksSetting, configs))
}; };
} }
} }

View File

@ -78,14 +78,17 @@ namespace Qv2ray
{ {
return dir->entryList(QStringList() << "*" << "*.*", QDir::Hidden | QDir::Files); return dir->entryList(QStringList() << "*" << "*.*", QDir::Hidden | QDir::Files);
} }
bool CheckFile(QDir *dir, QString fileName) bool CheckFile(QDir *dir, QString fileName)
{ {
return GetFileList(dir).indexOf(fileName) >= 0; return GetFileList(dir).indexOf(fileName) >= 0;
} }
void QvMessageBox(QWidget *parent, QString title, QString text) void QvMessageBox(QWidget *parent, QString title, QString text)
{ {
QMessageBox::warning(parent, title, text, QMessageBox::Ok | QMessageBox::Default, 0); QMessageBox::warning(parent, title, text, QMessageBox::Ok | QMessageBox::Default, 0);
} }
QTranslator *getTranslator(QString lang) QTranslator *getTranslator(QString lang)
{ {
QTranslator *translator = new QTranslator(); QTranslator *translator = new QTranslator();

View File

@ -16,17 +16,20 @@ bool initializeQv()
/// Qv2ray Config Path and ends with "/" /// Qv2ray Config Path and ends with "/"
QString configPath = ""; QString configPath = "";
QString exeDefaultPath = ""; QString exeDefaultPath = "";
QString v2AssetsPath = "";
#if defined(__WIN32) || defined(__APPLE__) #if defined(__WIN32) || defined(__APPLE__)
// For Windows and MacOS, there's no such 'installation' of a software // For Windows and MacOS, there's no such 'installation' of a software
// package, So as what ShadowSocks and v2rayX does, save config files next to // package, So as what ShadowSocks and v2rayX does, save config files next to
// the executable. // the executable.
configPath = "./qv2ray.conf.d"; configPath = "./qv2ray.d";
exeDefaultPath = "./v2ray"; exeDefaultPath = "./qv2ray.d/v2ray";
v2AssetsPath = "./qv2ray.d";
#else #else
// However, for linux, this software can be and/or will be provided as a // However, for linux, this software can be and/or will be provided as a
// package and install to whatever /usr/bin or /usr/local/bin or even /opt/ // package and install to whatever /usr/bin or /usr/local/bin or even /opt/
// Thus we save config files in the user's home directory. // Thus we save config files in the user's home directory.
configPath = QDir::homePath() + "/.qv2ray/"; configPath = QDir::homePath() + "/.qv2ray";
v2AssetsPath = "/etc/v2ray";
exeDefaultPath = "/bin/v2ray"; exeDefaultPath = "/bin/v2ray";
#endif #endif
SetConfigDirPath(configPath); SetConfigDirPath(configPath);
@ -60,7 +63,7 @@ bool initializeQv()
// These below genenrated very basic global config. // These below genenrated very basic global config.
QvInbondSetting inHttp = QvInbondSetting(true, "127.0.0.1", 8080); QvInbondSetting inHttp = QvInbondSetting(true, "127.0.0.1", 8080);
QvInbondSetting inSocks = QvInbondSetting(true, "127.0.0.1", 1080); QvInbondSetting inSocks = QvInbondSetting(true, "127.0.0.1", 1080);
Qv2Config conf = Qv2Config("zh-CN", exeDefaultPath.toStdString(), "info", inHttp, inSocks); Qv2Config conf = Qv2Config("zh-CN", exeDefaultPath.toStdString(), v2AssetsPath.toStdString(), 2, inHttp, inSocks);
// //
// Save initial config. // Save initial config.
SetGlobalConfig(conf); SetGlobalConfig(conf);

View File

@ -25,84 +25,56 @@ ImportConfigWindow::~ImportConfigWindow()
delete ui; delete ui;
} }
void ImportConfigWindow::on_pushButton_clicked() void ImportConfigWindow::on_importSourceCombo_currentIndexChanged(int index)
{
ui->stackedWidget->setCurrentIndex(index);
}
void ImportConfigWindow::on_selectFileBtn_clicked()
{ {
QString dir = QFileDialog::getOpenFileName(this, tr("OpenConfigFile"), "~/"); QString dir = QFileDialog::getOpenFileName(this, tr("OpenConfigFile"), "~/");
ui->fileLineTxt->setText(dir); ui->fileLineTxt->setText(dir);
} }
void ImportConfigWindow::savefromFile(QString path, QString alias) void ImportConfigWindow::on_buttonBox_clicked(QAbstractButton *button)
{
Q_UNUSED(path)
Q_UNUSED(alias)
QFile configFile(path);
if (!configFile.open(QIODevice::ReadOnly)) {
QvMessageBox(this, tr("ImportConfig"), tr("CannotOpenFile"));
qDebug() << "ImportConfig::CannotOpenFile";
return;
}
QByteArray allData = configFile.readAll();
configFile.close();
QJsonDocument v2conf(QJsonDocument::fromJson(allData));
QJsonObject rootobj = v2conf.object();
QJsonObject outbound;
if (rootobj.contains("outbounds")) {
outbound = rootobj.value("outbounds").toArray().first().toObject();
} else {
outbound = rootobj.value("outbound").toObject();
}
if (!QFile::copy(path, "newFile")) {
QvMessageBox(this, tr("ImportConfig"), tr("CannotCopyCustomConfig"));
qDebug() << "ImportConfig::CannotCopyCustomConfig";
}
}
void ImportConfigWindow::on_buttonBox_accepted()
{ {
QString alias = ui->nameTxt->text(); QString alias = ui->nameTxt->text();
QJsonObject config;
if (ui->importSourceCombo->currentIndex() == 0) { // From File... if (ui->importSourceCombo->currentIndex() == 0) { // From File...
bool overrideInBound = ui->useCurrentSettingRidBtn->isChecked(); bool overrideInBound = ui->keepInboundCheckBox->isChecked();
on_verifyFileBtn_clicked();
if (!Qv2Instance::VerifyVConfigFile(ui->fileLineTxt->text())) {
QvMessageBox(this, tr("#InvalidConfigFile"), tr("ConfigFileCheckFailed"));
return;
}
QString path = ui->fileLineTxt->text(); QString path = ui->fileLineTxt->text();
savefromFile(path, alias); config = ConvertConfigFromFile(path, overrideInBound);
// !!! TODO
} else { } else {
on_verifyVMessBtn_clicked(); QString vmess = ui->vmessConnectionStringTxt->toPlainText();
auto config = ConvertOutboundFromVMessString(ui->vmessConnectionStringTxt->toPlainText()); int result = VerifyVMessProtocolString(vmess);
if (result == 0) {
//QvMessageBox(this, tr("#VMessCheck"), tr("#AbleToImportConfig"));
} else if (result == -1) {
QvMessageBox(this, tr("#VMessCheck"), tr("#NotValidVMessProtocolString"));
done(0);
return;
} else {
QvMessageBox(this, tr("#VMessCheck"), tr("#INTERNAL_ERROR"));
return;
}
config = ConvertConfigFromVMessString(ui->vmessConnectionStringTxt->toPlainText());
//
alias = alias != "" ? alias : config["QV2RAY_ALIAS"].toString(); alias = alias != "" ? alias : config["QV2RAY_ALIAS"].toString();
config.remove("QV2RAY_ALIAS"); config.remove("QV2RAY_ALIAS");
Qv2Config conf = GetGlobalConfig();
conf.configs.push_back(alias.toStdString());
SetGlobalConfig(conf);
SaveConnectionConfig(config, &alias);
emit s_reload_config();
} }
}
void ImportConfigWindow::on_verifyVMessBtn_clicked() Qv2Config conf = GetGlobalConfig();
{ conf.configs.push_back(alias.toStdString());
QString vmess = ui->vmessConnectionStringTxt->toPlainText(); SetGlobalConfig(conf);
int result = VerifyVMessProtocolString(vmess); SaveConnectionConfig(config, &alias);
emit s_reload_config();
if (result == 0) {
QvMessageBox(this, tr("#VMessCheck"), tr("#AbleToImportConfig"));
} else if (result == -1) {
QvMessageBox(this, tr("#VMessCheck"), tr("#NotValidVMessProtocolString"));
} else {
QvMessageBox(this, tr("#VMessCheck"), tr("#INTERNAL_ERROR"));
}
}
void ImportConfigWindow::on_verifyFileBtn_clicked()
{
if (!Qv2Instance::checkConfigFile(ui->fileLineTxt->text())) {
QvMessageBox(this, tr("#InvalidConfigFile"), tr("ConfigFileCheckFailed"));
} else {
QvMessageBox(this, tr("#VConfigFileCheckPassed"), tr("#AbleToImportConfig"));
}
} }

View File

@ -15,18 +15,19 @@ class ImportConfigWindow : public QDialog
public: public:
explicit ImportConfigWindow(QWidget *parent = nullptr); explicit ImportConfigWindow(QWidget *parent = nullptr);
void savefromFile(QString path, QString alias);
~ImportConfigWindow(); ~ImportConfigWindow();
signals: signals:
void s_reload_config(); void s_reload_config();
private slots: private slots:
void on_pushButton_clicked(); void on_importSourceCombo_currentIndexChanged(int index);
void on_buttonBox_accepted();
void on_verifyVMessBtn_clicked(); void on_selectFileBtn_clicked();
void on_verifyFileBtn_clicked();
void on_buttonBox_clicked(QAbstractButton *button);
private: private:
Ui::ImportConfigWindow *ui; Ui::ImportConfigWindow *ui;
}; };
#endif // IMPORTCONF_H #endif // IMPORTCONF_H

View File

@ -6,174 +6,165 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>650</width> <width>370</width>
<height>350</height> <height>420</height>
</rect> </rect>
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>650</width> <width>370</width>
<height>350</height> <height>420</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>370</width>
<height>420</height>
</size> </size>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Import file</string> <string>Import file</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0" columnstretch="1,1"> <property name="sizeGripEnabled">
<item row="0" column="0" colspan="2"> <bool>false</bool>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,6"> </property>
<item> <property name="modal">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="aliasLabel">
<property name="text">
<string>#Name</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="nameTxt"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
<string>#ImportFrom</string> <string>#ImportFrom</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item row="1" column="1">
<widget class="QComboBox" name="importSourceCombo"> <widget class="QComboBox" name="importSourceCombo">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item> <item>
<property name="text"> <property name="text">
<string>Existing File</string> <string>#ExistingFile</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>VMess Connection String</string> <string>#VMessConnectionString</string>
</property> </property>
</item> </item>
</widget> </widget>
</item> </item>
</layout> </layout>
</item> </item>
<item row="1" column="1"> <item>
<widget class="QGroupBox" name="fromVMessGroupBox"> <widget class="QGroupBox" name="groupBox">
<property name="title"> <property name="title">
<string>#From VMess Connection String</string> <string>#Import</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_4">
<item> <item>
<widget class="QLabel" name="label_3"> <widget class="QStackedWidget" name="stackedWidget">
<property name="text"> <property name="currentIndex">
<string>#VMess Connection String</string> <number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="vmessConnectionStringTxt"/>
</item>
<item>
<widget class="QPushButton" name="verifyVMessBtn">
<property name="text">
<string>Verify</string>
</property> </property>
<widget class="QWidget" name="page">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="fileLabel">
<property name="text">
<string>#Path</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLineEdit" name="fileLineTxt">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="selectFileBtn">
<property name="text">
<string>#SelectFile</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>#Inbound</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="keepInboundCheckBox">
<property name="text">
<string>#KeepImportedInbounds</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_2">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>#VMess Connection String</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="vmessConnectionStringTxt"/>
</item>
</layout>
</widget>
</widget> </widget>
</item> </item>
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item>
<widget class="QDialogButtonBox" name="buttonBox"> <widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="standardButtons"> <property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> <set>QDialogButtonBox::Discard|QDialogButtonBox::Save</set>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0">
<widget class="QGroupBox" name="fromFileGroupBox">
<property name="title">
<string>#FromFile</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="fileLabel">
<property name="text">
<string>#Path</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLineEdit" name="fileLineTxt">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="selectFileBtn">
<property name="text">
<string>#SelectFile</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="aliasLabel">
<property name="text">
<string>#Name</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="nameTxt"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>#Inbound</string>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QRadioButton" name="useCurrentSettingRidBtn">
<property name="text">
<string>#UseCurrent</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="useImportedRidBtn">
<property name="text">
<string>#UseImported</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="verifyFileBtn">
<property name="text">
<string>Verify</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<tabstops> <tabstops>
<tabstop>importSourceCombo</tabstop>
<tabstop>fileLineTxt</tabstop> <tabstop>fileLineTxt</tabstop>
<tabstop>selectFileBtn</tabstop> <tabstop>selectFileBtn</tabstop>
<tabstop>nameTxt</tabstop>
<tabstop>useCurrentSettingRidBtn</tabstop>
<tabstop>useImportedRidBtn</tabstop>
<tabstop>vmessConnectionStringTxt</tabstop>
</tabstops> </tabstops>
<resources/> <resources/>
<connections> <connections>

View File

@ -101,7 +101,7 @@ void MainWindow::UpdateLog()
void MainWindow::on_startButton_clicked() void MainWindow::on_startButton_clicked()
{ {
ui->logText->clear(); ui->logText->clear();
bool startFlag = this->vinstance->start(); bool startFlag = this->vinstance->Start();
trayMenu->actions()[2]->setEnabled(!startFlag); trayMenu->actions()[2]->setEnabled(!startFlag);
trayMenu->actions()[3]->setEnabled(startFlag); trayMenu->actions()[3]->setEnabled(startFlag);
trayMenu->actions()[4]->setEnabled(startFlag); trayMenu->actions()[4]->setEnabled(startFlag);
@ -109,7 +109,7 @@ void MainWindow::on_startButton_clicked()
void MainWindow::on_stopButton_clicked() void MainWindow::on_stopButton_clicked()
{ {
this->vinstance->stop(); this->vinstance->Stop();
ui->logText->clear(); ui->logText->clear();
trayMenu->actions()[2]->setEnabled(true); trayMenu->actions()[2]->setEnabled(true);
trayMenu->actions()[3]->setEnabled(false); trayMenu->actions()[3]->setEnabled(false);

View File

@ -14,7 +14,7 @@ PrefrencesWindow::PrefrencesWindow(QWidget *parent) : QDialog(parent),
CurrentConfig = GetGlobalConfig(); CurrentConfig = GetGlobalConfig();
ui->languageComboBox->setCurrentText(QString::fromStdString(CurrentConfig.language)); ui->languageComboBox->setCurrentText(QString::fromStdString(CurrentConfig.language));
ui->runAsRootCheckBox->setChecked(CurrentConfig.runAsRoot); ui->runAsRootCheckBox->setChecked(CurrentConfig.runAsRoot);
ui->logLevelCheckBox->setCurrentText(QString::fromStdString(CurrentConfig.logLevel)); ui->logLevelComboBox->setCurrentIndex(CurrentConfig.logLevel);
// //
ui->httpCB->setChecked(CurrentConfig.httpSetting.enabled); ui->httpCB->setChecked(CurrentConfig.httpSetting.enabled);
ui->httpPortLE->setText(QString::fromStdString(to_string(CurrentConfig.httpSetting.port))); ui->httpPortLE->setText(QString::fromStdString(to_string(CurrentConfig.httpSetting.port)));
@ -29,7 +29,7 @@ PrefrencesWindow::PrefrencesWindow(QWidget *parent) : QDialog(parent),
ui->socksAuthUsernameTxt->setText(QString::fromStdString(CurrentConfig.socksSetting.authUsername)); ui->socksAuthUsernameTxt->setText(QString::fromStdString(CurrentConfig.socksSetting.authUsername));
ui->socksAuthPasswordTxt->setText(QString::fromStdString(CurrentConfig.socksSetting.authPassword)); ui->socksAuthPasswordTxt->setText(QString::fromStdString(CurrentConfig.socksSetting.authPassword));
// //
ui->vCoreExePathTxt->setText(QString::fromStdString(CurrentConfig.v2Path)); ui->vCoreExePathTxt->setText(QString::fromStdString(CurrentConfig.v2CorePath));
// //
ui->httpPortLE->setValidator(new QIntValidator()); ui->httpPortLE->setValidator(new QIntValidator());
ui->socksPortLE->setValidator(new QIntValidator()); ui->socksPortLE->setValidator(new QIntValidator());
@ -98,7 +98,7 @@ void PrefrencesWindow::on_runAsRootCheckBox_stateChanged(int arg1)
{ {
Q_UNUSED(arg1) Q_UNUSED(arg1)
#ifdef _WIN32 #ifdef _WIN32
showWarnMessageBox(this, tr("Prefrences"), tr("RunAsRootNotOnWindows")); QvMessageBox(this, tr("Prefrences"), tr("RunAsRootNotOnWindows"));
#endif #endif
} }

View File

@ -77,7 +77,7 @@
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="2" column="1">
<widget class="QComboBox" name="logLevelCheckBox"> <widget class="QComboBox" name="logLevelComboBox">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed"> <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
@ -336,7 +336,7 @@
<tabstops> <tabstops>
<tabstop>languageComboBox</tabstop> <tabstop>languageComboBox</tabstop>
<tabstop>runAsRootCheckBox</tabstop> <tabstop>runAsRootCheckBox</tabstop>
<tabstop>logLevelCheckBox</tabstop> <tabstop>logLevelComboBox</tabstop>
<tabstop>muxEnabledCB</tabstop> <tabstop>muxEnabledCB</tabstop>
<tabstop>muxConcurrencyTxt</tabstop> <tabstop>muxConcurrencyTxt</tabstop>
<tabstop>httpCB</tabstop> <tabstop>httpCB</tabstop>

View File

@ -262,135 +262,91 @@
<context> <context>
<name>ImportConfigWindow</name> <name>ImportConfigWindow</name>
<message> <message>
<location filename="../src/w_ImportConfig.ui" line="20"/> <location filename="../src/w_ImportConfig.ui" line="26"/>
<source>Import file</source> <source>Import file</source>
<translation>Import file</translation> <translation>Import file</translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.ui" line="28"/> <location filename="../src/w_ImportConfig.ui" line="50"/>
<source>#ImportFrom</source> <source>#ImportFrom</source>
<translation>Import From</translation> <translation>Import From</translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.ui" line="36"/> <location filename="../src/w_ImportConfig.ui" line="94"/>
<source>Existing File</source>
<translation>Existing File</translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="41"/>
<source>VMess Connection String</source>
<translation>VMess Connection String</translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="67"/>
<location filename="../src/w_ImportConfig.ui" line="160"/>
<source>Verify</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="87"/>
<source>#FromFile</source>
<translation>From file</translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="95"/>
<source>#Path</source> <source>#Path</source>
<translation>Path</translation> <translation>Path</translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.ui" line="111"/> <location filename="../src/w_ImportConfig.ui" line="110"/>
<source>#SelectFile</source> <source>#SelectFile</source>
<translation>Select File</translation> <translation>Select File</translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.ui" line="120"/> <location filename="../src/w_ImportConfig.ui" line="40"/>
<source>#Name</source> <source>#Name</source>
<translation>Name</translation> <translation>Name</translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.ui" line="130"/> <location filename="../src/w_ImportConfig.ui" line="64"/>
<source>#ExistingFile</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="69"/>
<source>#VMessConnectionString</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="79"/>
<source>#Import</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="119"/>
<source>#Inbound</source> <source>#Inbound</source>
<translation>Inbound Settings</translation> <translation>Inbound Settings</translation>
</message> </message>
<message>
<location filename="../src/w_ImportConfig.ui" line="126"/>
<source>#KeepImportedInbounds</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<location filename="../src/w_ImportConfig.ui" line="139"/> <location filename="../src/w_ImportConfig.ui" line="139"/>
<source>#UseCurrent</source>
<translation>Use Current Settings</translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="149"/>
<source>#UseImported</source>
<translation>Use Imported Inbound Settings</translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="51"/>
<source>#From VMess Connection String</source>
<translation>From VMess Connection String</translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="57"/>
<source>#VMess Connection String</source> <source>#VMess Connection String</source>
<translation>VMess Connection String</translation> <translation>VMess Connection String</translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.cpp" line="30"/> <location filename="../src/w_ImportConfig.cpp" line="35"/>
<source>OpenConfigFile</source> <source>OpenConfigFile</source>
<translation type="unfinished">Open Config File</translation> <translation type="unfinished">Open Config File</translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.cpp" line="41"/> <location filename="../src/w_ImportConfig.cpp" line="61"/>
<location filename="../src/w_ImportConfig.cpp" line="59"/>
<source>ImportConfig</source>
<translation type="unfinished">Import Config</translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="41"/>
<source>CannotOpenFile</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="59"/>
<source>CannotCopyCustomConfig</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="95"/>
<source>#NotValidVMessProtocolString</source> <source>#NotValidVMessProtocolString</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.cpp" line="93"/> <location filename="../src/w_ImportConfig.cpp" line="61"/>
<location filename="../src/w_ImportConfig.cpp" line="106"/> <location filename="../src/w_ImportConfig.cpp" line="65"/>
<source>#AbleToImportConfig</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="93"/>
<location filename="../src/w_ImportConfig.cpp" line="95"/>
<location filename="../src/w_ImportConfig.cpp" line="97"/>
<source>#VMessCheck</source> <source>#VMessCheck</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.cpp" line="97"/> <location filename="../src/w_ImportConfig.cpp" line="65"/>
<source>#INTERNAL_ERROR</source> <source>#INTERNAL_ERROR</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.cpp" line="104"/> <location filename="../src/w_ImportConfig.cpp" line="48"/>
<source>#InvalidConfigFile</source> <source>#InvalidConfigFile</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.cpp" line="104"/> <location filename="../src/w_ImportConfig.cpp" line="48"/>
<source>ConfigFileCheckFailed</source> <source>ConfigFileCheckFailed</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="106"/>
<source>#VConfigFileCheckPassed</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>MainWindow</name> <name>MainWindow</name>
@ -666,27 +622,27 @@
<context> <context>
<name>QObject</name> <name>QObject</name>
<message> <message>
<location filename="../src/main.cpp" line="89"/> <location filename="../src/main.cpp" line="92"/>
<source>AnotherInstanceRunning</source> <source>AnotherInstanceRunning</source>
<translation>Another instance is already running</translation> <translation>Another instance is already running</translation>
</message> </message>
<message> <message>
<location filename="../src/main.cpp" line="89"/> <location filename="../src/main.cpp" line="92"/>
<source>Qv2ray</source> <source>Qv2ray</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../src/QvCoreInteractions.cpp" line="45"/> <location filename="../src/QvCoreInteractions.cpp" line="48"/>
<source>CoreNotFound</source> <source>CoreNotFound</source>
<translation>Core files are not found</translation> <translation>Core files are not found</translation>
</message> </message>
<message> <message>
<location filename="../src/QvCoreInteractions.cpp" line="45"/> <location filename="../src/QvCoreInteractions.cpp" line="48"/>
<source>CoreFileNotFoundExplainationAt:</source> <source>CoreFileNotFoundExplainationAt:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/QvCoreInteractions.cpp" line="24"/> <location filename="../src/QvCoreInteractions.cpp" line="27"/>
<source>ConfigurationError</source> <source>ConfigurationError</source>
<translation>Configuration Error</translation> <translation>Configuration Error</translation>
</message> </message>

View File

@ -262,135 +262,91 @@
<context> <context>
<name>ImportConfigWindow</name> <name>ImportConfigWindow</name>
<message> <message>
<location filename="../src/w_ImportConfig.ui" line="20"/> <location filename="../src/w_ImportConfig.ui" line="26"/>
<source>Import file</source> <source>Import file</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.ui" line="28"/> <location filename="../src/w_ImportConfig.ui" line="50"/>
<source>#ImportFrom</source> <source>#ImportFrom</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.ui" line="36"/> <location filename="../src/w_ImportConfig.ui" line="94"/>
<source>Existing File</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="41"/>
<source>VMess Connection String</source>
<translation>VMess </translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="67"/>
<location filename="../src/w_ImportConfig.ui" line="160"/>
<source>Verify</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="87"/>
<source>#FromFile</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="95"/>
<source>#Path</source> <source>#Path</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.ui" line="111"/> <location filename="../src/w_ImportConfig.ui" line="110"/>
<source>#SelectFile</source> <source>#SelectFile</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.ui" line="120"/> <location filename="../src/w_ImportConfig.ui" line="40"/>
<source>#Name</source> <source>#Name</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.ui" line="130"/> <location filename="../src/w_ImportConfig.ui" line="64"/>
<source>#ExistingFile</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="69"/>
<source>#VMessConnectionString</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="79"/>
<source>#Import</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="119"/>
<source>#Inbound</source> <source>#Inbound</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<location filename="../src/w_ImportConfig.ui" line="126"/>
<source>#KeepImportedInbounds</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<location filename="../src/w_ImportConfig.ui" line="139"/> <location filename="../src/w_ImportConfig.ui" line="139"/>
<source>#UseCurrent</source>
<translation>使</translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="149"/>
<source>#UseImported</source>
<translation>使</translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="51"/>
<source>#From VMess Connection String</source>
<translation> VMess </translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="57"/>
<source>#VMess Connection String</source> <source>#VMess Connection String</source>
<translation>VMess </translation> <translation>VMess </translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.cpp" line="30"/> <location filename="../src/w_ImportConfig.cpp" line="35"/>
<source>OpenConfigFile</source> <source>OpenConfigFile</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.cpp" line="41"/> <location filename="../src/w_ImportConfig.cpp" line="61"/>
<location filename="../src/w_ImportConfig.cpp" line="59"/>
<source>ImportConfig</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="41"/>
<source>CannotOpenFile</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="59"/>
<source>CannotCopyCustomConfig</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="95"/>
<source>#NotValidVMessProtocolString</source> <source>#NotValidVMessProtocolString</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.cpp" line="93"/> <location filename="../src/w_ImportConfig.cpp" line="61"/>
<location filename="../src/w_ImportConfig.cpp" line="106"/> <location filename="../src/w_ImportConfig.cpp" line="65"/>
<source>#AbleToImportConfig</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="93"/>
<location filename="../src/w_ImportConfig.cpp" line="95"/>
<location filename="../src/w_ImportConfig.cpp" line="97"/>
<source>#VMessCheck</source> <source>#VMessCheck</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.cpp" line="97"/> <location filename="../src/w_ImportConfig.cpp" line="65"/>
<source>#INTERNAL_ERROR</source> <source>#INTERNAL_ERROR</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.cpp" line="104"/> <location filename="../src/w_ImportConfig.cpp" line="48"/>
<source>#InvalidConfigFile</source> <source>#InvalidConfigFile</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/w_ImportConfig.cpp" line="104"/> <location filename="../src/w_ImportConfig.cpp" line="48"/>
<source>ConfigFileCheckFailed</source> <source>ConfigFileCheckFailed</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="106"/>
<source>#VConfigFileCheckPassed</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>MainWindow</name> <name>MainWindow</name>
@ -666,27 +622,27 @@
<context> <context>
<name>QObject</name> <name>QObject</name>
<message> <message>
<location filename="../src/main.cpp" line="89"/> <location filename="../src/main.cpp" line="92"/>
<source>AnotherInstanceRunning</source> <source>AnotherInstanceRunning</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../src/main.cpp" line="89"/> <location filename="../src/main.cpp" line="92"/>
<source>Qv2ray</source> <source>Qv2ray</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../src/QvCoreInteractions.cpp" line="45"/> <location filename="../src/QvCoreInteractions.cpp" line="48"/>
<source>CoreNotFound</source> <source>CoreNotFound</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../src/QvCoreInteractions.cpp" line="45"/> <location filename="../src/QvCoreInteractions.cpp" line="48"/>
<source>CoreFileNotFoundExplainationAt:</source> <source>CoreFileNotFoundExplainationAt:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../src/QvCoreInteractions.cpp" line="24"/> <location filename="../src/QvCoreInteractions.cpp" line="27"/>
<source>ConfigurationError</source> <source>ConfigurationError</source>
<translation></translation> <translation></translation>
</message> </message>