[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 RROOT return root;
#define JSON_ROOT_TRY_REMOVE(obj) if (root.contains(obj)) { root.remove(obj); }
namespace Qv2ray
{
namespace ConfigOperations
@ -32,15 +34,24 @@ namespace Qv2ray
//
// Misc
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 ---------------------------------------------
int VerifyVMessProtocolString(QString vmess);
//
// -------------------------- BEGIN CONFIG CONVERSIONS ---------------------------------------------
// Save Connection Config
int SaveConnectionConfig(QJsonObject obj, const QString *alias);
// 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);
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
}
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)
{
DROOT
@ -122,62 +114,6 @@ namespace Qv2ray
JADD(auth, accounts, udp, ip, userLevel)
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 ------------------------------------------------------------------------------
}
}

View File

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

View File

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

View File

@ -41,22 +41,24 @@ namespace Qv2ray
struct Qv2Config {
string language;
bool runAsRoot;
string logLevel;
string v2Path;
int logLevel;
string v2CorePath;
string v2AssetsPath;
QvInbondSetting httpSetting;
QvInbondSetting socksSetting;
list<string> configs;
Qv2Config(): language(), runAsRoot(), logLevel(), httpSetting(), socksSetting(), configs() { }
Qv2Config(string lang, string exePath, string log, QvInbondSetting httpIn, QvInbondSetting socksIN): Qv2Config()
Qv2Config(): httpSetting(), socksSetting(), configs() { }
Qv2Config(string lang, string exePath, string assetsPath, int log, QvInbondSetting httpIn, QvInbondSetting socksIN): Qv2Config()
{
v2Path = exePath;
language = lang;
v2CorePath = exePath;
v2AssetsPath = assetsPath;
logLevel = log;
httpSetting = httpIn;
socksSetting = socksIN;
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);
}
bool CheckFile(QDir *dir, QString fileName)
{
return GetFileList(dir).indexOf(fileName) >= 0;
}
void QvMessageBox(QWidget *parent, QString title, QString text)
{
QMessageBox::warning(parent, title, text, QMessageBox::Ok | QMessageBox::Default, 0);
}
QTranslator *getTranslator(QString lang)
{
QTranslator *translator = new QTranslator();

View File

@ -16,17 +16,20 @@ bool initializeQv()
/// Qv2ray Config Path and ends with "/"
QString configPath = "";
QString exeDefaultPath = "";
QString v2AssetsPath = "";
#if defined(__WIN32) || defined(__APPLE__)
// 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
// the executable.
configPath = "./qv2ray.conf.d";
exeDefaultPath = "./v2ray";
configPath = "./qv2ray.d";
exeDefaultPath = "./qv2ray.d/v2ray";
v2AssetsPath = "./qv2ray.d";
#else
// 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/
// 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";
#endif
SetConfigDirPath(configPath);
@ -60,7 +63,7 @@ bool initializeQv()
// These below genenrated very basic global config.
QvInbondSetting inHttp = QvInbondSetting(true, "127.0.0.1", 8080);
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.
SetGlobalConfig(conf);

View File

@ -25,84 +25,56 @@ ImportConfigWindow::~ImportConfigWindow()
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"), "~/");
ui->fileLineTxt->setText(dir);
}
void ImportConfigWindow::savefromFile(QString path, QString alias)
{
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()
void ImportConfigWindow::on_buttonBox_clicked(QAbstractButton *button)
{
QString alias = ui->nameTxt->text();
QJsonObject config;
if (ui->importSourceCombo->currentIndex() == 0) { // From File...
bool overrideInBound = ui->useCurrentSettingRidBtn->isChecked();
on_verifyFileBtn_clicked();
bool overrideInBound = ui->keepInboundCheckBox->isChecked();
if (!Qv2Instance::VerifyVConfigFile(ui->fileLineTxt->text())) {
QvMessageBox(this, tr("#InvalidConfigFile"), tr("ConfigFileCheckFailed"));
return;
}
QString path = ui->fileLineTxt->text();
savefromFile(path, alias);
// !!! TODO
config = ConvertConfigFromFile(path, overrideInBound);
} else {
on_verifyVMessBtn_clicked();
auto config = ConvertOutboundFromVMessString(ui->vmessConnectionStringTxt->toPlainText());
QString vmess = ui->vmessConnectionStringTxt->toPlainText();
int result = VerifyVMessProtocolString(vmess);
if (result == 0) {
//QvMessageBox(this, tr("#VMessCheck"), tr("#AbleToImportConfig"));
} else if (result == -1) {
QvMessageBox(this, tr("#VMessCheck"), tr("#NotValidVMessProtocolString"));
done(0);
return;
} else {
QvMessageBox(this, tr("#VMessCheck"), tr("#INTERNAL_ERROR"));
return;
}
config = ConvertConfigFromVMessString(ui->vmessConnectionStringTxt->toPlainText());
//
alias = alias != "" ? alias : config["QV2RAY_ALIAS"].toString();
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()
{
QString vmess = ui->vmessConnectionStringTxt->toPlainText();
int result = VerifyVMessProtocolString(vmess);
if (result == 0) {
QvMessageBox(this, tr("#VMessCheck"), tr("#AbleToImportConfig"));
} else if (result == -1) {
QvMessageBox(this, tr("#VMessCheck"), tr("#NotValidVMessProtocolString"));
} else {
QvMessageBox(this, tr("#VMessCheck"), tr("#INTERNAL_ERROR"));
}
}
void ImportConfigWindow::on_verifyFileBtn_clicked()
{
if (!Qv2Instance::checkConfigFile(ui->fileLineTxt->text())) {
QvMessageBox(this, tr("#InvalidConfigFile"), tr("ConfigFileCheckFailed"));
} else {
QvMessageBox(this, tr("#VConfigFileCheckPassed"), tr("#AbleToImportConfig"));
}
Qv2Config conf = GetGlobalConfig();
conf.configs.push_back(alias.toStdString());
SetGlobalConfig(conf);
SaveConnectionConfig(config, &alias);
emit s_reload_config();
}

View File

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

View File

@ -6,174 +6,165 @@
<rect>
<x>0</x>
<y>0</y>
<width>650</width>
<height>350</height>
<width>370</width>
<height>420</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>650</width>
<height>350</height>
<width>370</width>
<height>420</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>370</width>
<height>420</height>
</size>
</property>
<property name="windowTitle">
<string>Import file</string>
</property>
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0" columnstretch="1,1">
<item row="0" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,6">
<item>
<property name="sizeGripEnabled">
<bool>false</bool>
</property>
<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">
<property name="text">
<string>#ImportFrom</string>
</property>
</widget>
</item>
<item>
<item row="1" column="1">
<widget class="QComboBox" name="importSourceCombo">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Existing File</string>
<string>#ExistingFile</string>
</property>
</item>
<item>
<property name="text">
<string>VMess Connection String</string>
<string>#VMessConnectionString</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item row="1" column="1">
<widget class="QGroupBox" name="fromVMessGroupBox">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>#From VMess Connection String</string>
<string>#Import</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<layout class="QVBoxLayout" name="verticalLayout_4">
<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>
<item>
<widget class="QPushButton" name="verifyVMessBtn">
<property name="text">
<string>Verify</string>
<widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex">
<number>0</number>
</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>
</item>
</layout>
</widget>
</item>
<item row="2" column="1">
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
<set>QDialogButtonBox::Discard|QDialogButtonBox::Save</set>
</property>
</widget>
</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>
</widget>
<tabstops>
<tabstop>importSourceCombo</tabstop>
<tabstop>fileLineTxt</tabstop>
<tabstop>selectFileBtn</tabstop>
<tabstop>nameTxt</tabstop>
<tabstop>useCurrentSettingRidBtn</tabstop>
<tabstop>useImportedRidBtn</tabstop>
<tabstop>vmessConnectionStringTxt</tabstop>
</tabstops>
<resources/>
<connections>

View File

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

View File

@ -14,7 +14,7 @@ PrefrencesWindow::PrefrencesWindow(QWidget *parent) : QDialog(parent),
CurrentConfig = GetGlobalConfig();
ui->languageComboBox->setCurrentText(QString::fromStdString(CurrentConfig.language));
ui->runAsRootCheckBox->setChecked(CurrentConfig.runAsRoot);
ui->logLevelCheckBox->setCurrentText(QString::fromStdString(CurrentConfig.logLevel));
ui->logLevelComboBox->setCurrentIndex(CurrentConfig.logLevel);
//
ui->httpCB->setChecked(CurrentConfig.httpSetting.enabled);
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->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->socksPortLE->setValidator(new QIntValidator());
@ -98,7 +98,7 @@ void PrefrencesWindow::on_runAsRootCheckBox_stateChanged(int arg1)
{
Q_UNUSED(arg1)
#ifdef _WIN32
showWarnMessageBox(this, tr("Prefrences"), tr("RunAsRootNotOnWindows"));
QvMessageBox(this, tr("Prefrences"), tr("RunAsRootNotOnWindows"));
#endif
}

View File

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

View File

@ -262,135 +262,91 @@
<context>
<name>ImportConfigWindow</name>
<message>
<location filename="../src/w_ImportConfig.ui" line="20"/>
<location filename="../src/w_ImportConfig.ui" line="26"/>
<source>Import file</source>
<translation>Import file</translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="28"/>
<location filename="../src/w_ImportConfig.ui" line="50"/>
<source>#ImportFrom</source>
<translation>Import From</translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="36"/>
<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"/>
<location filename="../src/w_ImportConfig.ui" line="94"/>
<source>#Path</source>
<translation>Path</translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="111"/>
<location filename="../src/w_ImportConfig.ui" line="110"/>
<source>#SelectFile</source>
<translation>Select File</translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="120"/>
<location filename="../src/w_ImportConfig.ui" line="40"/>
<source>#Name</source>
<translation>Name</translation>
</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>
<translation>Inbound Settings</translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="126"/>
<source>#KeepImportedInbounds</source>
<translation type="unfinished"></translation>
</message>
<message>
<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>
<translation>VMess Connection String</translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="30"/>
<location filename="../src/w_ImportConfig.cpp" line="35"/>
<source>OpenConfigFile</source>
<translation type="unfinished">Open Config File</translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="41"/>
<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"/>
<location filename="../src/w_ImportConfig.cpp" line="61"/>
<source>#NotValidVMessProtocolString</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="93"/>
<location filename="../src/w_ImportConfig.cpp" line="106"/>
<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"/>
<location filename="../src/w_ImportConfig.cpp" line="61"/>
<location filename="../src/w_ImportConfig.cpp" line="65"/>
<source>#VMessCheck</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="97"/>
<location filename="../src/w_ImportConfig.cpp" line="65"/>
<source>#INTERNAL_ERROR</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="104"/>
<location filename="../src/w_ImportConfig.cpp" line="48"/>
<source>#InvalidConfigFile</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="104"/>
<location filename="../src/w_ImportConfig.cpp" line="48"/>
<source>ConfigFileCheckFailed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="106"/>
<source>#VConfigFileCheckPassed</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MainWindow</name>
@ -666,27 +622,27 @@
<context>
<name>QObject</name>
<message>
<location filename="../src/main.cpp" line="89"/>
<location filename="../src/main.cpp" line="92"/>
<source>AnotherInstanceRunning</source>
<translation>Another instance is already running</translation>
</message>
<message>
<location filename="../src/main.cpp" line="89"/>
<location filename="../src/main.cpp" line="92"/>
<source>Qv2ray</source>
<translation></translation>
</message>
<message>
<location filename="../src/QvCoreInteractions.cpp" line="45"/>
<location filename="../src/QvCoreInteractions.cpp" line="48"/>
<source>CoreNotFound</source>
<translation>Core files are not found</translation>
</message>
<message>
<location filename="../src/QvCoreInteractions.cpp" line="45"/>
<location filename="../src/QvCoreInteractions.cpp" line="48"/>
<source>CoreFileNotFoundExplainationAt:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/QvCoreInteractions.cpp" line="24"/>
<location filename="../src/QvCoreInteractions.cpp" line="27"/>
<source>ConfigurationError</source>
<translation>Configuration Error</translation>
</message>

View File

@ -262,135 +262,91 @@
<context>
<name>ImportConfigWindow</name>
<message>
<location filename="../src/w_ImportConfig.ui" line="20"/>
<location filename="../src/w_ImportConfig.ui" line="26"/>
<source>Import file</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="28"/>
<location filename="../src/w_ImportConfig.ui" line="50"/>
<source>#ImportFrom</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="36"/>
<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"/>
<location filename="../src/w_ImportConfig.ui" line="94"/>
<source>#Path</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="111"/>
<location filename="../src/w_ImportConfig.ui" line="110"/>
<source>#SelectFile</source>
<translation></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="120"/>
<location filename="../src/w_ImportConfig.ui" line="40"/>
<source>#Name</source>
<translation></translation>
</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>
<translation></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.ui" line="126"/>
<source>#KeepImportedInbounds</source>
<translation type="unfinished"></translation>
</message>
<message>
<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>
<translation>VMess </translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="30"/>
<location filename="../src/w_ImportConfig.cpp" line="35"/>
<source>OpenConfigFile</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="41"/>
<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"/>
<location filename="../src/w_ImportConfig.cpp" line="61"/>
<source>#NotValidVMessProtocolString</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="93"/>
<location filename="../src/w_ImportConfig.cpp" line="106"/>
<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"/>
<location filename="../src/w_ImportConfig.cpp" line="61"/>
<location filename="../src/w_ImportConfig.cpp" line="65"/>
<source>#VMessCheck</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="97"/>
<location filename="../src/w_ImportConfig.cpp" line="65"/>
<source>#INTERNAL_ERROR</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="104"/>
<location filename="../src/w_ImportConfig.cpp" line="48"/>
<source>#InvalidConfigFile</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="104"/>
<location filename="../src/w_ImportConfig.cpp" line="48"/>
<source>ConfigFileCheckFailed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/w_ImportConfig.cpp" line="106"/>
<source>#VConfigFileCheckPassed</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MainWindow</name>
@ -666,27 +622,27 @@
<context>
<name>QObject</name>
<message>
<location filename="../src/main.cpp" line="89"/>
<location filename="../src/main.cpp" line="92"/>
<source>AnotherInstanceRunning</source>
<translation></translation>
</message>
<message>
<location filename="../src/main.cpp" line="89"/>
<location filename="../src/main.cpp" line="92"/>
<source>Qv2ray</source>
<translation></translation>
</message>
<message>
<location filename="../src/QvCoreInteractions.cpp" line="45"/>
<location filename="../src/QvCoreInteractions.cpp" line="48"/>
<source>CoreNotFound</source>
<translation></translation>
</message>
<message>
<location filename="../src/QvCoreInteractions.cpp" line="45"/>
<location filename="../src/QvCoreInteractions.cpp" line="48"/>
<source>CoreFileNotFoundExplainationAt:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/QvCoreInteractions.cpp" line="24"/>
<location filename="../src/QvCoreInteractions.cpp" line="27"/>
<source>ConfigurationError</source>
<translation></translation>
</message>