fix: several fix of complex editor

This commit is contained in:
Qv2ray Bot 2020-01-21 11:39:41 +08:00
parent 1a3a3c3266
commit c6075b1dc6
4 changed files with 150 additions and 61 deletions

View File

@ -1 +1 @@
2992
3005

View File

@ -20,7 +20,7 @@ static bool isLoading = false;
#define CHECKEMPTYRULES if (this->rules.isEmpty()) { \
LOG(MODULE_UI, "No rules currently, we add one.") \
on_addRouteBtn_clicked(); \
AddNewRule(); \
}
#define GRAPH_GLOBAL_OFFSET_X -80
@ -82,17 +82,17 @@ RouteEditor::RouteEditor(QJsonObject connection, QWidget *parent) : QDialog(pare
// Show connections in the node graph
for (auto in : root["inbounds"].toArray()) {
INBOUND _in = INBOUND(in.toObject());
AddNewInbound(_in);
AddInbound(_in);
}
for (auto out : root["outbounds"].toArray()) {
OUTBOUND _out = OUTBOUND(out.toObject());
AddNewOutbound(_out);
AddOutbound(_out);
}
for (auto item : root["routing"].toObject()["rules"].toArray()) {
auto _rule = StructFromJsonString<RuleObject>(JsonToString(item.toObject()));
AddNewRule(_rule);
AddRule(_rule);
}
// Set default outboung combo text AFTER adding all outbounds.
@ -300,11 +300,18 @@ CONFIGROOT RouteEditor::OpenEditor()
// Convert our internal data format to QJsonArray
for (auto x : inbounds) {
if (x.isEmpty())
continue;
_inbounds.append(x.raw());
}
for (auto x : outbounds) {
if (x.isEmpty())
continue;
if (getTag(x) == defaultOutbound) {
LOG(MODULE_CONNECTION, "Pushing default outbound to the front.")
// Put the default outbound to the first.
_outbounds.push_front(x.raw());
} else {
@ -328,7 +335,13 @@ void RouteEditor::ShowCurrentRuleDetail()
{
LOADINGCHECK
if (currentRuleTag.isEmpty()) {
LOG(MODULE_UI, "WARNING, trying to access a non-exist rule entry. return.")
return;
}
if (!rules.contains(currentRuleTag)) {
QvMessageBoxWarn(this, tr("Show rule details"), tr("A rule cannot be found: ") + currentRuleTag);
LOG(MODULE_UI, "WARNING, trying to access a non-exist rule entry. return.")
return;
}
@ -389,15 +402,17 @@ void RouteEditor::ShowCurrentRuleDetail()
ipList->setPlainText(ips);
LOAD_FLAG_END
}
void RouteEditor::on_insertDirectBtn_clicked()
{
auto freedom = GenerateFreedomOUT("as-is", "", 0);
auto tag = "Freedom_" + QSTRN(QTime::currentTime().msecsSinceStartOfDay());
auto out = GenerateOutboundEntry("freedom", freedom, QJsonObject(), QJsonObject(), "0.0.0.0", tag);
// ADD NODE
AddNewOutbound(out);
AddOutbound(out);
statusLabel->setText(tr("Added DIRECT outbound"));
}
void RouteEditor::on_routeProtocolHTTPCB_stateChanged(int arg1)
{
LOADINGCHECK
@ -488,18 +503,8 @@ void RouteEditor::on_routeUserTxt_textEdited(const QString &arg1)
}
void RouteEditor::on_addRouteBtn_clicked()
{
LOADINGCHECK
// 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(5));
rule.balancerTag = bTag;
balancers[bTag] = QStringList();
AddNewRule(rule);
auto ruleName = AddNewRule();
Q_UNUSED(ruleName)
}
void RouteEditor::on_netBothRB_clicked()
{
@ -570,8 +575,8 @@ void RouteEditor::on_addDefaultBtn_clicked()
auto _in_HTTP = GenerateInboundEntry(_Inconfig.listenip, _Inconfig.http_port, "http", _in_httpConf, "HTTP_gConf");
auto _in_SOCKS = GenerateInboundEntry(_Inconfig.listenip, _Inconfig.socks_port, "socks", _in_socksConf, "SOCKS_gConf");
//
AddNewInbound(_in_HTTP);
AddNewInbound(_in_SOCKS);
AddInbound(_in_HTTP);
AddInbound(_in_SOCKS);
CHECKEMPTYRULES
}
void RouteEditor::on_insertBlackBtn_clicked()
@ -580,7 +585,7 @@ void RouteEditor::on_insertBlackBtn_clicked()
auto blackHole = GenerateBlackHoleOUT(false);
auto tag = "blackhole_" + QSTRN(QTime::currentTime().msecsSinceStartOfDay());
auto _blackHoleOutbound = GenerateOutboundEntry("blackhole", blackHole, QJsonObject(), QJsonObject(), "0.0.0.0", tag);
AddNewOutbound(_blackHoleOutbound);
AddOutbound(_blackHoleOutbound);
}
void RouteEditor::on_addInboundBtn_clicked()
{
@ -589,7 +594,7 @@ void RouteEditor::on_addInboundBtn_clicked()
auto _result = w.OpenEditor();
if (w.result() == QDialog::Accepted) {
AddNewInbound(_result);
AddInbound(_result);
}
CHECKEMPTYRULES
@ -612,7 +617,7 @@ void RouteEditor::on_addOutboundBtn_clicked()
auto confList = conf["outbounds"].toArray();
for (int i = 0; i < confList.count(); i++) {
AddNewOutbound(OUTBOUND(confList[i].toObject()));
AddOutbound(OUTBOUND(confList[i].toObject()));
}
}
@ -642,22 +647,41 @@ void RouteEditor::on_delBtn_clicked()
// Then remove the node container.
if (isInbound) {
currentInboundOutboundTag = GetFirstNodeData(*firstNode, QvInboundNodeModel, InboundNodeData)->GetInbound();
inbounds.remove(currentInboundOutboundTag);
nodeScene->removeNode(*inboundNodes[currentInboundOutboundTag]);
inboundNodes.remove(currentInboundOutboundTag);
// Remove corresponded inboundtags 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, QvOutboundNodeModel, OutboundNodeData)->GetOutbound();
outbounds.remove(currentInboundOutboundTag);
nodeScene->removeNode(*outboundNodes[currentInboundOutboundTag]);
outboundNodes.remove(currentInboundOutboundTag);
//
defaultOutboundCombo->removeItem(defaultOutbound.indexOf(currentInboundOutboundTag));
defaultOutboundCombo->clear();
defaultOutboundCombo->addItems(outbounds.keys());
// Remove corresponded inboundtags from the rules.
for (auto k : rules.keys()) {
auto v = rules[k];
if (v.outboundTag == currentInboundOutboundTag)
v.outboundTag.clear();
rules[k] = v;
}
if (currentInboundOutboundTag == defaultOutbound) {
// Set default outbound to the new one since the current has been removed.
defaultOutbound = outbounds.firstKey();
defaultOutboundCombo->setCurrentText(defaultOutbound);
}
defaultOutboundCombo->setCurrentText(defaultOutbound);
nodeScene->removeNode(*outboundNodes[currentInboundOutboundTag]);
outboundNodes.remove(currentInboundOutboundTag);
} else if (isRule) {
ruleEnableCB->setEnabled(false);
currentRuleTag = GetFirstNodeData(*firstNode, QvRuleNodeDataModel, RuleNodeData)->GetRuleTag();
@ -683,12 +707,18 @@ void RouteEditor::on_editBtn_clicked()
QvMessageBoxWarn(this, tr("Edit Inbound/Outbound"), tr("Please select a node from the graph to continue."));
}
auto firstNode = nodeScene->selectedNodes()[0];
auto firstNode = nodeScene->selectedNodes().at(0);
auto isInbound = inboundNodes.values().contains(firstNode);
auto isOutbound = outboundNodes.values().contains(firstNode);
if (isInbound) {
currentInboundOutboundTag = GetFirstNodeData(*firstNode, QvInboundNodeModel, InboundNodeData)->GetInbound();
if (!inbounds.contains(currentInboundOutboundTag)) {
QvMessageBoxWarn(this, tr("Edit Inbound"), tr("No inbound tag found: ") + currentInboundOutboundTag);
return;
}
auto _in = inbounds[currentInboundOutboundTag];
INBOUND _result;
auto protocol = _in["protocol"].toString();
@ -719,13 +749,22 @@ void RouteEditor::on_editBtn_clicked()
RenameItemTag(RENAME_INBOUND, getTag(_in), getTag(_result));
}
DEBUG(MODULE_UI, "Removed old tag: " + getTag(_in))
inbounds.remove(getTag(_in));
DEBUG(MODULE_UI, "Adding new tag: " + getTag(_result))
inbounds[getTag(_result)] = _result;
}
} else if (isOutbound) {
currentInboundOutboundTag = GetFirstNodeData(*firstNode, QvOutboundNodeModel, OutboundNodeData)->GetOutbound();
if (!outbounds.contains(currentInboundOutboundTag)) {
QvMessageBoxWarn(this, tr("Edit Inbound"), tr("No inbound tag found: ") + currentInboundOutboundTag);
return;
}
OUTBOUND _result;
auto _out = outbounds[currentInboundOutboundTag];
auto protocol = _out["protocol"].toString();
auto protocol = _out["protocol"].toString().toLower();
int _code;
if (protocol != "vmess" && protocol != "shadowsocks" && protocol != "socks") {
@ -747,9 +786,13 @@ void RouteEditor::on_editBtn_clicked()
bool isTagChanged = getTag(_out) != getTag(_result);
if (isTagChanged) {
DEBUG(MODULE_UI, "Outbound tag is changed: " + QString(isTagChanged))
RenameItemTag(RENAME_OUTBOUND, getTag(_out), getTag(_result));
DEBUG(MODULE_UI, "Removed old tag: " + getTag(_out))
outbounds.remove(getTag(_out));
}
DEBUG(MODULE_UI, "Adding new tag: " + getTag(_result))
outbounds[getTag(_result)] = _result;
statusLabel->setText(tr("OK"));
}

View File

@ -112,7 +112,7 @@ class RouteEditor : public QDialog, private Ui::RouteEditor
void onConnectionDeleted(QtNodes::Connection const &c);
private:
void RenameItemTag(ROUTE_EDIT_MODE mode, const QString &originalTag, const QString &newTag);
void RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, const QString newTag);
void ShowCurrentRuleDetail();
//
QString currentRuleTag;
@ -136,7 +136,8 @@ class RouteEditor : public QDialog, private Ui::RouteEditor
//
FlowScene *nodeScene;
// ---------------------------- Extra Source File Headers ----------------
void AddNewInbound(INBOUND in);
void AddNewOutbound(OUTBOUND out);
void AddNewRule(RuleObject rule);
void AddInbound(INBOUND in);
void AddOutbound(OUTBOUND out);
void AddRule(RuleObject rule);
QString AddNewRule();
};

View File

@ -6,7 +6,7 @@
// Supplementary source file for Routes editor, basically providing routes-related operations.
void RouteEditor::AddNewInbound(INBOUND in)
void RouteEditor::AddInbound(INBOUND in)
{
QString tag = getTag(in);
@ -14,6 +14,7 @@ void RouteEditor::AddNewInbound(INBOUND in)
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();
@ -24,7 +25,7 @@ void RouteEditor::AddNewInbound(INBOUND in)
inbounds[getTag(in)] = in;
}
void RouteEditor::AddNewOutbound(OUTBOUND out)
void RouteEditor::AddOutbound(OUTBOUND out)
{
QString tag = getTag(out);
@ -32,6 +33,7 @@ void RouteEditor::AddNewOutbound(OUTBOUND out)
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);
@ -43,7 +45,23 @@ void RouteEditor::AddNewOutbound(OUTBOUND out)
defaultOutboundCombo->addItem(tag);
}
void RouteEditor::AddNewRule(RuleObject rule)
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)) {
@ -59,54 +77,68 @@ void RouteEditor::AddNewRule(RuleObject rule)
nodeScene->setNodePosition(node, pos);
for (auto inTag : rule.inboundTag) {
auto inboundNode = inboundNodes[inTag];
nodeScene->createConnection(node, 0, *inboundNode, 0);
if (!inboundNodes.contains(inTag)) {
LOG(MODULE_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 && outboundNodes.contains(rule.outboundTag)) {
nodeScene->createConnection(*outboundNodes[rule.outboundTag], 0, node, 0);
if (!rule.QV2RAY_RULE_USE_BALANCER) {
if (outboundNodes.contains(rule.outboundTag)) {
DEBUG(MODULE_GRAPH, "Found outbound tag: " + rule.outboundTag + ", for rule: " + rule.QV2RAY_RULE_TAG)
nodeScene->createConnection(*outboundNodes[rule.outboundTag], 0, node, 0);
} else {
LOG(MODULE_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);
}
void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString &originalTag, const QString &newTag)
// 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, please suggest another."));
return;
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(MODULE_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()) {
auto item = items.first();
item->setText(newTag);
} else {
if (items.isEmpty()) {
LOG(MODULE_UI, "Cannot find a node: " + originalTag)
} else {
items.first()->setText(newTag);
}
if (currentRuleTag == originalTag) {
currentRuleTag = newTag;
}
// Do not move this line, since originalTag is a reference (implicitly a pointer) to this value.
// We must change this at last.
rules[newTag].QV2RAY_RULE_TAG = newTag;
} else {
LOG(MODULE_UI, "There's thing match " + originalTag + " in the containers.")
LOG(MODULE_UI, "There's nothing match " + originalTag + " in the containers.")
}
break;
@ -114,13 +146,18 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString &originalTag
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, please suggest another."));
return;
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(MODULE_GRAPH, "EMPTY NODE WARN")
}
node->setData(newTag);
// Change outbound tag in rules accordingly.
@ -142,21 +179,29 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString &originalTag
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, please suggest another."));
return;
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);
static_cast<QvInboundNodeModel *>(inboundNodes[newTag]->nodeDataModel())->setData(newTag);
auto node = static_cast<QvInboundNodeModel *>(inboundNodes[newTag]->nodeDataModel());
if (node == nullptr) {
LOG(MODULE_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.removeAll(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;
}