add: added connection edit feature

This commit is contained in:
Qv2ray-dev 2020-02-26 20:21:57 +08:00
parent f339b814e1
commit b03849d9df
20 changed files with 164 additions and 195 deletions

View File

@ -15,8 +15,10 @@ INCLUDEPATH += /usr/local/include/
message(" --> Linking against protobuf library.") message(" --> Linking against protobuf library.")
LIBS += -L/usr/local/lib -lprotobuf LIBS += -L/usr/local/lib -lprotobuf
message(" --> Generating geosite headers for Unix") !no_generate_headers {
system("$$PWD/../tools/unix-generate-geosite.sh $$PWD") message(" --> Generating geosite headers for Unix")
system("$$PWD/../tools/unix-generate-geosite.sh $$PWD")
}
use_grpc { use_grpc {
no_generate_headers { no_generate_headers {

View File

@ -1 +1 @@
3963 3986

View File

@ -46,6 +46,7 @@ namespace Qv2ray::common
} }
request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy); 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"); request.setHeader(QNetworkRequest::KnownHeaders::UserAgentHeader, "Mozilla/5.0 (rv:71.0) Gecko/20100101 Firefox/71.0");
reply = accessManager.get(request); reply = accessManager.get(request);
connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished_p); connect(reply, &QNetworkReply::finished, this, &QvHttpRequestHelper::onRequestFinished_p);
@ -105,6 +106,10 @@ namespace Qv2ray::common
void QvHttpRequestHelper::onRequestFinished_p() void QvHttpRequestHelper::onRequestFinished_p()
{ {
if (reply->attribute(QNetworkRequest::HTTP2WasUsedAttribute).toBool()) {
DEBUG(MODULE_NETWORK, "HTTP/2 was used.")
}
if (reply->error() != QNetworkReply::NoError) { if (reply->error() != QNetworkReply::NoError) {
QString error = QMetaEnum::fromType<QNetworkReply::NetworkError>().key(reply->error()); QString error = QMetaEnum::fromType<QNetworkReply::NetworkError>().key(reply->error());
LOG(MODULE_NETWORK, "Network request error string: " + error) LOG(MODULE_NETWORK, "Network request error string: " + error)

View File

@ -31,15 +31,19 @@ namespace Qv2ray::common
source->close(); source->close();
return str; return str;
} }
bool StringToFile(const QString &text, const QString &targetpath)
bool StringToFile(const QString *text, QFile *targetFile)
{ {
bool override = targetFile->exists(); auto file = QFile(targetpath);
targetFile->open(QFile::WriteOnly); return StringToFile(text, file);
QTextStream stream(targetFile); }
stream << *text << endl; bool StringToFile(const QString &text, QFile &targetFile)
{
bool override = targetFile.exists();
targetFile.open(QFile::WriteOnly);
QTextStream stream(&targetFile);
stream << text << endl;
stream.flush(); stream.flush();
targetFile->close(); targetFile.close();
return override; return override;
} }

View File

@ -23,7 +23,8 @@ namespace Qv2ray::common
// //
QString StringFromFile(const QString &filePath); QString StringFromFile(const QString &filePath);
QString StringFromFile(QFile *source); 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); QJsonObject JsonFromString(QString string);
QString JsonToString(QJsonObject json, QJsonDocument::JsonFormat format = QJsonDocument::JsonFormat::Indented); QString JsonToString(QJsonObject json, QJsonDocument::JsonFormat format = QJsonDocument::JsonFormat::Indented);

View File

@ -1,8 +1,9 @@
#include "CoreUtils.hpp" #include "CoreUtils.hpp"
#include "common/QvHelpers.hpp"
namespace Qv2ray::core namespace Qv2ray::core
{ {
bool IsComplexConfig(CONFIGROOT root) bool IsComplexConfig(const CONFIGROOT &root)
{ {
bool cRouting = root.contains("routing"); bool cRouting = root.contains("routing");
bool cRule = cRouting && root["routing"].toObject().contains("rules"); bool cRule = cRouting && root["routing"].toObject().contains("rules");
@ -15,5 +16,34 @@ namespace Qv2ray::core
bool cOutboundCount = cOutbounds && root["outbounds"].toArray().count() > 1; bool cOutboundCount = cOutbounds && root["outbounds"].toArray().count() > 1;
return cRules || cInboundCount || cOutboundCount; 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;
}
}
} }

View File

@ -24,7 +24,8 @@ namespace Qv2ray::core
return in.QV2RAY_RULE_TAG; 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; using namespace Qv2ray::core;

View File

@ -6,9 +6,8 @@ namespace Qv2ray::core::config
void SaveGlobalConfig(const Qv2rayConfig &conf) void SaveGlobalConfig(const Qv2rayConfig &conf)
{ {
GlobalConfig = conf; GlobalConfig = conf;
QFile config(QV2RAY_CONFIG_FILE);
QString str = StructToJsonString(conf); QString str = StructToJsonString(conf);
StringToFile(&str, &config); StringToFile(str, QV2RAY_CONFIG_FILE);
} }
void SetConfigDirPath(const QString &path) void SetConfigDirPath(const QString &path)

View File

@ -5,12 +5,6 @@ namespace Qv2ray::core::connection
{ {
namespace ConnectionIO 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. //// Save Connection to a place, with checking if there's existing file.
//// If so, append "_N" to the name. //// If so, append "_N" to the name.

View File

@ -284,7 +284,6 @@ namespace Qv2ray::core::handlers
path.prepend(groups[group].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR); path.prepend(groups[group].isSubscription ? QV2RAY_SUBSCRIPTION_DIR : QV2RAY_CONNECTIONS_DIR);
return CONFIGROOT(JsonFromString(StringFromFile(path))); return CONFIGROOT(JsonFromString(StringFromFile(path)));
} }
//
const tuple<QString, int> QvConnectionHandler::GetConnectionInfo(const ConnectionId &id) const const tuple<QString, int> QvConnectionHandler::GetConnectionInfo(const ConnectionId &id) const
{ {
@ -296,7 +295,7 @@ namespace Qv2ray::core::handlers
for (auto item : root["outbounds"].toArray()) { for (auto item : root["outbounds"].toArray()) {
OUTBOUND outBoundRoot = OUTBOUND(item.toObject()); OUTBOUND outBoundRoot = OUTBOUND(item.toObject());
QString outboundType = ""; QString outboundType = "";
validOutboundFound = CHGetOutboundData_p(outBoundRoot, &host, &port); validOutboundFound = GetOutboundData(outBoundRoot, &host, &port, &outboundType);
if (validOutboundFound) { if (validOutboundFound) {
return make_tuple(host, port); return make_tuple(host, port);
@ -308,34 +307,7 @@ namespace Qv2ray::core::handlers
return make_tuple(QObject::tr("N/A"), 0); 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) 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.") 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);
}
} }

View File

@ -5,6 +5,7 @@
#include "core/tcping/QvTCPing.hpp" #include "core/tcping/QvTCPing.hpp"
#include "core/CoreSafeTypes.hpp" #include "core/CoreSafeTypes.hpp"
#include "core/connection/ConnectionIO.hpp" #include "core/connection/ConnectionIO.hpp"
#include "core/CoreUtils.hpp"
namespace Qv2ray::core::handlers namespace Qv2ray::core::handlers
{ {
@ -37,7 +38,7 @@ namespace Qv2ray::core::handlers
double GetConnectionLatency(const ConnectionId &id) const; double GetConnectionLatency(const ConnectionId &id) const;
const ConnectionId &CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root); const ConnectionId &CreateConnection(const QString &displayName, const GroupId &groupId, const CONFIGROOT &root);
const optional<QString> DeleteConnection(const ConnectionId &id); 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 optional<QString> RenameConnection(const ConnectionId &id, const QString &newName);
const ConnectionId DuplicateConnection(const ConnectionId &id); const ConnectionId DuplicateConnection(const ConnectionId &id);
const optional<QString> MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId); const optional<QString> MoveConnectionGroup(const ConnectionId &id, const GroupId &newGroupId);
@ -101,7 +102,6 @@ namespace Qv2ray::core::handlers
private: private:
void CHSaveConnectionData_p(); void CHSaveConnectionData_p();
// //
bool CHGetOutboundData_p(const OUTBOUND &out, QString *host, int *port) const;
optional<QString> CHStartConnection_p(const ConnectionId &id, const CONFIGROOT &root); optional<QString> CHStartConnection_p(const ConnectionId &id, const CONFIGROOT &root);
void CHStopConnection_p(); void CHStopConnection_p();
bool CHSaveConnectionConfig_p(CONFIGROOT obj, const ConnectionId &id, bool override); bool CHSaveConnectionConfig_p(CONFIGROOT obj, const ConnectionId &id, bool override);
@ -112,7 +112,7 @@ namespace Qv2ray::core::handlers
int pingConnectionTimerId; int pingConnectionTimerId;
QHash<GroupId, GroupMetaObject> groups; QHash<GroupId, GroupMetaObject> groups;
QHash<ConnectionId, ConnectionMetaObject> connections; QHash<ConnectionId, ConnectionMetaObject> connections;
QHash<ConnectionId, CONFIGROOT> connectionRootCache; //QHash<ConnectionId, CONFIGROOT> connectionRootCache;
private: private:
QvTCPingHelper *tcpingHelper; QvTCPingHelper *tcpingHelper;

View File

@ -147,8 +147,7 @@ namespace Qv2ray::core::kernel
// Write the final configuration to the disk. // Write the final configuration to the disk.
QString json = JsonToString(root); QString json = JsonToString(root);
QFile configFile(QV2RAY_GENERATED_FILE_PATH); StringToFile(json, QV2RAY_GENERATED_FILE_PATH);
StringToFile(&json, &configFile);
// //
auto filePath = QV2RAY_GENERATED_FILE_PATH; auto filePath = QV2RAY_GENERATED_FILE_PATH;

View File

@ -157,8 +157,7 @@ void RouteEditor::onNodeClicked(Node &n)
alias = GetFirstNodeData(n, QvOutboundNodeModel, OutboundNodeData)->GetOutbound(); alias = GetFirstNodeData(n, QvOutboundNodeModel, OutboundNodeData)->GetOutbound();
QJsonObject _root = outbounds[alias].raw(); QJsonObject _root = outbounds[alias].raw();
throw new runtime_error("Not implemented"); throw new runtime_error("Not implemented");
//auto result = GetOutboundData(OUTBOUND(_root), &host, &port, &protocol); GetOutboundData(OUTBOUND(_root), &host, &port, &protocol);
//Q_UNUSED(result)
} else { } else {
alias = GetFirstNodeData(n, QvInboundNodeModel, InboundNodeData)->GetInbound(); alias = GetFirstNodeData(n, QvInboundNodeModel, InboundNodeData)->GetInbound();
QJsonObject _root = inbounds[alias].raw(); QJsonObject _root = inbounds[alias].raw();

View File

@ -232,7 +232,7 @@ void ImportConfigWindow::on_editFileBtn_clicked()
if (editor.result() == QDialog::Accepted) { if (editor.result() == QDialog::Accepted) {
auto str = JsonToString(json); auto str = JsonToString(json);
bool result = StringToFile(&str, &file); bool result = StringToFile(str, file);
if (!result) { if (!result) {
QvMessageBoxWarn(this, tr("Edit file as JSON"), tr("Failed to save file, please check if you have proper permissions")); QvMessageBoxWarn(this, tr("Edit file as JSON"), tr("Failed to save file, please check if you have proper permissions"));

View File

@ -74,12 +74,6 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr
{ {
setupUi(this); setupUi(this);
MainWindow::mwInstance = 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); QvMessageBusConnect(MainWindow);
// //
infoWidget = new ConnectionInfoWidget(this); 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)"); 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::OnConnected, this, &MainWindow::OnConnected);
connect(ConnectionManager, &QvConnectionHandler::OnDisConnected, this, &MainWindow::OnDisConnected); connect(ConnectionManager, &QvConnectionHandler::OnDisConnected, this, &MainWindow::OnDisConnected);
connect(ConnectionManager, &QvConnectionHandler::OnStatsAvailable, this, &MainWindow::onConnectionStatsArrived); connect(ConnectionManager, &QvConnectionHandler::OnStatsAvailable, this, &MainWindow::onConnectionStatsArrived);
connect(ConnectionManager, &QvConnectionHandler::OnVCoreLogAvailable, this, &MainWindow::onVCoreLogArrived); 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 // Setup System tray icons and menus
hTray.setToolTip(TRAY_TOOLTIP_PREFIX); hTray.setToolTip(TRAY_TOOLTIP_PREFIX);
// Basic actions // Basic actions
@ -201,10 +204,7 @@ MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)//, vinstance(), hTr
if (!GlobalConfig.autoStartId.isEmpty()) { if (!GlobalConfig.autoStartId.isEmpty()) {
auto id = ConnectionId(GlobalConfig.autoStartId); auto id = ConnectionId(GlobalConfig.autoStartId);
ConnectionManager->StartConnection(id); needShowWindow = ConnectionManager->StartConnection(id).has_value();
needShowWindow = !ConnectionManager->IsConnected(id);
} else {
needShowWindow = true;
} }
if (needShowWindow) { 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 we are not connected to anything, show the MainWindow.
if (needShowWindow) {
}
#ifndef DISABLE_AUTO_UPDATE #ifndef DISABLE_AUTO_UPDATE
requestHelper = new QvHttpRequestHelper(); requestHelper = new QvHttpRequestHelper();
connect(requestHelper, &QvHttpRequestHelper::httpRequestFinished, this, &MainWindow::VersionUpdate); connect(requestHelper, &QvHttpRequestHelper::httpRequestFinished, this, &MainWindow::VersionUpdate);
@ -298,24 +301,6 @@ MainWindow::~MainWindow()
hTray.hide(); 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) void MainWindow::closeEvent(QCloseEvent *event)
{ {
this->hide(); this->hide();
@ -579,50 +564,6 @@ void MainWindow::on_importConfigButton_clicked()
} }
void MainWindow::on_editConfigButton_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() 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() 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() 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) if (val >= max * 0.8 || val >= max - 20)
bar->setValue(max); 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);
}
}

View File

@ -60,6 +60,8 @@ class MainWindow : public QMainWindow, Ui::MainWindow
// //
void OnConnected(const ConnectionId &id); void OnConnected(const ConnectionId &id);
void OnDisConnected(const ConnectionId &id); void OnDisConnected(const ConnectionId &id);
void OnEditRequested(const ConnectionId &id);
void OnJsonEditRequested(const ConnectionId &id);
void onConnectionWidgetFocusRequested(const ConnectionItemWidget *widget); void onConnectionWidgetFocusRequested(const ConnectionItemWidget *widget);
//void onConnectionConnected(const ConnectionId &id); //void onConnectionConnected(const ConnectionId &id);

View File

@ -892,8 +892,7 @@ void PreferencesWindow::on_pacGoBtn_clicked()
QDir(QV2RAY_RULES_DIR).mkpath(QV2RAY_RULES_DIR); QDir(QV2RAY_RULES_DIR).mkpath(QV2RAY_RULES_DIR);
} }
QFile privateGFWListFile(QV2RAY_RULES_GFWLIST_PATH); StringToFile(fileContent, QV2RAY_RULES_GFWLIST_PATH);
StringToFile(&fileContent, &privateGFWListFile);
} }
void PreferencesWindow::on_pacPortSB_valueChanged(int arg1) void PreferencesWindow::on_pacPortSB_valueChanged(int arg1)

