mirror of
https://github.com/Qv2ray/Qv2ray.git
synced 2025-05-19 18:30:34 +08:00
parent
ce218f1ada
commit
22ecbe25a3
@ -1 +1 @@
|
||||
887
|
||||
917
|
||||
|
@ -34,7 +34,7 @@ namespace Qv2ray
|
||||
bool RenameConnection(QString originalName, QString newName);
|
||||
// VMess URI Protocol
|
||||
QJsonObject ConvertConfigFromVMessString(QString vmess, QString *alias, QString *errMessage);
|
||||
QJsonObject ConvertConfigFromFile(QString sourceFilePath, bool overrideInbounds);
|
||||
QJsonObject ConvertConfigFromFile(QString sourceFilePath, bool keepInbounds);
|
||||
QString ConvertConfigToVMessString(const StreamSettingsObject &transfer, const VMessServerObject &serverConfig, const QString &alias);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "QvCoreConfigOperations.hpp"
|
||||
#include "QvCoreConfigOperations.hpp"
|
||||
|
||||
namespace Qv2ray
|
||||
{
|
||||
@ -224,7 +224,7 @@ namespace Qv2ray
|
||||
RROOT
|
||||
}
|
||||
|
||||
QJsonObject ConvertConfigFromFile(QString sourceFilePath, bool overrideInbounds)
|
||||
QJsonObject ConvertConfigFromFile(QString sourceFilePath, bool keepInbounds)
|
||||
{
|
||||
QFile source(sourceFilePath);
|
||||
|
||||
@ -233,9 +233,9 @@ namespace Qv2ray
|
||||
return QJsonObject();
|
||||
}
|
||||
|
||||
auto root = JsonFromString(StringFromFile(new QFile(sourceFilePath)));
|
||||
auto root = JsonFromString(StringFromFile(&source));
|
||||
|
||||
if (overrideInbounds) {
|
||||
if (!keepInbounds) {
|
||||
JSON_ROOT_TRY_REMOVE("inbounds")
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,15 @@ ImportConfigWindow::ImportConfigWindow(QWidget *parent)
|
||||
nameTxt->setText(QDateTime::currentDateTime().toString("MM-dd_hh-mm") + "_" + tr("Imported") + "_");
|
||||
}
|
||||
|
||||
QMap<QString, QJsonObject> ImportConfigWindow::OpenImport(bool outboundsOnly)
|
||||
{
|
||||
// if Outbound Only, set keepImported to false and disable the checkbox
|
||||
// keepImportedInboundCheckBox->setChecked(!outboundsOnly);
|
||||
keepImportedInboundCheckBox->setEnabled(!outboundsOnly);
|
||||
this->exec();
|
||||
return this->result() == QDialog::Accepted ? connections : QMap<QString, QJsonObject>();
|
||||
}
|
||||
|
||||
void ImportConfigWindow::on_importSourceCombo_currentIndexChanged(int index)
|
||||
{
|
||||
stackedWidget->setCurrentIndex(index);
|
||||
@ -37,17 +46,7 @@ void ImportConfigWindow::on_selectFileBtn_clicked()
|
||||
|
||||
void ImportConfigWindow::on_qrFromScreenBtn_clicked()
|
||||
{
|
||||
// QRubberBand
|
||||
QThread::msleep(static_cast<ulong>(doubleSpinBox->value() * 1000));
|
||||
//bool hasVmessDetected = false;
|
||||
//for (auto screen : qApp->screens()) {
|
||||
// if (!screen) {
|
||||
// LOG(MODULE_UI, "Cannot even find a screen. RARE")
|
||||
// QvMessageBox(this, tr("Screenshot failed"), tr("Cannot find a valid screen, it's rare."));
|
||||
// return;
|
||||
// }
|
||||
//auto pix = screen->grabWindow(0);
|
||||
//
|
||||
ScreenShotWindow w;
|
||||
auto pix = w.DoScreenShot();
|
||||
|
||||
@ -57,32 +56,25 @@ void ImportConfigWindow::on_qrFromScreenBtn_clicked()
|
||||
if (str.trimmed().isEmpty()) {
|
||||
LOG(MODULE_UI, "Cannot decode QR Code from an image, size: h=" + to_string(pix.width()) + ", v=" + to_string(pix.height()))
|
||||
QvMessageBox(this, tr("Capture QRCode"), tr("Cannot find a valid QRCode from this region."));
|
||||
// continue;
|
||||
} else {
|
||||
vmessConnectionStringTxt->appendPlainText(str.trimmed() + NEWLINE);
|
||||
//hasVmessDetected = true;
|
||||
}
|
||||
}
|
||||
|
||||
//}
|
||||
//if (!hasVmessDetected) {
|
||||
//QvMessageBox(this, tr("QRCode scanning failed"), tr("Cannot find any QRCode from any screens."));
|
||||
//}
|
||||
}
|
||||
|
||||
void ImportConfigWindow::on_beginImportBtn_clicked()
|
||||
{
|
||||
QString aliasPrefix = nameTxt->text();
|
||||
QJsonObject config;
|
||||
auto conf = GetGlobalConfig();
|
||||
//auto conf = GetGlobalConfig();
|
||||
|
||||
switch (importSourceCombo->currentIndex()) {
|
||||
case 0: {
|
||||
// From File...
|
||||
bool overrideInBound = !keepImportedInboundCheckBox->isChecked();
|
||||
bool keepInBound = keepImportedInboundCheckBox->isChecked();
|
||||
QString path = fileLineTxt->text();
|
||||
aliasPrefix = aliasPrefix.isEmpty() ? aliasPrefix : QFileInfo(path).fileName();
|
||||
config = ConvertConfigFromFile(path, overrideInBound);
|
||||
config = ConvertConfigFromFile(path, keepInBound);
|
||||
|
||||
if (config.isEmpty()) {
|
||||
QvMessageBox(this, tr("Import config file"), tr("Import from file failed, for more information, please check the log file."));
|
||||
@ -91,14 +83,7 @@ void ImportConfigWindow::on_beginImportBtn_clicked()
|
||||
QvMessageBox(this, tr("Import config file"), tr("Failed to check the validity of the config file."));
|
||||
return;
|
||||
} else {
|
||||
// We save first, "alias" may change to prevent override existing file.
|
||||
bool alwaysFalse = SaveConnectionConfig(config, &aliasPrefix, false);
|
||||
|
||||
if (alwaysFalse) {
|
||||
QvMessageBox(this, tr("Assertion Failed"), tr("Assertion failed: ::SaveConnectionConfig should returns false."));
|
||||
}
|
||||
|
||||
conf.configs.push_back(aliasPrefix.toStdString());
|
||||
connections[aliasPrefix] = config;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -125,13 +110,7 @@ void ImportConfigWindow::on_beginImportBtn_clicked()
|
||||
vmessErrors[vmess] = QString::number(vmessErrors.count() + 1) + ": " + errMessage;
|
||||
continue;
|
||||
} else {
|
||||
bool alwaysFalse = SaveConnectionConfig(config, &aliasPrefix, false);
|
||||
|
||||
if (alwaysFalse) {
|
||||
QvMessageBox(this, tr("Assertion Failed"), "Assertion failed: ::SaveConnectionConfig should returns false.");
|
||||
}
|
||||
|
||||
conf.configs.push_back(aliasPrefix.toStdString());
|
||||
connections[aliasPrefix] = config;
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,24 +120,19 @@ void ImportConfigWindow::on_beginImportBtn_clicked()
|
||||
vmessConnectionStringTxt->appendPlainText(vmessErrors.key(item));
|
||||
errorsList->addItem(item);
|
||||
}
|
||||
|
||||
// Don't quit;
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
QvMessageBox(this, tr("TODO"), tr("TODO"));
|
||||
// Subscription link.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SetGlobalConfig(conf);
|
||||
// Never restart current connection after import.
|
||||
emit s_reload_config(false);
|
||||
close();
|
||||
accept();
|
||||
}
|
||||
void ImportConfigWindow::on_selectImageBtn_clicked()
|
||||
{
|
||||
@ -197,7 +171,7 @@ void ImportConfigWindow::on_errorsList_currentItemChanged(QListWidgetItem *curre
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Select vmess string that is invalid.
|
||||
QTextCursor c = vmessConnectionStringTxt->textCursor();
|
||||
c.setPosition(startPos);
|
||||
c.setPosition(endPos, QTextCursor::KeepAnchor);
|
||||
@ -218,8 +192,7 @@ void ImportConfigWindow::on_editFileBtn_clicked()
|
||||
if (!jsonCheckingError.isEmpty()) {
|
||||
LOG(MODULE_FILE, "Currupted JSON file detected")
|
||||
|
||||
if (QvMessageBoxAsk(this, tr("Edit file as JSON"), tr("The file you selected has json syntax error. Continue editing may make you lose data. Would you like to continue?") +
|
||||
NEWLINE + jsonCheckingError) != QMessageBox::Yes) {
|
||||
if (QvMessageBoxAsk(this, tr("Edit file as JSON"), tr("The file you selected has json syntax error. Continue editing may make you lose data. Would you like to continue?") + NEWLINE + jsonCheckingError) != QMessageBox::Yes) {
|
||||
return;
|
||||
} else {
|
||||
LOG(MODULE_FILE, "Continue editing curruped json file, data loss is expected.")
|
||||
@ -257,13 +230,15 @@ void ImportConfigWindow::on_connectionEditBtn_clicked()
|
||||
root.insert("outbounds", outboundsList);
|
||||
//
|
||||
// WARN This one will change the connection name, because of some duplicates.
|
||||
SaveConnectionConfig(root, &alias, false);
|
||||
connections[alias] = root;
|
||||
//SaveConnectionConfig(root, &alias, false);
|
||||
//
|
||||
auto conf = GetGlobalConfig();
|
||||
auto connectionList = conf.configs;
|
||||
connectionList.push_back(alias.toStdString());
|
||||
conf.configs = connectionList;
|
||||
SetGlobalConfig(conf);
|
||||
// WARN Add connection here
|
||||
//auto conf = GetGlobalConfig();
|
||||
//auto connectionList = conf.configs;
|
||||
//connectionList.push_back(alias.toStdString());
|
||||
//conf.configs = connectionList;
|
||||
//SetGlobalConfig(conf);
|
||||
close();
|
||||
} else {
|
||||
return;
|
||||
|
@ -2,6 +2,8 @@
|
||||
#define IMPORTCONF_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QString>
|
||||
#include <QJsonObject>
|
||||
#include "ui_w_ImportConfig.h"
|
||||
|
||||
class ImportConfigWindow : public QDialog, private Ui::ImportConfigWindow
|
||||
@ -11,8 +13,7 @@ class ImportConfigWindow : public QDialog, private Ui::ImportConfigWindow
|
||||
public:
|
||||
explicit ImportConfigWindow(QWidget *parent = nullptr);
|
||||
~ImportConfigWindow() { }
|
||||
signals:
|
||||
void s_reload_config(bool need_restart);
|
||||
QMap<QString, QJsonObject> OpenImport(bool outboundsOnly = false);
|
||||
private slots:
|
||||
void on_importSourceCombo_currentIndexChanged(int index);
|
||||
|
||||
@ -30,6 +31,7 @@ class ImportConfigWindow : public QDialog, private Ui::ImportConfigWindow
|
||||
void on_cancelImportBtn_clicked();
|
||||
|
||||
private:
|
||||
QMap<QString, QJsonObject> connections;
|
||||
QMap<QString, QString> vmessErrors;
|
||||
};
|
||||
|
||||
|
@ -24,9 +24,13 @@ InboundEditor::InboundEditor(QJsonObject root, QWidget *parent) :
|
||||
} else if (inboundType == "mtproto") {
|
||||
mtSettings = root["settings"].toObject();
|
||||
} else {
|
||||
LOG(MODULE_UI, "Unsupported inbound type: " + inboundType.toStdString() + ", decisions should be made if to open JSONEDITOR")
|
||||
QvMessageBox(this, tr("Inbound type not supported"), tr("The inbound type is not supported by Qv2ray (yet). Please use JsonEditor to change the settings") + "\r\n" +
|
||||
tr("Inbound: ") + inboundType);
|
||||
if (!root["protocol"].toString().isEmpty()) {
|
||||
LOG(MODULE_UI, "Unsupported inbound type: " + inboundType.toStdString())
|
||||
QvMessageBox(this, tr("Inbound type not supported"), tr("The inbound type is not supported by Qv2ray (yet). Please use JsonEditor to change the settings") + "\r\n" +
|
||||
tr("Inbound: ") + inboundType);
|
||||
} else {
|
||||
LOG(MODULE_UI, "Creating new inbound config")
|
||||
}
|
||||
}
|
||||
|
||||
LoadUIData();
|
||||
@ -61,7 +65,10 @@ QJsonObject InboundEditor::GenerateNewRoot()
|
||||
void InboundEditor::LoadUIData()
|
||||
{
|
||||
isLoading = true;
|
||||
strategyCombo->setCurrentText(allocate["strategy"].toString());
|
||||
auto x = allocate["strategy"].toString();
|
||||
allocate["strategy"] = x.isEmpty() ? "always" : x;
|
||||
strategyCombo->setCurrentText(x);
|
||||
//
|
||||
refreshNumberBox->setValue(allocate["refresh"].toInt());
|
||||
concurrencyNumberBox->setValue(allocate["concurrency"].toInt());
|
||||
enableSniffingCB->setChecked(sniffing["enabled"].toBool());
|
||||
|
@ -65,6 +65,7 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
//
|
||||
QAction *action_RCM_RenameConnection = new QAction(tr("Rename"), this);
|
||||
QAction *action_RCM_StartThis = new QAction(tr("Connect to this"), this);
|
||||
QAction *action_RCM_ConvToComplex = new QAction(tr("Edit as Complex Config"), this);
|
||||
QAction *action_RCM_EditJson = new QAction(QICON_R("json.png"), tr("Edit as Json"), this);
|
||||
QAction *action_RCM_ShareQR = new QAction(QICON_R("share.png"), tr("Share as QRCode/VMess URL"), this);
|
||||
//
|
||||
@ -88,6 +89,7 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
connect(action_RCM_RenameConnection, &QAction::triggered, this, &MainWindow::on_action_RenameConnection_triggered);
|
||||
connect(action_RCM_StartThis, &QAction::triggered, this, &MainWindow::on_action_StartThis_triggered);
|
||||
connect(action_RCM_EditJson, &QAction::triggered, this, &MainWindow::on_action_RCM_EditJson_triggered);
|
||||
connect(action_RCM_ConvToComplex, &QAction::triggered, this, &MainWindow::on_action_RCM_ConvToComplex_triggered);
|
||||
//
|
||||
// Share optionss
|
||||
connect(action_RCM_ShareQR, &QAction::triggered, this, &MainWindow::on_action_RCM_ShareQR_triggered);
|
||||
@ -102,6 +104,7 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
listMenu = new QMenu(this);
|
||||
listMenu->addAction(action_RCM_RenameConnection);
|
||||
listMenu->addAction(action_RCM_StartThis);
|
||||
listMenu->addAction(action_RCM_ConvToComplex);
|
||||
listMenu->addAction(action_RCM_EditJson);
|
||||
listMenu->addAction(action_RCM_ShareQR);
|
||||
//
|
||||
@ -308,8 +311,6 @@ void MainWindow::on_startButton_clicked()
|
||||
bool httpEnabled = conf.inboundConfig.useHTTP;
|
||||
bool socksEnabled = conf.inboundConfig.useSocks;
|
||||
|
||||
// TODO: Set PAC proxy string
|
||||
|
||||
if (usePAC) {
|
||||
bool canStartPAC = true;
|
||||
QString pacProxyString; // Something like this --> SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080; DIRECT; http://proxy:8080
|
||||
@ -498,35 +499,44 @@ void MainWindow::ShowAndSetConnection(QString guiConnectionName, bool SetConnect
|
||||
// Check empty again...
|
||||
if (guiConnectionName.isEmpty()) return;
|
||||
|
||||
// --------- BRGIN Show Connection
|
||||
auto root = connections[guiConnectionName];
|
||||
auto outBoundRoot = root["outbounds"].toArray().first().toObject();
|
||||
//
|
||||
auto outboundType = outBoundRoot["protocol"].toString();
|
||||
_OutBoundTypeLabel->setText(outboundType);
|
||||
removeConfigButton->setEnabled(true);
|
||||
editConfigButton->setEnabled(true);
|
||||
editJsonBtn->setEnabled(true);
|
||||
duplicateBtn->setEnabled(true);
|
||||
//
|
||||
// --------- BRGIN Show Connection
|
||||
auto root = connections[guiConnectionName];
|
||||
//
|
||||
auto isComplexConfig = root["routing"].toObject()["rules"].toArray().count() > 0;
|
||||
routeCountLabel->setText(isComplexConfig > 0 ? tr("Complex") : tr("Simple"));
|
||||
|
||||
if (outboundType == "vmess") {
|
||||
auto Server = StructFromJsonString<VMessServerObject>(JsonToString(outBoundRoot["settings"].toObject()["vnext"].toArray().first().toObject()));
|
||||
_hostLabel->setText(QSTRING(Server.address));
|
||||
_portLabel->setText(QSTRING(to_string(Server.port)));
|
||||
} else if (outboundType == "shadowsocks") {
|
||||
auto x = JsonToString(outBoundRoot["settings"].toObject()["servers"].toArray().first().toObject());
|
||||
auto Server = StructFromJsonString<ShadowSocksServerObject>(x);
|
||||
_hostLabel->setText(QSTRING(Server.address));
|
||||
_portLabel->setText(QSTRING(to_string(Server.port)));
|
||||
} else if (outboundType == "socks") {
|
||||
auto x = JsonToString(outBoundRoot["settings"].toObject()["servers"].toArray().first().toObject());
|
||||
auto Server = StructFromJsonString<SocksServerObject>(x);
|
||||
_hostLabel->setText(QSTRING(Server.address));
|
||||
_portLabel->setText(QSTRING(to_string(Server.port)));
|
||||
if (isComplexConfig) {
|
||||
_OutBoundTypeLabel->setText(tr("N/A"));
|
||||
_hostLabel->setText(tr("N/A"));
|
||||
_portLabel->setText(tr("N/A"));
|
||||
} else {
|
||||
auto outBoundRoot = root["outbounds"].toArray().first().toObject();
|
||||
auto outboundType = outBoundRoot["protocol"].toString();
|
||||
_OutBoundTypeLabel->setText(outboundType);
|
||||
|
||||
if (outboundType == "vmess") {
|
||||
auto Server = StructFromJsonString<VMessServerObject>(JsonToString(outBoundRoot["settings"].toObject()["vnext"].toArray().first().toObject()));
|
||||
_hostLabel->setText(QSTRING(Server.address));
|
||||
_portLabel->setText(QSTRING(to_string(Server.port)));
|
||||
} else if (outboundType == "shadowsocks") {
|
||||
auto x = JsonToString(outBoundRoot["settings"].toObject()["servers"].toArray().first().toObject());
|
||||
auto Server = StructFromJsonString<ShadowSocksServerObject>(x);
|
||||
_hostLabel->setText(QSTRING(Server.address));
|
||||
_portLabel->setText(QSTRING(to_string(Server.port)));
|
||||
} else if (outboundType == "socks") {
|
||||
auto x = JsonToString(outBoundRoot["settings"].toObject()["servers"].toArray().first().toObject());
|
||||
auto Server = StructFromJsonString<SocksServerObject>(x);
|
||||
_hostLabel->setText(QSTRING(Server.address));
|
||||
_portLabel->setText(QSTRING(to_string(Server.port)));
|
||||
}
|
||||
}
|
||||
|
||||
routeCountLabel->setText(QString::number(root["routing"].toObject()["rules"].toArray().count()));
|
||||
|
||||
// --------- END Show Connection
|
||||
//
|
||||
// Set Connection
|
||||
@ -660,8 +670,22 @@ void MainWindow::on_removeConfigButton_clicked()
|
||||
}
|
||||
void MainWindow::on_importConfigButton_clicked()
|
||||
{
|
||||
// BETA
|
||||
ImportConfigWindow *w = new ImportConfigWindow(this);
|
||||
w->exec();
|
||||
auto configs = w->OpenImport();
|
||||
auto gConf = GetGlobalConfig();
|
||||
|
||||
for (auto conf : configs) {
|
||||
auto name = configs.key(conf, "");
|
||||
|
||||
if (name.isEmpty())
|
||||
continue;
|
||||
|
||||
SaveConnectionConfig(conf, &name, false);
|
||||
gConf.configs.push_back(name.toStdString());
|
||||
}
|
||||
|
||||
SetGlobalConfig(gConf);
|
||||
OnConfigListChanged(false);
|
||||
}
|
||||
void MainWindow::on_editConfigButton_clicked()
|
||||
@ -677,7 +701,7 @@ void MainWindow::on_editConfigButton_clicked()
|
||||
QJsonObject root;
|
||||
bool isChanged = false;
|
||||
|
||||
if (outBoundRoot["outbounds"].toArray().count() > 1) {
|
||||
if (CheckIsComplexConfig(outBoundRoot)) {
|
||||
LOG(MODULE_UI, "INFO: Opening route editor.")
|
||||
RouteEditor *routeWindow = new RouteEditor(outBoundRoot, this);
|
||||
root = routeWindow->OpenEditor();
|
||||
@ -705,6 +729,34 @@ void MainWindow::on_reconnectButton_clicked()
|
||||
on_stopButton_clicked();
|
||||
on_startButton_clicked();
|
||||
}
|
||||
|
||||
void MainWindow::on_action_RCM_ConvToComplex_triggered()
|
||||
{
|
||||
// Check if we have a connection selected...
|
||||
if (connectionListWidget->currentIndex().row() < 0) {
|
||||
QvMessageBox(this, tr("No Config Selected"), tr("Please Select a Config"));
|
||||
return;
|
||||
}
|
||||
|
||||
auto alias = connectionListWidget->currentItem()->text();
|
||||
auto outBoundRoot = connections[alias];
|
||||
QJsonObject root;
|
||||
bool isChanged = false;
|
||||
//
|
||||
LOG(MODULE_UI, "INFO: Opening route editor.")
|
||||
RouteEditor *routeWindow = new RouteEditor(outBoundRoot, this);
|
||||
root = routeWindow->OpenEditor();
|
||||
isChanged = routeWindow->result() == QDialog::Accepted;
|
||||
|
||||
if (isChanged) {
|
||||
connections[alias] = root;
|
||||
// true indicates the alias will NOT change
|
||||
SaveConnectionConfig(root, &alias, true);
|
||||
OnConfigListChanged(alias == CurrentConnectionName);
|
||||
ShowAndSetConnection(CurrentConnectionName, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_action_RCM_EditJson_triggered()
|
||||
{
|
||||
// Check if we have a connection selected...
|
||||
@ -745,10 +797,9 @@ void MainWindow::on_shareBtn_clicked()
|
||||
auto alias = connectionListWidget->currentItem()->text();
|
||||
auto root = connections[alias];
|
||||
auto outBoundRoot = root["outbounds"].toArray().first().toObject();
|
||||
//
|
||||
auto outboundType = outBoundRoot["protocol"].toString();
|
||||
|
||||
if (outboundType == "vmess") {
|
||||
if (CheckIsComplexConfig(root) && outboundType == "vmess") {
|
||||
auto vmessServer = StructFromJsonString<VMessServerObject>(JsonToString(outBoundRoot["settings"].toObject()["vnext"].toArray().first().toObject()));
|
||||
auto transport = StructFromJsonString<StreamSettingsObject>(JsonToString(outBoundRoot["streamSettings"].toObject()));
|
||||
auto vmess = ConvertConfigToVMessString(transport, vmessServer, alias);
|
||||
|
@ -90,6 +90,7 @@ class MainWindow : public QMainWindow, Ui::MainWindow
|
||||
//
|
||||
void on_action_StartThis_triggered();
|
||||
void on_action_RCM_EditJson_triggered();
|
||||
void on_action_RCM_ConvToComplex_triggered();
|
||||
void on_action_RenameConnection_triggered();
|
||||
//
|
||||
QvHttpRequestHelper HTTPRequestHelper;
|
||||
|
@ -331,26 +331,12 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Mux</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="muxLabel">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Actions</string>
|
||||
<string>Operations</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -387,6 +373,9 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pingTestBtn">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Ping Test</string>
|
||||
</property>
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "w_OutboundEditor.hpp"
|
||||
#include "w_MainWindow.hpp"
|
||||
#include "w_JsonEditor.hpp"
|
||||
#include "w_RoutesEditor.hpp"
|
||||
|
||||
OutboundEditor::OutboundEditor(QWidget *parent)
|
||||
: QDialog(parent),
|
||||
|
@ -28,7 +28,7 @@
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4" columnstretch="8,3">
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<layout class="QFormLayout" name="formLayout_5">
|
||||
<item row="0" column="0">
|
||||
@ -327,7 +327,7 @@
|
||||
<item row="3" column="5">
|
||||
<widget class="QPushButton" name="tcpRespDefBtn">
|
||||
<property name="text">
|
||||
<string>Default Value</string>
|
||||
<string>Default</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -428,7 +428,7 @@
|
||||
<item row="3" column="2">
|
||||
<widget class="QPushButton" name="tcpRequestDefBtn">
|
||||
<property name="text">
|
||||
<string>Default Value</string>
|
||||
<string>Default</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -1045,15 +1045,19 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -1,12 +1,12 @@
|
||||
#include "w_RoutesEditor.hpp"
|
||||
#include "w_RoutesEditor.hpp"
|
||||
#include "QvCoreConfigOperations.hpp"
|
||||
#include "w_OutboundEditor.hpp"
|
||||
#include "w_JsonEditor.hpp"
|
||||
#include "w_InboundEditor.hpp"
|
||||
#include "w_ImportConfig.hpp"
|
||||
|
||||
static bool isLoading = false;
|
||||
#define CurrentRule this->rules[this->currentRuleIndex]
|
||||
#define STATUS(msg) statusLabel->setText(tr(msg));
|
||||
#define LOADINGCHECK if(isLoading) return;
|
||||
|
||||
RouteEditor::RouteEditor(QJsonObject connection, QWidget *parent) :
|
||||
@ -318,9 +318,9 @@ void RouteEditor::ShowRuleDetail(RuleObject rule)
|
||||
|
||||
inboundsList->item(_index)->setCheckState(Qt::Checked);
|
||||
inboundsList->setCurrentRow(_index);
|
||||
STATUS("OK")
|
||||
statusLabel->setText(tr("OK"));
|
||||
} else {
|
||||
STATUS("Cannot find inbound by a tag, possible currupted files?")
|
||||
statusLabel->setText(tr("Cannot find inbound by a tag, possible currupted files?"));
|
||||
LOG(MODULE_UI, "An inbound could not be determined by tag.")
|
||||
return;
|
||||
}
|
||||
@ -335,7 +335,7 @@ void RouteEditor::on_editOutboundBtn_clicked()
|
||||
int row = outboundsList->currentRow();
|
||||
|
||||
if (row < 0) {
|
||||
STATUS("No row selected.")
|
||||
statusLabel->setText(tr("No row selected."));
|
||||
LOG(MODULE_UI, "No outbound row selected.")
|
||||
return;
|
||||
}
|
||||
@ -348,19 +348,19 @@ void RouteEditor::on_editOutboundBtn_clicked()
|
||||
tr("This outbound entry is not supported by the GUI editor.") + "\r\n" +
|
||||
tr("We will launch Json Editor instead."));
|
||||
JsonEditor *w = new JsonEditor(currentOutbound, this);
|
||||
STATUS("Opening JSON editor")
|
||||
statusLabel->setText(tr("Opening JSON editor"));
|
||||
result = w->OpenEditor();
|
||||
delete w;
|
||||
} else {
|
||||
OutboundEditor *w = new OutboundEditor(currentOutbound, this);
|
||||
STATUS("Opening default outbound editor.")
|
||||
statusLabel->setText(tr("Opening default outbound editor."));
|
||||
result = w->OpenEditor();
|
||||
delete w;
|
||||
}
|
||||
|
||||
outbounds[row] = result;
|
||||
on_outboundsList_currentRowChanged(row);
|
||||
STATUS("OK")
|
||||
statusLabel->setText(tr("OK"));
|
||||
}
|
||||
|
||||
void RouteEditor::on_insertDirectBtn_clicked()
|
||||
@ -370,7 +370,7 @@ void RouteEditor::on_insertDirectBtn_clicked()
|
||||
auto out = GenerateOutboundEntry("freedom", freedom, QJsonObject(), QJsonObject(), "0.0.0.0", tag);
|
||||
this->outbounds.append(out);
|
||||
outboundsList->addItem(tag);
|
||||
STATUS("Added DIRECT outbound")
|
||||
statusLabel->setText(tr("Added DIRECT outbound"));
|
||||
}
|
||||
|
||||
void RouteEditor::on_editInboundBtn_clicked()
|
||||
@ -386,20 +386,20 @@ void RouteEditor::on_editInboundBtn_clicked()
|
||||
if (protocol != "http" && protocol != "mtproto" && protocol != "socks" && protocol != "dokodemo-door") {
|
||||
QvMessageBox(this, tr("Cannot Edit"), tr("Currently, this type of outbound is not supported by the editor.") + "\r\n" +
|
||||
tr("We will launch Json Editor instead."));
|
||||
STATUS("Opening JSON editor")
|
||||
statusLabel->setText(tr("Opening JSON editor"));
|
||||
JsonEditor *w = new JsonEditor(currentInbound, this);
|
||||
result = w->OpenEditor();
|
||||
delete w;
|
||||
} else {
|
||||
InboundEditor *w = new InboundEditor(currentInbound, this);
|
||||
STATUS("Opening default inbound editor")
|
||||
statusLabel->setText(tr("Opening default inbound editor"));
|
||||
result = w->OpenEditor();
|
||||
delete w;
|
||||
}
|
||||
|
||||
inbounds[row] = result;
|
||||
on_inboundsList_currentRowChanged(row);
|
||||
STATUS("OK")
|
||||
statusLabel->setText(tr("OK"));
|
||||
}
|
||||
|
||||
void RouteEditor::on_routeProtocolHTTPCB_stateChanged(int arg1)
|
||||
@ -414,7 +414,7 @@ void RouteEditor::on_routeProtocolHTTPCB_stateChanged(int arg1)
|
||||
if (routeProtocolBTCB->isChecked()) protocols << "bittorrent";
|
||||
|
||||
CurrentRule.protocol = protocols.toStdList();
|
||||
STATUS("Protocol list changed.")
|
||||
statusLabel->setText(tr("Protocol list changed."));
|
||||
}
|
||||
|
||||
void RouteEditor::on_routeProtocolTLSCB_stateChanged(int arg1)
|
||||
@ -429,7 +429,7 @@ void RouteEditor::on_routeProtocolTLSCB_stateChanged(int arg1)
|
||||
if (routeProtocolBTCB->isChecked()) protocols << "bittorrent";
|
||||
|
||||
CurrentRule.protocol = protocols.toStdList();
|
||||
STATUS("Protocol list changed.")
|
||||
statusLabel->setText(tr("Protocol list changed."));
|
||||
}
|
||||
|
||||
void RouteEditor::on_routeProtocolBTCB_stateChanged(int arg1)
|
||||
@ -444,7 +444,7 @@ void RouteEditor::on_routeProtocolBTCB_stateChanged(int arg1)
|
||||
if (routeProtocolTLSCB->isChecked()) protocols << "tls";
|
||||
|
||||
CurrentRule.protocol = protocols.toStdList();
|
||||
STATUS("Protocol list changed.")
|
||||
statusLabel->setText(tr("Protocol list changed."));
|
||||
}
|
||||
|
||||
void RouteEditor::on_balabcerAddBtn_clicked()
|
||||
@ -460,9 +460,9 @@ void RouteEditor::on_balabcerAddBtn_clicked()
|
||||
if (!balancerTx.isEmpty()) {
|
||||
balancerList->addItem(balancerTx);
|
||||
balancerSelectionCombo->setEditText("");
|
||||
STATUS("OK")
|
||||
statusLabel->setText(tr("OK"));
|
||||
} else {
|
||||
STATUS("Balacer is empty, not processing.")
|
||||
statusLabel->setText(tr("Balacer is empty, not processing."));
|
||||
}
|
||||
}
|
||||
|
||||
@ -476,7 +476,7 @@ void RouteEditor::on_balancerDelBtn_clicked()
|
||||
|
||||
Balancers[QSTRING(CurrentRule.balancerTag)].removeAt(balancerList->currentRow());
|
||||
balancerList->takeItem(balancerList->currentRow());
|
||||
STATUS("Removed a balancer entry.")
|
||||
statusLabel->setText(tr("Removed a balancer entry."));
|
||||
}
|
||||
|
||||
void RouteEditor::on_hostList_textChanged()
|
||||
@ -569,7 +569,7 @@ void RouteEditor::on_routesTable_cellChanged(int row, int column)
|
||||
}
|
||||
|
||||
rules[row].QV2RAY_RULE_ENABLED = routesTable->item(row, column)->checkState() == Qt::Checked;
|
||||
STATUS((rules[row].QV2RAY_RULE_ENABLED ? "Enabled a route" : "Disabled a route"))
|
||||
statusLabel->setText(tr((rules[row].QV2RAY_RULE_ENABLED ? "Enabled a route" : "Disabled a route")));
|
||||
}
|
||||
|
||||
void RouteEditor::on_netBothRB_clicked()
|
||||
@ -647,7 +647,7 @@ void RouteEditor::on_inboundsList_itemChanged(QListWidgetItem *item)
|
||||
}
|
||||
|
||||
CurrentRule.inboundTag = new_inbounds.toStdList();
|
||||
STATUS("OK")
|
||||
statusLabel->setText(tr("OK"));
|
||||
}
|
||||
|
||||
void RouteEditor::on_delRouteBtn_clicked()
|
||||
@ -730,3 +730,35 @@ void RouteEditor::on_delInboundBtn_clicked()
|
||||
inbounds.removeAt(index);
|
||||
inboundsList->takeItem(index);
|
||||
}
|
||||
|
||||
void RouteEditor::on_addInboundBtn_clicked()
|
||||
{
|
||||
LOADINGCHECK
|
||||
InboundEditor w(QJsonObject(), this);
|
||||
auto _result = w.OpenEditor();
|
||||
inbounds.append(_result);
|
||||
inboundsList->addItem(tr("New Inbound"));
|
||||
}
|
||||
|
||||
void RouteEditor::on_addOutboundBtn_clicked()
|
||||
{
|
||||
LOADINGCHECK
|
||||
ImportConfigWindow *w = new ImportConfigWindow(this);
|
||||
// True here for not keep the inbounds.
|
||||
auto configs = w->OpenImport(true);
|
||||
|
||||
for (auto conf : configs) {
|
||||
auto name = configs.key(conf, "");
|
||||
|
||||
if (name.isEmpty())
|
||||
continue;
|
||||
|
||||
// conf is rootObject, needs to unwrap it.
|
||||
auto confList = conf["outbounds"].toArray();
|
||||
|
||||
for (int i = 0; i < confList.count(); i++) {
|
||||
outbounds.append(confList[i]);
|
||||
outboundsList->addItem(name + "_" + QString::number(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
#ifndef W_QVOUTBOUNDEDITOR_H
|
||||
#ifndef W_QVOUTBOUNDEDITOR_H
|
||||
#define W_QVOUTBOUNDEDITOR_H
|
||||
|
||||
#include <list>
|
||||
@ -80,12 +80,16 @@ class RouteEditor : public QDialog, private Ui::RouteEditor
|
||||
|
||||
void on_delInboundBtn_clicked();
|
||||
|
||||
void on_addInboundBtn_clicked();
|
||||
|
||||
void on_addOutboundBtn_clicked();
|
||||
|
||||
private:
|
||||
void ShowRuleDetail(RuleObject rule);
|
||||
int currentRuleIndex;
|
||||
QString DomainStrategy;
|
||||
QMap<QString, QStringList> Balancers;
|
||||
QList<RuleObject> rules;
|
||||
QString DomainStrategy;
|
||||
//
|
||||
QJsonArray inbounds;
|
||||
QJsonArray outbounds;
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user