From cdc87d61d7b23c07d2aa97541bad0b1e096ac1fa Mon Sep 17 00:00:00 2001 From: QwQ <59914293+Qv2ray-dev@users.noreply.github.com> Date: Thu, 23 Jul 2020 20:12:14 +0800 Subject: [PATCH] add: added copy existing config, link existing config, edit existing config --- makespec/BUILDVERSION | 2 +- src/base/models/QvComplexConfigModels.hpp | 1 + src/ui/editors/w_RoutesEditor.cpp | 82 +++---------------- src/ui/editors/w_RoutesEditor.hpp | 2 + src/ui/editors/w_RoutesEditor.ui | 15 +++- src/ui/node/NodeDispatcher.cpp | 32 ++++++++ src/ui/node/NodeDispatcher.hpp | 3 + src/ui/node/widgets/InboundOutboundWidget.cpp | 81 ++++++++++++++---- src/ui/node/widgets/InboundOutboundWidget.hpp | 7 ++ src/ui/node/widgets/InboundOutboundWidget.ui | 61 ++++++++------ 10 files changed, 172 insertions(+), 114 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index d01f253a..3d971f5a 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -5820 +5821 diff --git a/src/base/models/QvComplexConfigModels.hpp b/src/base/models/QvComplexConfigModels.hpp index 2e91dafe..a58619a5 100644 --- a/src/base/models/QvComplexConfigModels.hpp +++ b/src/base/models/QvComplexConfigModels.hpp @@ -107,6 +107,7 @@ namespace Qv2ray::base::objects::complex { OutboundObjectMeta meta; meta.metaType = METAOUTBOUND_ORIGINAL; + meta.object.mode = MODE_CONNECTIONID; meta.object.connectionId = id; meta.object.displayName = tag; return meta; diff --git a/src/ui/editors/w_RoutesEditor.cpp b/src/ui/editors/w_RoutesEditor.cpp index 464ac1db..206e2ec3 100644 --- a/src/ui/editors/w_RoutesEditor.cpp +++ b/src/ui/editors/w_RoutesEditor.cpp @@ -71,7 +71,6 @@ void RouteEditor::SetupNodeWidget() nodeScene = new FlowScene(this); flowView = new FlowView(nodeScene, nodeGraphWidget); flowView->scaleDown(); - flowView->scaleDown(); if (!nodeGraphWidget->layout()) { // The QWidget will take ownership of layout. @@ -416,79 +415,18 @@ void RouteEditor::on_delBtn_clicked() return; } - auto firstNode = nodeScene->selectedNodes()[0]; - auto isInbound = false; // inboundNodes.values().contains(firstNode->id()); - auto isOutbound = false; // outboundNodes.values().contains(firstNode->id()); - auto isRule = false; // ruleNodes.values().contains(firstNode->id()); - - // Get the tag first, and call inbounds/outbounds/rules container variable - // remove() Remove the node last since some events may trigger. Then remove - // the node container. - if (isInbound) + const auto selecteNodes = nodeScene->selectedNodes(); + if (selecteNodes.empty()) { - // currentInboundOutboundTag = GetFirstNodeData(firstNode->id(), InboundNode)->GetInbound(); - // nodeScene->removeNode(*nodeScene->node(inboundNodes[currentInboundOutboundTag])); - // inboundNodes.remove(currentInboundOutboundTag); - // - // // Remove corresponded inbound tags from the rules. - // for (auto k : rules.keys()) - // { - // auto v = rules[k]; - // v.inboundTag.removeAll(currentInboundOutboundTag); - // rules[k] = v; - // } - // - // inbounds.remove(currentInboundOutboundTag); - } - else if (isOutbound) - { - // currentInboundOutboundTag = GetFirstNodeData(firstNode->id(), OutboundNode)->GetOutbound(); - // outbounds.remove(currentInboundOutboundTag); - // ResolveDefaultOutboundTag(currentInboundOutboundTag, ""); - // - //// Remove corresponded outbound tags from the rules. - // for (auto k : rules.keys()) - //{ - // auto v = rules[k]; - // - // if (v.outboundTag == currentInboundOutboundTag) - // v.outboundTag.clear(); - // - // rules[k] = v; - //} - // - // nodeScene->removeNode(*nodeScene->node(outboundNodes[currentInboundOutboundTag])); - // outboundNodes.remove(currentInboundOutboundTag); - } - else if (isRule) - { - // ruleEnableCB->setEnabled(false); - // ruleTagLineEdit->setEnabled(false); - // ruleRenameBtn->setEnabled(false); - // auto RuleTag = GetFirstNodeData(firstNode->id(), RuleNode)->GetRuleTag(); - // currentRuleTag.clear(); - // routeRuleGroupBox->setEnabled(false); - // routeEditGroupBox->setEnabled(false); - // rules.remove(RuleTag); - // nodeScene->removeNode(*nodeScene->node(ruleNodes[RuleTag])); - // ruleNodes.remove(RuleTag); - //// - //// Remove item from the rule order list widget. - // ruleListWidget->takeItem(ruleListWidget->row(ruleListWidget->findItems(RuleTag, Qt::MatchExactly).first())); - // CHECKEMPTYRULES - //// currentRuleTag = rules.firstKey(); - // ShowCurrentRuleDetail(); - } - else - { - LOG(MODULE_UI, "Unknown node selected.") - QvMessageBoxWarn(this, tr("Error"), tr("Qv2ray entered an unknown state.")); + QvMessageBoxWarn(this, tr("Deleting a node"), tr("You need to select a node first")); + return; } + nodeDispatcher->DeleteNode(selecteNodes.front()->id()); } + void RouteEditor::on_addRouteBtn_clicked() { - auto ruleName = nodeDispatcher->CreateRule({}); - Q_UNUSED(ruleName) + const auto _ = nodeDispatcher->CreateRule({}); } void RouteEditor::on_domainStrategyCombo_currentIndexChanged(const QString &arg1) @@ -540,3 +478,9 @@ void RouteEditor::on_debugPainterCB_clicked(bool checked) flowView->repaint(); #endif } + +void RouteEditor::on_linkExistingBtn_clicked() +{ + const auto cid = ConnectionId{ importConnBtn->currentData(Qt::UserRole).toString() }; + auto _ = nodeDispatcher->CreateOutbound(make_outbound(cid, GetDisplayName(cid))); +} diff --git a/src/ui/editors/w_RoutesEditor.hpp b/src/ui/editors/w_RoutesEditor.hpp index 500133c4..ebe5e82a 100644 --- a/src/ui/editors/w_RoutesEditor.hpp +++ b/src/ui/editors/w_RoutesEditor.hpp @@ -72,6 +72,8 @@ class RouteEditor void on_debugPainterCB_clicked(bool checked); + void on_linkExistingBtn_clicked(); + private: // NOTE: Self managed pointer. std::shared_ptr nodeDispatcher; diff --git a/src/ui/editors/w_RoutesEditor.ui b/src/ui/editors/w_RoutesEditor.ui index 58c6679b..69bf9f24 100644 --- a/src/ui/editors/w_RoutesEditor.ui +++ b/src/ui/editors/w_RoutesEditor.ui @@ -123,11 +123,11 @@ - + - Existed Connection + Existing Connection @@ -138,9 +138,16 @@ - + - OK + Copy + + + + + + + Reference diff --git a/src/ui/node/NodeDispatcher.cpp b/src/ui/node/NodeDispatcher.cpp index 8d1e662d..22f4f642 100644 --- a/src/ui/node/NodeDispatcher.cpp +++ b/src/ui/node/NodeDispatcher.cpp @@ -83,6 +83,38 @@ void NodeDispatcher::RestoreConnections() isConstructing = false; } +void NodeDispatcher::DeleteNode(const QUuid &nodeId) +{ + bool isInbound = inboundNodes.values().contains(nodeId); + bool isOutbound = outboundNodes.values().contains(nodeId); + bool isRule = ruleNodes.values().contains(nodeId); + // Lots of duplicated checks. + { + Q_ASSERT_X(isInbound && !isOutbound, "Delete Node", "Node type error."); + Q_ASSERT_X(isInbound && !isRule, "Delete Node", "Node type error."); + Q_ASSERT_X(isOutbound && !isInbound, "Delete Node", "Node type error."); + Q_ASSERT_X(isOutbound && !isRule, "Delete Node", "Node type error."); + Q_ASSERT_X(isRule && !isInbound, "Delete Node", "Node type error."); + Q_ASSERT_X(isRule && !isOutbound, "Delete Node", "Node type error."); + } + + if (isInbound) + { + if (!inboundNodes.values().contains(nodeId)) + { + LOG(MODULE_NODE, "Could not find a inbound with id: " + nodeId.toString()) + } + } + else if (isOutbound) + { + } + else if (isRule) + { + } + else + Q_UNREACHABLE(); +} + QString NodeDispatcher::CreateInbound(INBOUND in) { auto tag = getTag(in); diff --git a/src/ui/node/NodeDispatcher.hpp b/src/ui/node/NodeDispatcher.hpp index 87d2469f..45d33322 100644 --- a/src/ui/node/NodeDispatcher.hpp +++ b/src/ui/node/NodeDispatcher.hpp @@ -50,6 +50,9 @@ class NodeDispatcher return outbounds.count(); } + public: + void DeleteNode(const QUuid &nodeId); + signals: void OnInboundCreated(std::shared_ptr, QtNodes::Node &); void OnOutboundCreated(std::shared_ptr, QtNodes::Node &); diff --git a/src/ui/node/widgets/InboundOutboundWidget.cpp b/src/ui/node/widgets/InboundOutboundWidget.cpp index 0da77427..0b766fd9 100644 --- a/src/ui/node/widgets/InboundOutboundWidget.cpp +++ b/src/ui/node/widgets/InboundOutboundWidget.cpp @@ -2,6 +2,8 @@ #include "base/Qv2rayBase.hpp" #include "core/CoreUtils.hpp" +#include "core/handler/ConfigHandler.hpp" +#include "ui/common/UIBase.hpp" #include "ui/editors/w_InboundEditor.hpp" #include "ui/editors/w_JsonEditor.hpp" #include "ui/editors/w_OutboundEditor.hpp" @@ -10,6 +12,8 @@ InboundOutboundWidget::InboundOutboundWidget(WidgetMode mode, std::shared_ptrsetIcon(QICON_R("edit")); + editJsonBtn->setIcon(QICON_R("code")); } void InboundOutboundWidget::setValue(std::shared_ptr data) @@ -23,7 +27,10 @@ void InboundOutboundWidget::setValue(std::shared_ptr data) { assert(workingMode == MODE_OUTBOUND); outboundObject = data; - tagTxt->setText(getTag(outboundObject->realOutbound)); + tagTxt->setText(outboundObject->getTag()); + isExternalOutbound = outboundObject->object.mode == MODE_CONNECTIONID; + statusLabel->setText(isExternalOutbound ? tr("External Config") : ""); + tagTxt->setEnabled(!isExternalOutbound); } void InboundOutboundWidget::changeEvent(QEvent *e) @@ -56,13 +63,37 @@ void InboundOutboundWidget::on_editBtn_clicked() } case MODE_OUTBOUND: { - OutboundEditor editor{ outboundObject->realOutbound, parentWidget() }; - outboundObject->realOutbound = editor.OpenEditor(); - // Set tag - const auto newTag = getTag(outboundObject->realOutbound); - tagTxt->setText(newTag); - outboundObject->realOutbound["tag"] = newTag; - break; + if (isExternalOutbound) + { + if (QvMessageBoxAsk(parentWidget(), tr("Edit Outbound"), editExternalMsg) != QMessageBox::Yes) + { + return; + } + const auto externalId = outboundObject->object.connectionId; + const auto root = ConnectionManager->GetConnectionRoot(externalId); + if (IsComplexConfig(root)) + { + if (QvMessageBoxAsk(parentWidget(), tr("Trying to edit an Complex Config"), editExternalComplexMsg) != QMessageBox::Yes) + { + return; + } + } + OUTBOUND outbound{ QJsonIO::GetValue(root, "outbounds", 0).toObject() }; + OutboundEditor editor{ outbound, parentWidget() }; + outbound = editor.OpenEditor(); + // + ConnectionManager->UpdateConnection(externalId, CONFIGROOT{ QJsonObject{ { "outbounds", QJsonArray{ outbound } } } }); + } + else + { + OutboundEditor editor{ outboundObject->realOutbound, parentWidget() }; + outboundObject->realOutbound = editor.OpenEditor(); + // Set tag + const auto newTag = getTag(outboundObject->realOutbound); + tagTxt->setText(newTag); + outboundObject->realOutbound["tag"] = newTag; + break; + } } } } @@ -83,13 +114,33 @@ void InboundOutboundWidget::on_editJsonBtn_clicked() } case MODE_OUTBOUND: { - JsonEditor editor{ outboundObject->realOutbound, parentWidget() }; - outboundObject->realOutbound = OUTBOUND{ editor.OpenEditor() }; - const auto newTag = getTag(outboundObject->realOutbound); - // Set tag - tagTxt->setText(newTag); - outboundObject->realOutbound["tag"] = newTag; - break; + if (isExternalOutbound) + { + if (QvMessageBoxAsk(parentWidget(), tr("Edit Outbound"), editExternalMsg) != QMessageBox::Yes) + { + return; + } + const auto externalId = outboundObject->object.connectionId; + const auto root = ConnectionManager->GetConnectionRoot(externalId); + + OUTBOUND outbound{ QJsonIO::GetValue(root, "outbounds", 0).toObject() }; + JsonEditor editor{ outbound, parentWidget() }; + outbound = OUTBOUND{ editor.OpenEditor() }; + // + ConnectionManager->UpdateConnection(externalId, CONFIGROOT{ QJsonObject{ { "outbounds", QJsonArray{ outbound } } } }); + } + else + { + // Open Editor + JsonEditor editor{ outboundObject->realOutbound, parentWidget() }; + outboundObject->realOutbound = OUTBOUND{ editor.OpenEditor() }; + // + // Set tag (only for local connections) + const auto newTag = getTag(outboundObject->realOutbound); + tagTxt->setText(newTag); + outboundObject->realOutbound["tag"] = newTag; + break; + } } } } diff --git a/src/ui/node/widgets/InboundOutboundWidget.hpp b/src/ui/node/widgets/InboundOutboundWidget.hpp index 10722900..78b96de4 100644 --- a/src/ui/node/widgets/InboundOutboundWidget.hpp +++ b/src/ui/node/widgets/InboundOutboundWidget.hpp @@ -33,4 +33,11 @@ class InboundOutboundWidget WidgetMode workingMode; std::shared_ptr inboundObject; std::shared_ptr outboundObject; + bool isExternalOutbound = false; + + private: + const QString editExternalMsg = tr("You are trying to edit an external connection config, is this what you want?"); + const QString editExternalComplexMsg = tr("You have selected an complex config as outbound.") + NEWLINE + + tr("continuing editing this configuration will make you LOSS ALL INBOUND AND ROUTING settings.") + + NEWLINE + tr("Is this what you want?"); }; diff --git a/src/ui/node/widgets/InboundOutboundWidget.ui b/src/ui/node/widgets/InboundOutboundWidget.ui index 5f3d3551..470c0d33 100644 --- a/src/ui/node/widgets/InboundOutboundWidget.ui +++ b/src/ui/node/widgets/InboundOutboundWidget.ui @@ -6,14 +6,14 @@ 0 0 - 152 - 64 + 181 + 66 Form - + 0 @@ -26,30 +26,41 @@ 0 - + - - - - - - - - :/assets/icons/ui_dark/edit.svg:/assets/icons/ui_dark/edit.svg - - - - - - - - - - - :/assets/icons/ui_dark/code.svg:/assets/icons/ui_dark/code.svg - - + + + + + + + + + + :/assets/icons/ui_light/edit.svg:/assets/icons/ui_light/edit.svg + + + + + + + + + + + :/assets/icons/ui_light/code.svg:/assets/icons/ui_light/code.svg + + + + + + + + + + +