View File

@ -120,7 +120,7 @@ void SubscribeEditor::on_updateButton_clicked()
subscriptions[currentSubName].address = newAddress; 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) { if (QvMessageBoxAsk(this, tr("Update Subscription"), tr("Would you like to reload this subscription from the Url?")) == QMessageBox::Yes) {
StartUpdateSubscription(currentSubName); StartUpdateSubscription(currentSubName);
@ -129,10 +129,9 @@ void SubscribeEditor::on_updateButton_clicked()
void SubscribeEditor::StartUpdateSubscription(const QString &subscriptionName) void SubscribeEditor::StartUpdateSubscription(const QString &subscriptionName)
{ {
//this->setEnabled(false); this->setEnabled(false);
//auto data = helper.syncget(subscriptions[subscriptionName].address, withProxyCB->isChecked()); auto data = helper.syncget(subscriptions[subscriptionName].address, withProxyCB->isChecked());
//auto content = DecodeSubscriptionString(data).trimmed(); auto content = DecodeSubscriptionString(data).trimmed();
//
//if (!content.isEmpty()) { //if (!content.isEmpty()) {
// connectionsList->clear(); // connectionsList->clear();
// auto vmessList = SplitLines(content); // 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.")); // 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() void SubscribeEditor::on_removeSubsButton_clicked()
@ -213,16 +212,16 @@ void SubscribeEditor::on_subscriptionList_currentRowChanged(int currentRow)
void SubscribeEditor::SaveConfig() void SubscribeEditor::SaveConfig()
{ {
QMap<QString, SubscriptionObject_Config> newConf; //QMap<QString, SubscriptionObject_Config> newConf;
//
for (auto _ : subscriptions.toStdMap()) { //for (auto _ : subscriptions.toStdMap()) {
if (!_.second.address.isEmpty()) { // if (!_.second.address.isEmpty()) {
newConf[_.first] = _.second; // newConf[_.first] = _.second;
} // }
} //}
//
GlobalConfig.subscriptions = newConf; //GlobalConfig.subscriptions = newConf;
SaveGlobalConfig(GlobalConfig); //SaveGlobalConfig(GlobalConfig);
} }
void SubscribeEditor::on_buttonBox_accepted() void SubscribeEditor::on_buttonBox_accepted()

View File

@ -24,19 +24,19 @@ void ConnectionInfoWidget::ShowDetails(const tuple<GroupId, ConnectionId> &_iden
{ {
groupId = get<0>(_identifier); groupId = get<0>(_identifier);
connectionId = get<1>(_identifier); connectionId = get<1>(_identifier);
bool isConnection = connectionId != NullConnectionId;
editJsonBtn->setEnabled(isConnection);
connectBtn->setEnabled(isConnection);
duplicateBtn->setEnabled(isConnection);
editBtn->setEnabled(isConnection);
if (connectionId != NullConnectionId) { if (isConnection) {
//connNameLabel->setText(ConnectionManager->GetDisplayName(connectionId));
groupLabel->setText(ConnectionManager->GetDisplayName(groupId, 175)); groupLabel->setText(ConnectionManager->GetDisplayName(groupId, 175));
protocolLabel->setText(ConnectionManager->GetConnectionProtocolString(connectionId)); protocolLabel->setText(ConnectionManager->GetConnectionProtocolString(connectionId));
auto [host, port] = ConnectionManager->GetConnectionInfo(connectionId); auto [host, port] = ConnectionManager->GetConnectionInfo(connectionId);
addressLabel->setText(host); addressLabel->setText(host);
portLabel->setNum(port); portLabel->setNum(port);
// //
editJsonBtn->setEnabled(true);
connectBtn->setEnabled(true);
duplicateBtn->setEnabled(true);
//
auto shareLink = ConvertConfigToString(connectionId); auto shareLink = ConvertConfigToString(connectionId);
shareLinkTxt->setText(shareLink); shareLinkTxt->setText(shareLink);
shareLinkTxt->setCursorPosition(0); shareLinkTxt->setCursorPosition(0);
@ -55,10 +55,6 @@ void ConnectionInfoWidget::ShowDetails(const tuple<GroupId, ConnectionId> &_iden
addressLabel->setText(tr("N/A")); addressLabel->setText(tr("N/A"));
portLabel->setText(tr("N/A")); portLabel->setText(tr("N/A"));
// //
editJsonBtn->setEnabled(false);
connectBtn->setEnabled(false);
duplicateBtn->setEnabled(false);
//
shareLinkTxt->clear(); shareLinkTxt->clear();
qrLabel->clear(); qrLabel->clear();
} }
@ -76,27 +72,15 @@ void ConnectionInfoWidget::on_connectBtn_clicked()
ConnectionManager->StartConnection(connectionId); 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() void ConnectionInfoWidget::on_editBtn_clicked()
{ {
emit OnEditRequested(connectionId);
} }
void ConnectionInfoWidget::on_editJsonBtn_clicked() void ConnectionInfoWidget::on_editJsonBtn_clicked()
{ {
emit OnJsonEditRequested(connectionId);
} }
void ConnectionInfoWidget::on_deleteBtn_clicked() void ConnectionInfoWidget::on_deleteBtn_clicked()

View File

@ -13,6 +13,10 @@ class ConnectionInfoWidget : public QWidget, private Ui::ConnectionInfoWidget
void ShowDetails(const tuple<GroupId, ConnectionId> &_identifier); void ShowDetails(const tuple<GroupId, ConnectionId> &_identifier);
~ConnectionInfoWidget(); ~ConnectionInfoWidget();
signals:
void OnEditRequested(const ConnectionId &id);
void OnJsonEditRequested(const ConnectionId &id);
private slots: private slots:
void on_connectBtn_clicked(); void on_connectBtn_clicked();
void on_editBtn_clicked(); void on_editBtn_clicked();
@ -25,9 +29,7 @@ class ConnectionInfoWidget : public QWidget, private Ui::ConnectionInfoWidget
private slots: private slots:
void OnConnected(const ConnectionId &id); void OnConnected(const ConnectionId &id);
void OnDisConnected(const ConnectionId &id); void OnDisConnected(const ConnectionId &id);
void on_duplicateBtn_clicked(); void on_duplicateBtn_clicked();
void on_latencyBtn_clicked(); void on_latencyBtn_clicked();
private: private: