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.")
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 {

View File

@ -1 +1 @@
3963
3986

View File

@ -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)

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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)

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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();

View File

@ -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"));

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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)

View File

@ -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()

View File

@ -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()

View File

@ -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: