mirror of
https://github.com/Qv2ray/Qv2ray.git
synced 2025-05-20 02:40:20 +08:00
add: added connection edit feature
This commit is contained in:
parent
f339b814e1
commit
b03849d9df
@ -15,8 +15,10 @@ INCLUDEPATH += /usr/local/include/
|
||||
message(" --> Linking against protobuf library.")
|
||||
LIBS += -L/usr/local/lib -lprotobuf
|
||||
|
||||
message(" --> Generating geosite headers for Unix")
|
||||
system("$$PWD/../tools/unix-generate-geosite.sh $$PWD")
|
||||
!no_generate_headers {
|
||||
message(" --> Generating geosite headers for Unix")
|
||||
system("$$PWD/../tools/unix-generate-geosite.sh $$PWD")
|
||||
}
|
||||
|
||||
use_grpc {
|
||||
no_generate_headers {
|
||||
|
@ -1 +1 @@
|
||||
3963
|
||||
3986
|
||||
|
@ -46,6 +46,7 @@ namespace Qv2ray::common
|
||||
}
|
||||
|
||||
request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
|
||||
request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true);
|
||||
request.setHeader(QNetworkRequest::KnownHeaders::UserAgentHeader, "Mozilla/5.0 (rv:71.0) Gecko/20100101 Firefox/71.0");
|
||||
reply = accessManager.get(request);
|
||||
connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished_p);
|
||||
@ -105,6 +106,10 @@ namespace Qv2ray::common
|
||||
|
||||
void QvHttpRequestHelper::onRequestFinished_p()
|
||||
{
|
||||
if (reply->attribute(QNetworkRequest::HTTP2WasUsedAttribute).toBool()) {
|
||||
DEBUG(MODULE_NETWORK, "HTTP/2 was used.")
|
||||
}
|
||||
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
QString error = QMetaEnum::fromType<QNetworkReply::NetworkError>().key(reply->error());
|
||||
LOG(MODULE_NETWORK, "Network request error string: " + error)
|
||||
|
@ -31,15 +31,19 @@ namespace Qv2ray::common
|
||||
source->close();
|
||||
return str;
|
||||
}
|
||||
|
||||
bool StringToFile(const QString *text, QFile *targetFile)
|
||||
bool StringToFile(const QString &text, const QString &targetpath)
|
||||
{
|
||||
bool override = targetFile->exists();
|
||||
targetFile->open(QFile::WriteOnly);
|
||||
QTextStream stream(targetFile);
|
||||
stream << *text << endl;
|
||||
auto file = QFile(targetpath);
|
||||
return StringToFile(text, file);
|
||||
}
|
||||
bool StringToFile(const QString &text, QFile &targetFile)
|
||||
{
|
||||
bool override = targetFile.exists();
|
||||
targetFile.open(QFile::WriteOnly);
|
||||
QTextStream stream(&targetFile);
|
||||
stream << text << endl;
|
||||
stream.flush();
|
||||
targetFile->close();
|
||||
targetFile.close();
|
||||
return override;
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,8 @@ namespace Qv2ray::common
|
||||
//
|
||||
QString StringFromFile(const QString &filePath);
|
||||
QString StringFromFile(QFile *source);
|
||||
bool StringToFile(const QString *text, QFile *target);
|
||||
bool StringToFile(const QString &text, QFile &target);
|
||||
bool StringToFile(const QString &text, const QString &targetpath);
|
||||
//
|
||||
QJsonObject JsonFromString(QString string);
|
||||
QString JsonToString(QJsonObject json, QJsonDocument::JsonFormat format = QJsonDocument::JsonFormat::Indented);
|
||||
|
@ -1,8 +1,9 @@
|
||||
#include "CoreUtils.hpp"
|
||||
#include "common/QvHelpers.hpp"
|
||||
|
||||
namespace Qv2ray::core
|
||||
{
|
||||
bool IsComplexConfig(CONFIGROOT root)
|
||||
bool IsComplexConfig(const CONFIGROOT &root)
|
||||
{
|
||||
bool cRouting = root.contains("routing");
|
||||
bool cRule = cRouting && root["routing"].toObject().contains("rules");
|
||||
@ -15,5 +16,34 @@ namespace Qv2ray::core
|
||||
bool cOutboundCount = cOutbounds && root["outbounds"].toArray().count() > 1;
|
||||
return cRules || cInboundCount || cOutboundCount;
|
||||
}
|
||||
|
||||
bool GetOutboundData(const OUTBOUND &out, QString *host, int *port, QString *protocol)
|
||||
{
|
||||
// Set initial values.
|
||||
*host = QObject::tr("N/A");
|
||||
*port = 0;
|
||||
*protocol = out["protocol"].toString(QObject::tr("N/A")).toLower();
|
||||
|
||||
if (*protocol == "vmess") {
|
||||
auto Server = StructFromJsonString<VMessServerObject>(JsonToString(out["settings"].toObject()["vnext"].toArray().first().toObject()));
|
||||
*host = Server.address;
|
||||
*port = Server.port;
|
||||
return true;
|
||||
} else if (*protocol == "shadowsocks") {
|
||||
auto x = JsonToString(out["settings"].toObject()["servers"].toArray().first().toObject());
|
||||
auto Server = StructFromJsonString<ShadowSocksServerObject>(x);
|
||||
*host = Server.address;
|
||||
*port = Server.port;
|
||||
return true;
|
||||
} else if (*protocol == "socks") {
|
||||
auto x = JsonToString(out["settings"].toObject()["servers"].toArray().first().toObject());
|
||||
auto Server = StructFromJsonString<SocksServerObject>(x);
|
||||
*host = Server.address;
|
||||
*port = Server.port;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,8 @@ namespace Qv2ray::core
|
||||
return in.QV2RAY_RULE_TAG;
|
||||
}
|
||||
|
||||
bool IsComplexConfig(CONFIGROOT root);
|
||||
bool GetOutboundData(const OUTBOUND &out, QString *host, int *port, QString *protocol);
|
||||
bool IsComplexConfig(const CONFIGROOT &root);
|
||||
}
|
||||
|
||||
using namespace Qv2ray::core;
|
||||
|
@ -6,9 +6,8 @@ namespace Qv2ray::core::config
|
||||
void SaveGlobalConfig(const Qv2rayConfig &conf)
|
||||
{
|
||||
GlobalConfig = conf;
|
||||
QFile config(QV2RAY_CONFIG_FILE);
|
||||
QString str = StructToJsonString(conf);
|
||||
StringToFile(&str, &config);
|
||||
StringToFile(str, QV2RAY_CONFIG_FILE);
|
||||
}
|
||||
|
||||
void SetConfigDirPath(const QString &path)
|
||||
|
@ -5,12 +5,6 @@ namespace Qv2ray::core::connection
|
||||
{
|
||||
namespace ConnectionIO
|
||||
{
|
||||
|
||||
//CONFIGROOT GetConnectionRoot(const SubscriptionId &subscription, const ConnectionId &id)
|
||||
//{
|
||||
// return ReadConnectionInternal(QV2RAY_SUBSCRIPTION_DIR + subscription.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION);
|
||||
//}
|
||||
|
||||
////
|
||||
//// Save Connection to a place, with checking if there's existing file.
|
||||
//// If so, append "_N" to the name.
|
||||
|
@ -284,7 +284,6 @@ namespace Qv2ray::core::handlers
|
||||
path.prepend(groups[group].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR);
|
||||
return CONFIGROOT(JsonFromString(StringFromFile(path)));
|
||||
}
|
||||
//
|
||||
|
||||
const tuple<QString, int> QvConnectionHandler::GetConnectionInfo(const ConnectionId &id) const
|
||||
{
|
||||
@ -296,7 +295,7 @@ namespace Qv2ray::core::handlers
|
||||
for (auto item : root["outbounds"].toArray()) {
|
||||
OUTBOUND outBoundRoot = OUTBOUND(item.toObject());
|
||||
QString outboundType = "";
|
||||
validOutboundFound = CHGetOutboundData_p(outBoundRoot, &host, &port);
|
||||
validOutboundFound = GetOutboundData(outBoundRoot, &host, &port, &outboundType);
|
||||
|
||||
if (validOutboundFound) {
|
||||
return make_tuple(host, port);
|
||||
@ -308,34 +307,7 @@ namespace Qv2ray::core::handlers
|
||||
return make_tuple(QObject::tr("N/A"), 0);
|
||||
}
|
||||
|
||||
bool QvConnectionHandler::CHGetOutboundData_p(const OUTBOUND &out, QString *host, int *port) const
|
||||
{
|
||||
// Set initial values.
|
||||
*host = QObject::tr("N/A");
|
||||
*port = 0;
|
||||
auto protocol = out["protocol"].toString(QObject::tr("N/A")).toLower();
|
||||
|
||||
if (protocol == "vmess") {
|
||||
auto Server = StructFromJsonString<VMessServerObject>(JsonToString(out["settings"].toObject()["vnext"].toArray().first().toObject()));
|
||||
*host = Server.address;
|
||||
*port = Server.port;
|
||||
return true;
|
||||
} else if (protocol == "shadowsocks") {
|
||||
auto x = JsonToString(out["settings"].toObject()["servers"].toArray().first().toObject());
|
||||
auto Server = StructFromJsonString<ShadowSocksServerObject>(x);
|
||||
*host = Server.address;
|
||||
*port = Server.port;
|
||||
return true;
|
||||
} else if (protocol == "socks") {
|
||||
auto x = JsonToString(out["settings"].toObject()["servers"].toArray().first().toObject());
|
||||
auto Server = StructFromJsonString<SocksServerObject>(x);
|
||||
*host = Server.address;
|
||||
*port = Server.port;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void QvConnectionHandler::OnLatencyDataArrived(const QvTCPingResultObject &result)
|
||||
{
|
||||
@ -346,4 +318,13 @@ namespace Qv2ray::core::handlers
|
||||
LOG(MODULE_CORE_HANDLER, "Received a latecy result with non-exist connection id.")
|
||||
}
|
||||
}
|
||||
|
||||
bool QvConnectionHandler::UpdateConnection(const ConnectionId &id, const CONFIGROOT &root)
|
||||
{
|
||||
auto groupId = connections[id].groupId;
|
||||
auto path = (groups[groupId].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR)
|
||||
+ groupId.toString() + "/" + id.toString() + QV2RAY_CONFIG_FILE_EXTENSION;
|
||||
auto content = JsonToString(root);
|
||||
return StringToFile(content, path);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "core/tcping/QvTCPing.hpp"
|
||||
#include "core/CoreSafeTypes.hpp"
|
||||
#include "core/connection/ConnectionIO.hpp"
|
||||
#include "core/CoreUtils.hpp"
|
||||
|
||||
namespace Qv2ray::core::handlers
|
||||
{
|
||||
@ -37,7 +38,7 @@ namespace Qv2ray::core::handlers
|
||||
double GetConnectionLatency(const ConnectionId &id) const;
|
||||
const ConnectionId &CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root);
|
||||
const optional<QString> DeleteConnection(const ConnectionId &id);
|
||||
const optional<QString> UpdateConnection(const ConnectionId &id, const CONFIGROOT &root);
|
||||
bool UpdateConnection(const ConnectionId &id, const CONFIGROOT &root);
|
||||
const optional<QString> RenameConnection(const ConnectionId &id, const QString &newName);
|
||||
const ConnectionId DuplicateConnection(const ConnectionId &id);
|
||||
const optional<QString> MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId);
|
||||
@ -101,7 +102,6 @@ namespace Qv2ray::core::handlers
|
||||
private:
|
||||
void CHSaveConnectionData_p();
|
||||
//
|
||||
bool CHGetOutboundData_p(const OUTBOUND &out, QString *host, int *port) const;
|
||||
optional<QString> CHStartConnection_p(const ConnectionId &id, const CONFIGROOT &root);
|
||||
void CHStopConnection_p();
|
||||
bool CHSaveConnectionConfig_p(CONFIGROOT obj, const ConnectionId &id, bool override);
|
||||
@ -112,7 +112,7 @@ namespace Qv2ray::core::handlers
|
||||
int pingConnectionTimerId;
|
||||
QHash<GroupId, GroupMetaObject> groups;
|
||||
QHash<ConnectionId, ConnectionMetaObject> connections;
|
||||
QHash<ConnectionId, CONFIGROOT> connectionRootCache;
|
||||
//QHash<ConnectionId, CONFIGROOT> connectionRootCache;
|
||||
|
||||
private:
|
||||
QvTCPingHelper *tcpingHelper;
|
||||
|
@ -147,8 +147,7 @@ namespace Qv2ray::core::kernel
|
||||
|
||||
// Write the final configuration to the disk.
|
||||
QString json = JsonToString(root);
|
||||
QFile configFile(QV2RAY_GENERATED_FILE_PATH);
|
||||
StringToFile(&json, &configFile);
|
||||
StringToFile(json, QV2RAY_GENERATED_FILE_PATH);
|
||||
//
|
||||
auto filePath = QV2RAY_GENERATED_FILE_PATH;
|
||||
|
||||
|
@ -157,8 +157,7 @@ void RouteEditor::onNodeClicked(Node &n)
|
||||
alias = GetFirstNodeData(n, QvOutboundNodeModel, OutboundNodeData)->GetOutbound();
|
||||
QJsonObject _root = outbounds[alias].raw();
|
||||
throw new runtime_error("Not implemented");
|
||||
//auto result = GetOutboundData(OUTBOUND(_root), &host, &port, &protocol);
|
||||
//Q_UNUSED(result)
|
||||
GetOutboundData(OUTBOUND(_root), &host, &port, &protocol);
|
||||
} else {
|
||||
alias = GetFirstNodeData(n, QvInboundNodeModel, InboundNodeData)->GetInbound();
|
||||
QJsonObject _root = inbounds[alias].raw();
|
||||
|
@ -232,7 +232,7 @@ void ImportConfigWindow::on_editFileBtn_clicked()
|
||||
|
||||
if (editor.result() == QDialog::Accepted) {
|
||||
auto str = JsonToString(json);
|
||||
bool result = StringToFile(&str, &file);
|
||||
bool result = StringToFile(str, file);
|
||||
|
||||
if (!result) {
|
||||
QvMessageBoxWarn(this, tr("Edit file as JSON"), tr("Failed to save file, please check if you have proper permissions"));
|
||||
|
@ -74,12 +74,6 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr
|
||||
{
|
||||
setupUi(this);
|
||||
MainWindow::mwInstance = this;
|
||||
connect(ConnectionManager, &QvConnectionHandler::OnCrashed, [&] {
|
||||
this->show();
|
||||
QvMessageBoxWarn(this, tr("V2ray vcore terminated."),
|
||||
tr("V2ray vcore terminated unexpectedly.") + NEWLINE + NEWLINE +
|
||||
tr("To solve the problem, read the V2ray log in the log text browser."));
|
||||
});
|
||||
QvMessageBusConnect(MainWindow);
|
||||
//
|
||||
infoWidget = new ConnectionInfoWidget(this);
|
||||
@ -98,11 +92,20 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr
|
||||
updownImageBox_2->setStyleSheet("image: url(" + QV2RAY_UI_RESOURCES_ROOT + "netspeed_arrow.png)");
|
||||
//
|
||||
//
|
||||
connect(ConnectionManager, &QvConnectionHandler::OnCrashed, [&] {
|
||||
this->show();
|
||||
QvMessageBoxWarn(this, tr("V2ray vcore terminated."),
|
||||
tr("V2ray vcore terminated unexpectedly.") + NEWLINE + NEWLINE +
|
||||
tr("To solve the problem, read the V2ray log in the log text browser."));
|
||||
});
|
||||
connect(ConnectionManager, &QvConnectionHandler::OnConnected, this, &MainWindow::OnConnected);
|
||||
connect(ConnectionManager, &QvConnectionHandler::OnDisConnected, this, &MainWindow::OnDisConnected);
|
||||
connect(ConnectionManager, &QvConnectionHandler::OnStatsAvailable, this, &MainWindow::onConnectionStatsArrived);
|
||||
connect(ConnectionManager, &QvConnectionHandler::OnVCoreLogAvailable, this, &MainWindow::onVCoreLogArrived);
|
||||
//
|
||||
connect(infoWidget, &ConnectionInfoWidget::OnEditRequested, this, &MainWindow::OnEditRequested);
|
||||
connect(infoWidget, &ConnectionInfoWidget::OnJsonEditRequested, this, &MainWindow::OnJsonEditRequested);
|
||||
//
|
||||
// Setup System tray icons and menus
|
||||
hTray.setToolTip(TRAY_TOOLTIP_PREFIX);
|
||||
// Basic actions
|
||||
@ -201,10 +204,7 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr
|
||||
|
||||
if (!GlobalConfig.autoStartId.isEmpty()) {
|
||||
auto id = ConnectionId(GlobalConfig.autoStartId);
|
||||
ConnectionManager->StartConnection(id);
|
||||
needShowWindow = !ConnectionManager->IsConnected(id);
|
||||
} else {
|
||||
needShowWindow = true;
|
||||
needShowWindow = ConnectionManager->StartConnection(id).has_value();
|
||||
}
|
||||
|
||||
if (needShowWindow) {
|
||||
@ -212,6 +212,9 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr
|
||||
}
|
||||
|
||||
//// If we are not connected to anything, show the MainWindow.
|
||||
if (needShowWindow) {
|
||||
}
|
||||
|
||||
#ifndef DISABLE_AUTO_UPDATE
|
||||
requestHelper = new QvHttpRequestHelper();
|
||||
connect(requestHelper, &QvHttpRequestHelper::httpRequestFinished, this, &MainWindow::VersionUpdate);
|
||||
@ -298,24 +301,6 @@ MainWindow::~MainWindow()
|
||||
hTray.hide();
|
||||
}
|
||||
|
||||
//void MainWindow::on_stopButton_clicked()
|
||||
//{
|
||||
// //hTray.setToolTip(TRAY_TOOLTIP_PREFIX);
|
||||
// //statusLabel->setText(tr("Disconnected"));
|
||||
// action_Tray_Start->setEnabled(true);
|
||||
// action_Tray_Stop->setEnabled(false);
|
||||
// action_Tray_Reconnect->setEnabled(false);
|
||||
// // Set to false as the system proxy has been cleared in the StopConnection function.
|
||||
// tray_SystemProxyMenu->setEnabled(false);
|
||||
// //startButton->setEnabled(true);
|
||||
// //stopButton->setEnabled(false);
|
||||
// ////
|
||||
// //netspeedLabel->setText("0.00 B/s\r\n0.00 B/s");
|
||||
// //dataamountLabel->setText("0.00 B\r\n0.00 B");
|
||||
// //LOG(UI, "Stopped successfully.")
|
||||
// //this->hTray.showMessage("Qv2ray", tr("Disconnected from: ") + CurrentConnectionIdentifier.IdentifierString());
|
||||
//}
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
this->hide();
|
||||
@ -579,50 +564,6 @@ void MainWindow::on_importConfigButton_clicked()
|
||||
}
|
||||
void MainWindow::on_editConfigButton_clicked()
|
||||
{
|
||||
//// Check if we have a connection selected...
|
||||
//if (!IsSelectionConnectable) {
|
||||
// QvMessageBoxWarn(this, tr("No Config Selected"), tr("Please Select a Config"));
|
||||
// return;
|
||||
//}
|
||||
//
|
||||
//auto firstSelected = connectionListWidget->selectedItems().first();
|
||||
//auto _identifier = ItemConnectionIdentifier(firstSelected);
|
||||
//SUBSCRIPTION_CONFIG_MODIFY_ASK(firstSelected)
|
||||
////
|
||||
//auto outBoundRoot = connections[_identifier].config;
|
||||
//CONFIGROOT root;
|
||||
//bool isChanged = false;
|
||||
//
|
||||
//if (IsComplexConfig(outBoundRoot)) {
|
||||
// LOG(UI, "INFO: Opening route editor.")
|
||||
// RouteEditor routeWindow(outBoundRoot, this);
|
||||
// root = routeWindow.OpenEditor();
|
||||
// isChanged = routeWindow.result() == QDialog::Accepted;
|
||||
//} else {
|
||||
// LOG(UI, "INFO: Opening single connection edit window.")
|
||||
// OutboundEditor w(OUTBOUND(outBoundRoot["outbounds"].toArray().first().toObject()), this);
|
||||
// auto outboundEntry = w.OpenEditor();
|
||||
// isChanged = w.result() == QDialog::Accepted;
|
||||
// QJsonArray outboundsList;
|
||||
// outboundsList.push_back(outboundEntry);
|
||||
// root.insert("outbounds", outboundsList);
|
||||
//}
|
||||
//
|
||||
//QString alias = _identifier.connectionName;
|
||||
//
|
||||
//if (isChanged) {
|
||||
// if (CheckConfigType(firstSelected, SUBSCRIPTION)) {
|
||||
// auto name = connections[_identifier].connectionName;
|
||||
// // Assume name will not change.
|
||||
// SaveSubscriptionConfig(root, connections[_identifier].subscriptionName, &name);
|
||||
// } else {
|
||||
// connections[_identifier].config = root;
|
||||
// // true indicates the alias will NOT change
|
||||
// SaveConnectionConfig(root, &alias, true);
|
||||
// }
|
||||
//
|
||||
// OnConfigListChanged(alias == CurrentConnectionIdentifier.connectionName);
|
||||
//}
|
||||
}
|
||||
|
||||
void MainWindow::on_action_RCM_ConvToComplex_triggered()
|
||||
@ -658,26 +599,6 @@ void MainWindow::on_action_RCM_ConvToComplex_triggered()
|
||||
|
||||
void MainWindow::on_action_RCM_EditJson_triggered()
|
||||
{
|
||||
//// Check if we have a connection selected...
|
||||
//if (!IsSelectionConnectable) {
|
||||
// QvMessageBoxWarn(this, tr("No Config Selected"), tr("Please Select a Config"));
|
||||
// return;
|
||||
//}
|
||||
//
|
||||
//auto selectedFirst = connectionListWidget->currentItem();
|
||||
//auto _identifier = ItemConnectionIdentifier(selectedFirst);
|
||||
//SUBSCRIPTION_CONFIG_MODIFY_DENY(selectedFirst)
|
||||
//JsonEditor w(connections[_identifier].config, this);
|
||||
//auto root = CONFIGROOT(w.OpenEditor());
|
||||
//bool isChanged = w.result() == QDialog::Accepted;
|
||||
//QString alias = _identifier.connectionName;
|
||||
//
|
||||
//if (isChanged) {
|
||||
// connections[_identifier].config = root;
|
||||
// // Alias here will not change.
|
||||
// SaveConnectionConfig(root, &alias, true);
|
||||
// ShowAndSetConnection(CurrentConnectionIdentifier, false, false);
|
||||
//}
|
||||
}
|
||||
|
||||
void MainWindow::on_action_RCM_ShareQR_triggered()
|
||||
@ -871,3 +792,50 @@ void MainWindow::onVCoreLogArrived(const ConnectionId &id, const QString &log)
|
||||
if (val >= max * 0.8 || val >= max - 20)
|
||||
bar->setValue(max);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::OnEditRequested(const ConnectionId &id)
|
||||
{
|
||||
auto outBoundRoot = ConnectionManager->GetConnectionRoot(id);
|
||||
CONFIGROOT root;
|
||||
bool isChanged = false;
|
||||
|
||||
if (IsComplexConfig(outBoundRoot)) {
|
||||
LOG(MODULE_UI, "INFO: Opening route editor.")
|
||||
RouteEditor routeWindow(outBoundRoot, this);
|
||||
root = routeWindow.OpenEditor();
|
||||
isChanged = routeWindow.result() == QDialog::Accepted;
|
||||
} else {
|
||||
LOG(MODULE_UI, "INFO: Opening single connection edit window.")
|
||||
auto out = OUTBOUND(outBoundRoot["outbounds"].toArray().first().toObject());
|
||||
OutboundEditor w(out, this);
|
||||
auto outboundEntry = w.OpenEditor();
|
||||
isChanged = w.result() == QDialog::Accepted;
|
||||
QJsonArray outboundsList;
|
||||
outboundsList.push_back(outboundEntry);
|
||||
root.insert("outbounds", outboundsList);
|
||||
}
|
||||
|
||||
if (isChanged) {
|
||||
//if (CheckConfigType(firstSelected, SUBSCRIPTION)) {
|
||||
// auto name = connections[_identifier].connectionName;
|
||||
// // Assume name will not change.
|
||||
// SaveSubscriptionConfig(root, connections[_identifier].subscriptionName, &name);
|
||||
//} else {
|
||||
// connections[_identifier].config = root;
|
||||
// // true indicates the alias will NOT change
|
||||
// SaveConnectionConfig(root, &alias, true);
|
||||
//}
|
||||
ConnectionManager->UpdateConnection(id, root);
|
||||
//OnConfigListChanged(alias == CurrentConnectionIdentifier.connectionName);
|
||||
}
|
||||
}
|
||||
void MainWindow::OnJsonEditRequested(const ConnectionId &id)
|
||||
{
|
||||
JsonEditor w(ConnectionManager->GetConnectionRoot(id), this);
|
||||
auto root = CONFIGROOT(w.OpenEditor());
|
||||
|
||||
if (w.result() == QDialog::Accepted) {
|
||||
ConnectionManager->UpdateConnection(id, root);
|
||||
}
|
||||
}
|
||||
|
@ -60,6 +60,8 @@ class MainWindow : public QMainWindow, Ui::MainWindow
|
||||
//
|
||||
void OnConnected(const ConnectionId &id);
|
||||
void OnDisConnected(const ConnectionId &id);
|
||||
void OnEditRequested(const ConnectionId &id);
|
||||
void OnJsonEditRequested(const ConnectionId &id);
|
||||
|
||||
void onConnectionWidgetFocusRequested(const ConnectionItemWidget *widget);
|
||||
//void onConnectionConnected(const ConnectionId &id);
|
||||
|
@ -892,8 +892,7 @@ void PreferencesWindow::on_pacGoBtn_clicked()
|
||||
QDir(QV2RAY_RULES_DIR).mkpath(QV2RAY_RULES_DIR);
|
||||
}
|
||||
|
||||
QFile privateGFWListFile(QV2RAY_RULES_GFWLIST_PATH);
|
||||
StringToFile(&fileContent, &privateGFWListFile);
|
||||
StringToFile(fileContent, QV2RAY_RULES_GFWLIST_PATH);
|
||||
}
|
||||
|
||||
void PreferencesWindow::on_pacPortSB_valueChanged(int arg1)
|
||||
|
@ -120,7 +120,7 @@ void SubscribeEditor::on_updateButton_clicked()
|
||||
subscriptions[currentSubName].address = newAddress;
|
||||
}
|
||||
|
||||
SaveConfig();
|
||||
//SaveConfig();
|
||||
|
||||
if (QvMessageBoxAsk(this, tr("Update Subscription"), tr("Would you like to reload this subscription from the Url?")) == QMessageBox::Yes) {
|
||||
StartUpdateSubscription(currentSubName);
|
||||
@ -129,10 +129,9 @@ void SubscribeEditor::on_updateButton_clicked()
|
||||
|
||||
void SubscribeEditor::StartUpdateSubscription(const QString &subscriptionName)
|
||||
{
|
||||
//this->setEnabled(false);
|
||||
//auto data = helper.syncget(subscriptions[subscriptionName].address, withProxyCB->isChecked());
|
||||
//auto content = DecodeSubscriptionString(data).trimmed();
|
||||
//
|
||||
this->setEnabled(false);
|
||||
auto data = helper.syncget(subscriptions[subscriptionName].address, withProxyCB->isChecked());
|
||||
auto content = DecodeSubscriptionString(data).trimmed();
|
||||
//if (!content.isEmpty()) {
|
||||
// connectionsList->clear();
|
||||
// auto vmessList = SplitLines(content);
|
||||
@ -160,7 +159,7 @@ void SubscribeEditor::StartUpdateSubscription(const QString &subscriptionName)
|
||||
// QvMessageBoxWarn(this, tr("Updating subscriptions"), tr("Failed to process the result from the upstream, please check your Url."));
|
||||
//}
|
||||
//
|
||||
//this->setEnabled(true);
|
||||
this->setEnabled(true);
|
||||
}
|
||||
|
||||
void SubscribeEditor::on_removeSubsButton_clicked()
|
||||
@ -213,16 +212,16 @@ void SubscribeEditor::on_subscriptionList_currentRowChanged(int currentRow)
|
||||
|
||||
void SubscribeEditor::SaveConfig()
|
||||
{
|
||||
QMap<QString, SubscriptionObject_Config> newConf;
|
||||
|
||||
for (auto _ : subscriptions.toStdMap()) {
|
||||
if (!_.second.address.isEmpty()) {
|
||||
newConf[_.first] = _.second;
|
||||
}
|
||||
}
|
||||
|
||||
GlobalConfig.subscriptions = newConf;
|
||||
SaveGlobalConfig(GlobalConfig);
|
||||
//QMap<QString, SubscriptionObject_Config> newConf;
|
||||
//
|
||||
//for (auto _ : subscriptions.toStdMap()) {
|
||||
// if (!_.second.address.isEmpty()) {
|
||||
// newConf[_.first] = _.second;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//GlobalConfig.subscriptions = newConf;
|
||||
//SaveGlobalConfig(GlobalConfig);
|
||||
}
|
||||
|
||||
void SubscribeEditor::on_buttonBox_accepted()
|
||||
|
@ -24,19 +24,19 @@ void ConnectionInfoWidget::ShowDetails(const tuple<GroupId, ConnectionId> &_iden
|
||||
{
|
||||
groupId = get<0>(_identifier);
|
||||
connectionId = get<1>(_identifier);
|
||||
bool isConnection = connectionId != NullConnectionId;
|
||||
editJsonBtn->setEnabled(isConnection);
|
||||
connectBtn->setEnabled(isConnection);
|
||||
duplicateBtn->setEnabled(isConnection);
|
||||
editBtn->setEnabled(isConnection);
|
||||
|
||||
if (connectionId != NullConnectionId) {
|
||||
//connNameLabel->setText(ConnectionManager->GetDisplayName(connectionId));
|
||||
if (isConnection) {
|
||||
groupLabel->setText(ConnectionManager->GetDisplayName(groupId, 175));
|
||||
protocolLabel->setText(ConnectionManager->GetConnectionProtocolString(connectionId));
|
||||
auto [host, port] = ConnectionManager->GetConnectionInfo(connectionId);
|
||||
addressLabel->setText(host);
|
||||
portLabel->setNum(port);
|
||||
//
|
||||
editJsonBtn->setEnabled(true);
|
||||
connectBtn->setEnabled(true);
|
||||
duplicateBtn->setEnabled(true);
|
||||
//
|
||||
auto shareLink = ConvertConfigToString(connectionId);
|
||||
shareLinkTxt->setText(shareLink);
|
||||
shareLinkTxt->setCursorPosition(0);
|
||||
@ -55,10 +55,6 @@ void ConnectionInfoWidget::ShowDetails(const tuple<GroupId, ConnectionId> &_iden
|
||||
addressLabel->setText(tr("N/A"));
|
||||
portLabel->setText(tr("N/A"));
|
||||
//
|
||||
editJsonBtn->setEnabled(false);
|
||||
connectBtn->setEnabled(false);
|
||||
duplicateBtn->setEnabled(false);
|
||||
//
|
||||
shareLinkTxt->clear();
|
||||
qrLabel->clear();
|
||||
}
|
||||
@ -76,27 +72,15 @@ void ConnectionInfoWidget::on_connectBtn_clicked()
|
||||
ConnectionManager->StartConnection(connectionId);
|
||||
}
|
||||
}
|
||||
//// Share QR
|
||||
//if (!IsSelectionConnectable) {
|
||||
// return;
|
||||
//}
|
||||
//
|
||||
//auto _identifier = ItemConnectionIdentifier(connectionListWidget->currentItem());
|
||||
//auto root = connections[_identifier].config;
|
||||
//auto type = get<2>(GetConnectionInfo(root));
|
||||
//
|
||||
//if (!IsComplexConfig(root) && (type == "vmess" || type == "shadowsocks")) {
|
||||
// ConfigExporter v(root, _identifier, this);
|
||||
// v.OpenExport();
|
||||
//} else {
|
||||
// QvMessageBoxWarn(this, tr("Share Connection"), tr("There're no support of sharing configs other than vmess and shadowsocks"));
|
||||
//}
|
||||
|
||||
void ConnectionInfoWidget::on_editBtn_clicked()
|
||||
{
|
||||
emit OnEditRequested(connectionId);
|
||||
}
|
||||
|
||||
void ConnectionInfoWidget::on_editJsonBtn_clicked()
|
||||
{
|
||||
emit OnJsonEditRequested(connectionId);
|
||||
}
|
||||
|
||||
void ConnectionInfoWidget::on_deleteBtn_clicked()
|
||||
|
@ -13,6 +13,10 @@ class ConnectionInfoWidget : public QWidget, private Ui::ConnectionInfoWidget
|
||||
void ShowDetails(const tuple<GroupId, ConnectionId> &_identifier);
|
||||
~ConnectionInfoWidget();
|
||||
|
||||
signals:
|
||||
void OnEditRequested(const ConnectionId &id);
|
||||
void OnJsonEditRequested(const ConnectionId &id);
|
||||
|
||||
private slots:
|
||||
void on_connectBtn_clicked();
|
||||
void on_editBtn_clicked();
|
||||
@ -25,9 +29,7 @@ class ConnectionInfoWidget : public QWidget, private Ui::ConnectionInfoWidget
|
||||
private slots:
|
||||
void OnConnected(const ConnectionId &id);
|
||||
void OnDisConnected(const ConnectionId &id);
|
||||
|
||||
void on_duplicateBtn_clicked();
|
||||
|
||||
void on_latencyBtn_clicked();
|
||||
|
||||
private:
|
||||
|
Loading…
Reference in New Issue
Block a user