mirror of
https://github.com/Qv2ray/Qv2ray.git
synced 2025-05-20 10:50:23 +08:00
add: added copy existing config, link existing config, edit existing config
This commit is contained in:
parent
b26f455166
commit
cdc87d61d7
@ -1 +1 @@
|
|||||||
5820
|
5821
|
||||||
|
@ -107,6 +107,7 @@ namespace Qv2ray::base::objects::complex
|
|||||||
{
|
{
|
||||||
OutboundObjectMeta meta;
|
OutboundObjectMeta meta;
|
||||||
meta.metaType = METAOUTBOUND_ORIGINAL;
|
meta.metaType = METAOUTBOUND_ORIGINAL;
|
||||||
|
meta.object.mode = MODE_CONNECTIONID;
|
||||||
meta.object.connectionId = id;
|
meta.object.connectionId = id;
|
||||||
meta.object.displayName = tag;
|
meta.object.displayName = tag;
|
||||||
return meta;
|
return meta;
|
||||||
|
@ -71,7 +71,6 @@ void RouteEditor::SetupNodeWidget()
|
|||||||
nodeScene = new FlowScene(this);
|
nodeScene = new FlowScene(this);
|
||||||
flowView = new FlowView(nodeScene, nodeGraphWidget);
|
flowView = new FlowView(nodeScene, nodeGraphWidget);
|
||||||
flowView->scaleDown();
|
flowView->scaleDown();
|
||||||
flowView->scaleDown();
|
|
||||||
if (!nodeGraphWidget->layout())
|
if (!nodeGraphWidget->layout())
|
||||||
{
|
{
|
||||||
// The QWidget will take ownership of layout.
|
// The QWidget will take ownership of layout.
|
||||||
@ -416,79 +415,18 @@ void RouteEditor::on_delBtn_clicked()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto firstNode = nodeScene->selectedNodes()[0];
|
const auto selecteNodes = nodeScene->selectedNodes();
|
||||||
auto isInbound = false; // inboundNodes.values().contains(firstNode->id());
|
if (selecteNodes.empty())
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
// currentInboundOutboundTag = GetFirstNodeData(firstNode->id(), InboundNode)->GetInbound();
|
QvMessageBoxWarn(this, tr("Deleting a node"), tr("You need to select a node first"));
|
||||||
// nodeScene->removeNode(*nodeScene->node(inboundNodes[currentInboundOutboundTag]));
|
return;
|
||||||
// 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."));
|
|
||||||
}
|
}
|
||||||
|
nodeDispatcher->DeleteNode(selecteNodes.front()->id());
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouteEditor::on_addRouteBtn_clicked()
|
void RouteEditor::on_addRouteBtn_clicked()
|
||||||
{
|
{
|
||||||
auto ruleName = nodeDispatcher->CreateRule({});
|
const auto _ = nodeDispatcher->CreateRule({});
|
||||||
Q_UNUSED(ruleName)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouteEditor::on_domainStrategyCombo_currentIndexChanged(const QString &arg1)
|
void RouteEditor::on_domainStrategyCombo_currentIndexChanged(const QString &arg1)
|
||||||
@ -540,3 +478,9 @@ void RouteEditor::on_debugPainterCB_clicked(bool checked)
|
|||||||
flowView->repaint();
|
flowView->repaint();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RouteEditor::on_linkExistingBtn_clicked()
|
||||||
|
{
|
||||||
|
const auto cid = ConnectionId{ importConnBtn->currentData(Qt::UserRole).toString() };
|
||||||
|
auto _ = nodeDispatcher->CreateOutbound(make_outbound(cid, GetDisplayName(cid)));
|
||||||
|
}
|
||||||
|
@ -72,6 +72,8 @@ class RouteEditor
|
|||||||
|
|
||||||
void on_debugPainterCB_clicked(bool checked);
|
void on_debugPainterCB_clicked(bool checked);
|
||||||
|
|
||||||
|
void on_linkExistingBtn_clicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// NOTE: Self managed pointer.
|
// NOTE: Self managed pointer.
|
||||||
std::shared_ptr<NodeDispatcher> nodeDispatcher;
|
std::shared_ptr<NodeDispatcher> nodeDispatcher;
|
||||||
|
@ -123,11 +123,11 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<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>
|
<item>
|
||||||
<widget class="QLabel" name="label_18">
|
<widget class="QLabel" name="label_18">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Existed Connection</string>
|
<string>Existing Connection</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -138,9 +138,16 @@
|
|||||||
<widget class="QComboBox" name="importConnBtn"/>
|
<widget class="QComboBox" name="importConnBtn"/>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QToolButton" name="importExistingBtn">
|
<widget class="QPushButton" name="importExistingBtn">
|
||||||
<property name="text">
|
<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>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -83,6 +83,38 @@ void NodeDispatcher::RestoreConnections()
|
|||||||
isConstructing = false;
|
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)
|
QString NodeDispatcher::CreateInbound(INBOUND in)
|
||||||
{
|
{
|
||||||
auto tag = getTag(in);
|
auto tag = getTag(in);
|
||||||
|
@ -50,6 +50,9 @@ class NodeDispatcher
|
|||||||
return outbounds.count();
|
return outbounds.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void DeleteNode(const QUuid &nodeId);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void OnInboundCreated(std::shared_ptr<INBOUND>, QtNodes::Node &);
|
void OnInboundCreated(std::shared_ptr<INBOUND>, QtNodes::Node &);
|
||||||
void OnOutboundCreated(std::shared_ptr<OutboundObjectMeta>, QtNodes::Node &);
|
void OnOutboundCreated(std::shared_ptr<OutboundObjectMeta>, QtNodes::Node &);
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "base/Qv2rayBase.hpp"
|
#include "base/Qv2rayBase.hpp"
|
||||||
#include "core/CoreUtils.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_InboundEditor.hpp"
|
||||||
#include "ui/editors/w_JsonEditor.hpp"
|
#include "ui/editors/w_JsonEditor.hpp"
|
||||||
#include "ui/editors/w_OutboundEditor.hpp"
|
#include "ui/editors/w_OutboundEditor.hpp"
|
||||||
@ -10,6 +12,8 @@ InboundOutboundWidget::InboundOutboundWidget(WidgetMode mode, std::shared_ptr<No
|
|||||||
{
|
{
|
||||||
workingMode = mode;
|
workingMode = mode;
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
editBtn->setIcon(QICON_R("edit"));
|
||||||
|
editJsonBtn->setIcon(QICON_R("code"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InboundOutboundWidget::setValue(std::shared_ptr<INBOUND> data)
|
void InboundOutboundWidget::setValue(std::shared_ptr<INBOUND> data)
|
||||||
@ -23,7 +27,10 @@ void InboundOutboundWidget::setValue(std::shared_ptr<OutboundObjectMeta> data)
|
|||||||
{
|
{
|
||||||
assert(workingMode == MODE_OUTBOUND);
|
assert(workingMode == MODE_OUTBOUND);
|
||||||
outboundObject = data;
|
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)
|
void InboundOutboundWidget::changeEvent(QEvent *e)
|
||||||
@ -56,13 +63,37 @@ void InboundOutboundWidget::on_editBtn_clicked()
|
|||||||
}
|
}
|
||||||
case MODE_OUTBOUND:
|
case MODE_OUTBOUND:
|
||||||
{
|
{
|
||||||
OutboundEditor editor{ outboundObject->realOutbound, parentWidget() };
|
if (isExternalOutbound)
|
||||||
outboundObject->realOutbound = editor.OpenEditor();
|
{
|
||||||
// Set tag
|
if (QvMessageBoxAsk(parentWidget(), tr("Edit Outbound"), editExternalMsg) != QMessageBox::Yes)
|
||||||
const auto newTag = getTag(outboundObject->realOutbound);
|
{
|
||||||
tagTxt->setText(newTag);
|
return;
|
||||||
outboundObject->realOutbound["tag"] = newTag;
|
}
|
||||||
break;
|
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:
|
case MODE_OUTBOUND:
|
||||||
{
|
{
|
||||||
JsonEditor editor{ outboundObject->realOutbound, parentWidget() };
|
if (isExternalOutbound)
|
||||||
outboundObject->realOutbound = OUTBOUND{ editor.OpenEditor() };
|
{
|
||||||
const auto newTag = getTag(outboundObject->realOutbound);
|
if (QvMessageBoxAsk(parentWidget(), tr("Edit Outbound"), editExternalMsg) != QMessageBox::Yes)
|
||||||
// Set tag
|
{
|
||||||
tagTxt->setText(newTag);
|
return;
|
||||||
outboundObject->realOutbound["tag"] = newTag;
|
}
|
||||||
break;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,4 +33,11 @@ class InboundOutboundWidget
|
|||||||
WidgetMode workingMode;
|
WidgetMode workingMode;
|
||||||
std::shared_ptr<INBOUND> inboundObject;
|
std::shared_ptr<INBOUND> inboundObject;
|
||||||
std::shared_ptr<OutboundObjectMeta> outboundObject;
|
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?");
|
||||||
};
|
};
|
||||||
|
@ -6,14 +6,14 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>152</width>
|
<width>181</width>
|
||||||
<height>64</height>
|
<height>66</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Form</string>
|
<string>Form</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
@ -26,30 +26,41 @@
|
|||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="0" colspan="2">
|
<item>
|
||||||
<widget class="QLineEdit" name="tagTxt"/>
|
<widget class="QLineEdit" name="tagTxt"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item>
|
||||||
<widget class="QPushButton" name="editBtn">
|
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,1">
|
||||||
<property name="text">
|
<item>
|
||||||
<string/>
|
<widget class="QPushButton" name="editBtn">
|
||||||
</property>
|
<property name="text">
|
||||||
<property name="icon">
|
<string/>
|
||||||
<iconset resource="../../../../resources.new.qrc">
|
</property>
|
||||||
<normaloff>:/assets/icons/ui_dark/edit.svg</normaloff>:/assets/icons/ui_dark/edit.svg</iconset>
|
<property name="icon">
|
||||||
</property>
|
<iconset resource="../../../../resources.new.qrc">
|
||||||
</widget>
|
<normaloff>:/assets/icons/ui_light/edit.svg</normaloff>:/assets/icons/ui_light/edit.svg</iconset>
|
||||||
</item>
|
</property>
|
||||||
<item row="1" column="1">
|
</widget>
|
||||||
<widget class="QPushButton" name="editJsonBtn">
|
</item>
|
||||||
<property name="text">
|
<item>
|
||||||
<string/>
|
<widget class="QPushButton" name="editJsonBtn">
|
||||||
</property>
|
<property name="text">
|
||||||
<property name="icon">
|
<string/>
|
||||||
<iconset resource="../../../../resources.new.qrc">
|
</property>
|
||||||
<normaloff>:/assets/icons/ui_dark/code.svg</normaloff>:/assets/icons/ui_dark/code.svg</iconset>
|
<property name="icon">
|
||||||
</property>
|
<iconset resource="../../../../resources.new.qrc">
|
||||||
</widget>
|
<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>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
Loading…
Reference in New Issue
Block a user