add: added copy existing config, link existing config, edit existing config

This commit is contained in:
QwQ 2020-07-23 20:12:14 +08:00
parent b26f455166
commit cdc87d61d7
No known key found for this signature in database
GPG Key ID: E7FAEFAFCD031D4B
10 changed files with 172 additions and 114 deletions

View File

@ -1 +1 @@
5820
5821

View File

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

View File

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

View File

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

View File

@ -123,11 +123,11 @@
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="0,1,1,0">
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="0,1,1,0,0">
<item>
<widget class="QLabel" name="label_18">
<property name="text">
<string>Existed Connection</string>
<string>Existing Connection</string>
</property>
</widget>
</item>
@ -138,9 +138,16 @@
<widget class="QComboBox" name="importConnBtn"/>
</item>
<item>
<widget class="QToolButton" name="importExistingBtn">
<widget class="QPushButton" name="importExistingBtn">
<property name="text">
<string>OK</string>
<string>Copy</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="linkExistingBtn">
<property name="text">
<string>Reference</string>
</property>
</widget>
</item>

View File

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

View File

@ -50,6 +50,9 @@ class NodeDispatcher
return outbounds.count();
}
public:
void DeleteNode(const QUuid &nodeId);
signals:
void OnInboundCreated(std::shared_ptr<INBOUND>, QtNodes::Node &);
void OnOutboundCreated(std::shared_ptr<OutboundObjectMeta>, QtNodes::Node &);

View File

@ -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_ptr<No
{
workingMode = mode;
setupUi(this);
editBtn->setIcon(QICON_R("edit"));
editJsonBtn->setIcon(QICON_R("code"));
}
void InboundOutboundWidget::setValue(std::shared_ptr<INBOUND> data)
@ -23,7 +27,10 @@ void InboundOutboundWidget::setValue(std::shared_ptr<OutboundObjectMeta> 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;
}
}
}
}

View File

@ -33,4 +33,11 @@ class InboundOutboundWidget
WidgetMode workingMode;
std::shared_ptr<INBOUND> inboundObject;
std::shared_ptr<OutboundObjectMeta> 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?");
};

View File

@ -6,14 +6,14 @@
<rect>
<x>0</x>
<y>0</y>
<width>152</width>
<height>64</height>
<width>181</width>
<height>66</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
@ -26,30 +26,41 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0" colspan="2">
<item>
<widget class="QLineEdit" name="tagTxt"/>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="editBtn">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../../resources.new.qrc">
<normaloff>:/assets/icons/ui_dark/edit.svg</normaloff>:/assets/icons/ui_dark/edit.svg</iconset>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="editJsonBtn">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../../resources.new.qrc">
<normaloff>:/assets/icons/ui_dark/code.svg</normaloff>:/assets/icons/ui_dark/code.svg</iconset>
</property>
</widget>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,1">
<item>
<widget class="QPushButton" name="editBtn">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../../resources.new.qrc">
<normaloff>:/assets/icons/ui_light/edit.svg</normaloff>:/assets/icons/ui_light/edit.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="editJsonBtn">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../../resources.new.qrc">
<normaloff>:/assets/icons/ui_light/code.svg</normaloff>:/assets/icons/ui_light/code.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="statusLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>