Qv2ray/src/ui/editors/w_RoutesEditor_extra.cpp
2020-02-03 17:37:09 +08:00

247 lines
9.4 KiB
C++

// WARNING
// Since it's required for this file to know the content of the macros defined in another CPP file.
// We included an CPP file instead of the proper HPP file.
#include "w_RoutesEditor.cpp"
// Supplementary source file for Routes editor, basically providing routes-related operations.
void RouteEditor::AddInbound(INBOUND in)
{
QString tag = getTag(in);
if (inbounds.contains(tag)) {
tag = tag + "_" + GenerateRandomString(5);
}
in["tag"] = tag;
auto _nodeData = make_unique<QvInboundNodeModel>(make_shared<InboundNodeData>(tag));
auto &node = nodeScene->createNode(std::move(_nodeData));
auto pos = QPointF();
pos.setX(0 + GRAPH_GLOBAL_OFFSET_X);
pos.setY(inboundNodes.count() * 130 + GRAPH_GLOBAL_OFFSET_Y);
nodeScene->setNodePosition(node, pos);
inboundNodes[tag] = &node;
inbounds[getTag(in)] = in;
}
void RouteEditor::AddOutbound(OUTBOUND out)
{
QString tag = getTag(out);
if (outbounds.contains(tag)) {
tag = tag + "_" + GenerateRandomString(5);
}
out["tag"] = tag;
auto _nodeData = make_unique<QvOutboundNodeModel>(make_shared<OutboundNodeData>(tag));
auto pos = nodeGraphWidget->pos();
pos.setX(pos.x() + 850 + GRAPH_GLOBAL_OFFSET_X);
pos.setY(pos.y() + outboundNodes.count() * 120 + GRAPH_GLOBAL_OFFSET_Y);
auto &node = nodeScene->createNode(std::move(_nodeData));
nodeScene->setNodePosition(node, pos);
outboundNodes[tag] = &node;
outbounds[tag] = out;
defaultOutboundCombo->addItem(tag);
}
QString RouteEditor::AddNewRule()
{
// Add Route
RuleObject rule;
//
rule.QV2RAY_RULE_ENABLED = true;
rule.QV2RAY_RULE_USE_BALANCER = false;
// Default balancer tag, it's a random string.
auto bTag = GenerateRandomString();
rule.QV2RAY_RULE_TAG = rules.isEmpty() ? tr("Default rule") : (tr("rule") + "-" + GenerateRandomString(6));
rule.balancerTag = bTag;
balancers[bTag] = QStringList();
AddRule(rule);
return rule.QV2RAY_RULE_TAG;
}
void RouteEditor::AddRule(RuleObject rule)
{
// Prevent duplicate
if (ruleNodes.contains(rule.QV2RAY_RULE_TAG)) {
rule.QV2RAY_RULE_TAG += "-" + GenerateRandomString(5);
}
rules[rule.QV2RAY_RULE_TAG] = rule;
auto pos = nodeGraphWidget->pos();
pos.setX(pos.x() + 350 + GRAPH_GLOBAL_OFFSET_X);
pos.setY(pos.y() + ruleNodes.count() * 120 + GRAPH_GLOBAL_OFFSET_Y);
auto _nodeData = make_unique<QvRuleNodeDataModel>(make_shared<RuleNodeData>(rule.QV2RAY_RULE_TAG));
auto &node = nodeScene->createNode(std::move(_nodeData));
nodeScene->setNodePosition(node, pos);
for (auto inTag : rule.inboundTag) {
if (!inboundNodes.contains(inTag)) {
LOG(UI, "No inbound tag found for rule: " + rule.QV2RAY_RULE_TAG + ", inbound tag: " + inTag)
QvMessageBoxWarn(this, tr("No Inbound"), tr("No inbound item found: ") + inTag);
rule.inboundTag.removeAll(inTag);
} else {
auto inboundNode = inboundNodes[inTag];
nodeScene->createConnection(node, 0, *inboundNode, 0);
}
}
// If not using balancers (use outbound tag)
if (!rule.QV2RAY_RULE_USE_BALANCER) {
if (outboundNodes.contains(rule.outboundTag)) {
DEBUG(GRAPH, "Found outbound tag: " + rule.outboundTag + ", for rule: " + rule.QV2RAY_RULE_TAG)
nodeScene->createConnection(*outboundNodes[rule.outboundTag], 0, node, 0);
} else {
LOG(GRAPH, "Outbound tag not found: " + rule.outboundTag + ", for: " + rule.QV2RAY_RULE_TAG)
//QvMessageBoxWarn(this, tr("No outbound tag"), tr("Please connect the rule with an outbound."));
}
}
this->ruleNodes[rule.QV2RAY_RULE_TAG] = &node;
ruleListWidget->addItem(rule.QV2RAY_RULE_TAG);
}
// Do not use reference here, we need deep
void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, QString newTag)
{
switch (mode) {
case RENAME_RULE:
if (rules.contains(originalTag) && ruleNodes.contains(originalTag)) {
if (rules.contains(newTag) && rules.contains(newTag)) {
QvMessageBoxWarn(this, tr("Rename tags"), tr("The new tag has been used, we appended a postfix."));
newTag += "_" + GenerateRandomString(5);
}
auto node = static_cast<QvRuleNodeDataModel *>(ruleNodes[originalTag]->nodeDataModel());
if (node == nullptr) {
LOG(GRAPH, "EMPTY NODE WARN")
}
node->setData(newTag);
//
rules[newTag] = rules.take(originalTag);
rules[newTag].QV2RAY_RULE_TAG = newTag;
ruleNodes[newTag] = ruleNodes.take(originalTag);
//
// No other operation needed, but need to rename the one in the ruleOrder list widget.
auto items = ruleListWidget->findItems(originalTag, Qt::MatchExactly);
if (items.isEmpty()) {
LOG(UI, "Cannot find a node: " + originalTag)
} else {
items.first()->setText(newTag);
}
if (currentRuleTag == originalTag) {
currentRuleTag = newTag;
}
} else {
LOG(UI, "There's nothing match " + originalTag + " in the containers.")
}
break;
case RENAME_OUTBOUND:
if (outbounds.contains(originalTag) && outboundNodes.contains(originalTag)) {
if (outbounds.contains(newTag) && outboundNodes.contains(newTag)) {
QvMessageBoxWarn(this, tr("Rename tags"), tr("The new tag has been used, we appended a postfix."));
newTag += "_" + GenerateRandomString(5);
}
outbounds[newTag] = outbounds.take(originalTag);
outboundNodes[newTag] = outboundNodes.take(originalTag);
auto node = static_cast<QvOutboundNodeModel *>(outboundNodes[newTag]->nodeDataModel());
if (node == nullptr) {
LOG(GRAPH, "EMPTY NODE WARN")
}
node->setData(newTag);
// Change outbound tag in rules accordingly.
for (auto k : rules.keys()) {
auto v = rules[k];
if (v.outboundTag == originalTag) {
v.outboundTag = newTag;
// Put this inside the if block since no need an extra operation if the condition is false.
rules[k] = v;
}
}
// Resolve default outbound.
ResolveDefaultOutboundTag(originalTag, newTag);
} else {
LOG(UI, "Failed to rename an outbound --> Item not found.")
}
break;
case RENAME_INBOUND:
if (inbounds.contains(originalTag) && inboundNodes.contains(originalTag)) {
if (inbounds.contains(newTag) && inboundNodes.contains(newTag)) {
QvMessageBoxWarn(this, tr("Rename tags"), tr("The new tag has been used, we appended a postfix."));
newTag += "_" + GenerateRandomString(5);
}
inbounds[newTag] = inbounds.take(originalTag);
inboundNodes[newTag] = inboundNodes.take(originalTag);
auto node = static_cast<QvInboundNodeModel *>(inboundNodes[newTag]->nodeDataModel());
if (node == nullptr) {
LOG(GRAPH, "EMPTY NODE WARN")
}
node->setData(newTag);
// Change inbound tag in rules accordingly.
// k -> rule tag
// v -> rule object
for (auto k : rules.keys()) {
auto v = rules[k];
if (v.inboundTag.contains(originalTag)) {
v.inboundTag.append(newTag);
v.inboundTag.removeAll(originalTag);
// Put this inside the if block since no need an extra operation if the condition is false.
rules[k] = v;
}
}
} else {
LOG(UI, "Failed to rename an outbound --> Item not found.")
}
break;
}
}
void RouteEditor::ResolveDefaultOutboundTag(QString original, QString newTag)
{
LOG(UI, "Resolving default outbound settings: default=" + defaultOutbound + " original=" + original + " new=" + newTag)
auto isDefaultChanged = original == defaultOutbound;
defaultOutboundCombo->clear();
defaultOutboundCombo->addItems(outbounds.keys());
if (!isDefaultChanged) {
LOG(UI, "Default outbound is not changed: retaining: " + defaultOutbound)
// Just simply restore the default one.
defaultOutboundCombo->setCurrentText(defaultOutbound);
} else if (newTag.isEmpty()) {
LOG(UI, "Default outbound is removed, using first key from the outbounds as the default one.")
// Removed the default one, so set the first one as the default.
if (outbounds.isEmpty()) {
defaultOutbound.clear();
} else {
defaultOutbound = getTag(outbounds.first());
defaultOutboundCombo->addItem(outbounds.firstKey());
}
} else {
LOG(UI, "Default outbound is renamed, ")
defaultOutboundCombo->setCurrentText(newTag);
defaultOutbound = newTag;
}
}