refactor: huge refactor of basic SafeType system

This commit is contained in:
QwQ 2020-07-15 17:02:00 +08:00
parent 3059fc9d88
commit cd017adb2a
No known key found for this signature in database
GPG Key ID: E7FAEFAFCD031D4B
26 changed files with 929 additions and 1331 deletions

View File

@ -44,6 +44,16 @@ set(QV2RAY_UI_SOURCES
${CMAKE_SOURCE_DIR}/src/ui/models/OutboundNodeModel.cpp
${CMAKE_SOURCE_DIR}/src/ui/models/RuleNodeModel.hpp
${CMAKE_SOURCE_DIR}/src/ui/models/RuleNodeModel.cpp
# NodeEditor Widgets
${CMAKE_SOURCE_DIR}/src/ui/widgets/node/RuleWidget.cpp
${CMAKE_SOURCE_DIR}/src/ui/widgets/node/RuleWidget.hpp
${CMAKE_SOURCE_DIR}/src/ui/widgets/node/RuleWidget.ui
${CMAKE_SOURCE_DIR}/src/ui/widgets/node/InboundOutboundWidget.cpp
${CMAKE_SOURCE_DIR}/src/ui/widgets/node/InboundOutboundWidget.hpp
${CMAKE_SOURCE_DIR}/src/ui/widgets/node/InboundOutboundWidget.ui
${CMAKE_SOURCE_DIR}/src/ui/widgets/node/OutboundBalancerWidget.cpp
${CMAKE_SOURCE_DIR}/src/ui/widgets/node/OutboundBalancerWidget.hpp
${CMAKE_SOURCE_DIR}/src/ui/widgets/node/OutboundBalancerWidget.ui
# Style Manager
${CMAKE_SOURCE_DIR}/src/ui/styles/StyleManager.cpp
${CMAKE_SOURCE_DIR}/src/ui/styles/StyleManager.hpp

View File

@ -1 +1 @@
5791
5792

View File

@ -6,23 +6,23 @@
#include <QJsonObject>
#include <QMap>
#define SAFE_TYPEDEF_EXTRA(Base, name, extra) \
class name : public Base \
{ \
public: \
template<class... Args> \
explicit name(Args... args) : Base(args...) \
{ \
} \
const Base &raw() const \
{ \
return *this; \
} \
extra \
template<typename placeholder, typename BASETYPE_T>
class SAFETYPE_IMPL : public BASETYPE_T
{
public:
template<class... Args>
explicit SAFETYPE_IMPL(Args... args) : BASETYPE_T(args...){};
const BASETYPE_T &raw() const
{
return *this;
}
};
#define SAFE_TYPEDEF(BASE, CLASS) \
class __##CLASS##__; \
typedef SAFETYPE_IMPL<__##CLASS##__, BASE> CLASS;
#define nothing
#define SAFE_TYPEDEF(Base, name) SAFE_TYPEDEF_EXTRA(Base, name, nothing)
namespace Qv2ray::base::safetype
{
// To prevent anonying QJsonObject misuse
@ -31,14 +31,11 @@ namespace Qv2ray::base::safetype
SAFE_TYPEDEF(QJsonObject, INBOUND);
SAFE_TYPEDEF(QJsonObject, OUTBOUND);
SAFE_TYPEDEF(QJsonObject, CONFIGROOT);
SAFE_TYPEDEF(QJsonObject, PROXYSETTING);
//
SAFE_TYPEDEF(QJsonArray, ROUTERULELIST);
SAFE_TYPEDEF(QJsonArray, INOUTLIST);
SAFE_TYPEDEF(QJsonObject, ROUTING);
SAFE_TYPEDEF(QJsonObject, ROUTERULE);
SAFE_TYPEDEF(INOUTLIST, OUTBOUNDS);
SAFE_TYPEDEF(INOUTLIST, INBOUNDS);
//
SAFE_TYPEDEF(QJsonArray, OUTBOUNDS);
SAFE_TYPEDEF(QJsonArray, INBOUNDS);
template<typename T>
struct QvPair

View File

@ -165,23 +165,30 @@ namespace Qv2ray::core
return TruncateString(ConnectionManager->GetGroupMetaObject(id).displayName, limit);
}
const QMap<QString, InboundInfoObject> GetConfigInboundInfo(const CONFIGROOT &root)
bool GetInboundInfo(const INBOUND &in, QString *listen, int *port, QString *protocol)
{
*protocol = in["protocol"].toString();
*listen = in["listen"].toString();
*port = in["port"].toVariant().toInt();
return true;
}
const QMap<QString, InboundInfoObject> GetInboundInfo(const CONFIGROOT &root)
{
QMap<QString, InboundInfoObject> inboundPorts;
for (const auto &inboundVal : root["inbounds"].toArray())
{
const auto &inbound = inboundVal.toObject();
inboundPorts[inbound["tag"].toString()] = {
inbound["protocol"].toString(), //
inbound["listen"].toString(), //
inbound["port"].toVariant().toInt() //
};
INBOUND in{ inboundVal.toObject() };
QString host, protocol;
int port;
if (GetInboundInfo(in, &host, &port, &protocol))
inboundPorts[getTag(in)] = { protocol, host, port };
}
return inboundPorts;
}
const QMap<QString, InboundInfoObject> GetConfigInboundInfo(const ConnectionId &id)
const QMap<QString, InboundInfoObject> GetInboundInfo(const ConnectionId &id)
{
return GetConfigInboundInfo(ConnectionManager->GetConnectionRoot(id));
return GetInboundInfo(ConnectionManager->GetConnectionRoot(id));
}
} // namespace Qv2ray::core

View File

@ -49,8 +49,9 @@ namespace Qv2ray::core
//
// const GroupId GetConnectionGroupId(const ConnectionId &id);
//
const QMap<QString, InboundInfoObject> GetConfigInboundInfo(const CONFIGROOT &root);
const QMap<QString, InboundInfoObject> GetConfigInboundInfo(const ConnectionId &id);
bool GetInboundInfo(const INBOUND &in, QString *listen, int *port, QString *protocol);
const QMap<QString, InboundInfoObject> GetInboundInfo(const CONFIGROOT &root);
const QMap<QString, InboundInfoObject> GetInboundInfo(const ConnectionId &id);
} // namespace Qv2ray::core
using namespace Qv2ray::core;

View File

@ -79,7 +79,7 @@ namespace Qv2ray::core::handler
std::optional<QString> KernelInstanceHandler::StartConnection(const ConnectionGroupPair &id, CONFIGROOT fullConfig)
{
StopConnection();
inboundInfo = GetConfigInboundInfo(fullConfig);
inboundInfo = GetInboundInfo(fullConfig);
//
const auto inboundPorts = GetInboundPorts();
const auto inboundHosts = GetInboundHosts();

View File

@ -25,7 +25,7 @@ namespace Qv2ray::core::handler
{
return activeKernels.size();
}
const QMap<QString, InboundInfoObject> GetInboundInfo() const
const QMap<QString, InboundInfoObject> GetCurrentConnectionInboundInfo() const
{
return inboundInfo;
}

View File

@ -50,7 +50,7 @@ namespace Qv2ray::core::handler
root.insert("domainStrategy", routeConfig.domainStrategy);
//
// For Rules list
ROUTERULELIST rulesList;
QJsonArray rulesList;
// Private IPs should always NOT TO PROXY!
rulesList.append(GenerateSingleRouteRule("geoip:private", false, OUTBOUND_TAG_DIRECT));
@ -256,7 +256,7 @@ namespace Qv2ray::core::handler
// And what's more, process (by removing unused items) from a
// rule object.
ROUTING routing(root["routing"].toObject());
ROUTERULELIST rules;
QJsonArray rules;
LOG(MODULE_CONNECTION, "Processing an existing routing table.")
for (const auto &_rule : routing["rules"].toArray())
@ -315,7 +315,7 @@ namespace Qv2ray::core::handler
if (firstOutbound[QV2RAY_USE_FPROXY_KEY].toBool(false))
{
LOG(MODULE_CONNECTION, "Applying forward proxy to current connection.")
PROXYSETTING proxy;
QJsonObject proxy;
proxy["tag"] = OUTBOUND_TAG_FORWARD_PROXY;
firstOutbound["proxySettings"] = proxy;

View File

@ -22,7 +22,7 @@
using QtNodes::FlowView;
using namespace Qv2ray::ui::nodemodels;
#define CurrentRule this->rules[this->currentRuleTag]
//#define CurrentRule this->rules[this->currentRuleTag]
#define LOADINGCHECK \
if (isLoading) \
return;
@ -85,14 +85,7 @@ RouteEditor::RouteEditor(QJsonObject connection, QWidget *parent) : QvDialog(par
//
SetupNodeWidget();
//
// Setup icons according to the theme settings.
addInboundBtn->setIcon(QICON_R("add.png"));
addOutboundBtn->setIcon(QICON_R("add.png"));
editBtn->setIcon(QICON_R("edit.png"));
addRouteBtn->setIcon(QICON_R("add.png"));
delBtn->setIcon(QICON_R("delete.png"));
balancerAddBtn->setIcon(QICON_R("add.png"));
balancerDelBtn->setIcon(QICON_R("delete.png"));
updateColorScheme();
//
domainStrategy = root["routing"].toObject()["domainStrategy"].toString();
domainStrategyCombo->setCurrentText(domainStrategy);
@ -117,15 +110,15 @@ RouteEditor::RouteEditor(QJsonObject connection, QWidget *parent) : QvDialog(par
defaultOutbound = getTag(OUTBOUND(root["outbounds"].toArray().first().toObject()));
defaultOutboundCombo->setCurrentText(defaultOutbound);
// Find and add balancers.
for (auto _balancer : root["routing"].toObject()["balancers"].toArray())
{
auto _balancerObject = _balancer.toObject();
if (!_balancerObject["tag"].toString().isEmpty())
{
balancers.insert(_balancerObject["tag"].toString(), _balancerObject["selector"].toVariant().toStringList());
}
}
// // Find and add balancers.
// for (auto _balancer : root["routing"].toObject()["balancers"].toArray())
// {
// auto _balancerObject = _balancer.toObject();
// if (!_balancerObject["tag"].toString().isEmpty())
// {
// balancers.insert(_balancerObject["tag"].toString(), _balancerObject["selector"].toVariant().toStringList());
// }
// }
for (const auto &group : ConnectionManager->AllGroups())
{
@ -157,43 +150,37 @@ void RouteEditor::onNodeClicked(Node &n)
auto isIn = inboundNodes.values().contains(n.id());
auto isRule = ruleNodes.values().contains(n.id());
if (isRule)
/* if (isRule)
{
// It's a rule object
currentRuleTag = GetFirstNodeData(n.id(), RuleNode)->GetRuleTag();
DEBUG(MODULE_GRAPH, "Selecting rule: " + currentRuleTag)
ShowCurrentRuleDetail();
// ShowCurrentRuleDetail();
toolBox->setCurrentIndex(1);
}
else if (isOut || isIn)
else*/
if (isOut || isIn)
{
// It's an inbound or an outbound.
QString alias;
QString tag;
QString host;
QString port;
int port;
QString protocol;
if (isOut)
{
alias = GetFirstNodeData(n.id(), OutboundNode)->GetOutbound();
QJsonObject _root = outbounds[alias].raw();
int _port;
GetOutboundInfo(OUTBOUND(_root), &host, &_port, &protocol);
port = QString::number(_port);
const auto root = GetFirstNodeData(n.id(), OutboundNode)->GetOutbound();
GetOutboundInfo(*root, &host, &port, &protocol);
}
else
{
alias = GetFirstNodeData(n.id(), InboundNode)->GetInbound();
QJsonObject _root = inbounds[alias].raw();
host = _root["listen"].toString();
protocol = _root["protocol"].toString();
// Port could be a string, or an integer.
port = _root["port"].toVariant().toString();
const auto root = GetFirstNodeData(n.id(), InboundNode)->GetInbound();
GetInboundInfo(*root, &host, &port, &protocol);
}
tagLabel->setText(alias);
tagLabel->setText(tag);
protocolLabel->setText(protocol);
portLabel->setText(port);
portLabel->setText(QSTRN(port));
hostLabel->setText(host);
}
else
@ -213,58 +200,58 @@ void RouteEditor::onConnectionCreated(QtNodes::Connection const &c)
auto const &sourceNode = c.getNode(PortType::Out);
auto const &targetNode = c.getNode(PortType::In);
if (inboundNodes.values().contains(sourceNode->id()) && ruleNodes.values().contains(targetNode->id()))
{
// It's a inbound-rule connection
onNodeClicked(*sourceNode);
onNodeClicked(*targetNode);
LOG(MODULE_GRAPH, "Inbound-rule new connection.")
// Get all connected inbounds to this rule node.
// QStringList has an helper to let us remove duplicates, see below.
QSet<QString> _inbounds;
// if (inboundNodes.values().contains(sourceNode->id()) && ruleNodes.values().contains(targetNode->id()))
// {
// // It's a inbound-rule connection
// onNodeClicked(*sourceNode);
// onNodeClicked(*targetNode);
// LOG(MODULE_GRAPH, "Inbound-rule new connection.")
// // Get all connected inbounds to this rule node.
// // QStringList has an helper to let us remove duplicates, see below.
// QSet<QString> _inbounds;
// //
// // Workaround for removing a connection within the loop.
// QList<std::shared_ptr<QtNodes::Connection>> connectionsTobeRemoved;
// for (auto &&[_, conn] : nodeScene->connections())
// {
// const auto &inNode = conn->getNode(PortType::In);
// const auto &outNode = conn->getNode(PortType::Out);
// // If a connection is not current Id, but with same IN/OUT nodes.
// // It is a "duplicated" connection.
// if (inNode->id() == targetNode->id() && outNode->id() == sourceNode->id() && conn->id() != c.id())
// {
// connectionsTobeRemoved << (conn);
// }
// // Append all inbounds
// if (inNode->id() == targetNode->id())
// {
// _inbounds.insert(GetFirstNodeData(outNode->id(), InboundNode)->GetInbound());
// }
// }
// for (const auto &connRemoved : connectionsTobeRemoved)
// {
// nodeScene->deleteConnection(*connRemoved);
// }
//
// Workaround for removing a connection within the loop.
QList<std::shared_ptr<QtNodes::Connection>> connectionsTobeRemoved;
for (auto &&[_, conn] : nodeScene->connections())
{
const auto &inNode = conn->getNode(PortType::In);
const auto &outNode = conn->getNode(PortType::Out);
// If a connection is not current Id, but with same IN/OUT nodes.
// It is a "duplicated" connection.
if (inNode->id() == targetNode->id() && outNode->id() == sourceNode->id() && conn->id() != c.id())
{
connectionsTobeRemoved << (conn);
}
// Append all inbounds
if (inNode->id() == targetNode->id())
{
_inbounds.insert(GetFirstNodeData(outNode->id(), InboundNode)->GetInbound());
}
}
for (const auto &connRemoved : connectionsTobeRemoved)
{
nodeScene->deleteConnection(*connRemoved);
}
CurrentRule.inboundTag = _inbounds.values();
}
else if (ruleNodes.values().contains(sourceNode->id()) && outboundNodes.values().contains(targetNode->id()))
{
// It's a rule-outbound connection
onNodeClicked(*sourceNode);
onNodeClicked(*targetNode);
CurrentRule.outboundTag = GetFirstNodeData(targetNode->id(), OutboundNode)->GetOutbound();
// Connecting to an outbound will disable the balancer feature.
CurrentRule.QV2RAY_RULE_USE_BALANCER = false;
// Update balancer settings.
ShowCurrentRuleDetail();
LOG(MODULE_GRAPH, "Updated outbound: " + CurrentRule.outboundTag)
}
else
{
// It's an impossible connection
LOG(MODULE_GRAPH, "Unrecognized connection, RARE.")
}
// CurrentRule.inboundTag = _inbounds.values();
// }
// else if (ruleNodes.values().contains(sourceNode->id()) && outboundNodes.values().contains(targetNode->id()))
// {
// // It's a rule-outbound connection
// onNodeClicked(*sourceNode);
// onNodeClicked(*targetNode);
// CurrentRule.outboundTag = GetFirstNodeData(targetNode->id(), OutboundNode)->GetOutbound();
// // Connecting to an outbound will disable the balancer feature.
// CurrentRule.QV2RAY_RULE_USE_BALANCER = false;
// // Update balancer settings.
// // ShowCurrentRuleDetail();
// LOG(MODULE_GRAPH, "Updated outbound: " + CurrentRule.outboundTag)
// }
// else
// {
// // It's an impossible connection
// LOG(MODULE_GRAPH, "Unrecognized connection, RARE.")
// }
}
void RouteEditor::onConnectionDeleted(QtNodes::Connection const &c)
@ -278,36 +265,36 @@ void RouteEditor::onConnectionDeleted(QtNodes::Connection const &c)
const auto &source = c.getNode(PortType::Out);
const auto &target = c.getNode(PortType::In);
if (inboundNodes.values().contains(source->id()) && ruleNodes.values().contains(target->id()))
{
// It's a inbound-rule connection
onNodeClicked(*source);
onNodeClicked(*target);
currentRuleTag = GetFirstNodeData(target->id(), RuleNode)->GetRuleTag();
auto _inboundTag = GetFirstNodeData(source->id(), InboundNode)->GetInbound();
LOG(MODULE_UI, "Removing inbound: " + _inboundTag + " from rule: " + currentRuleTag)
CurrentRule.inboundTag.removeAll(_inboundTag);
}
else if (ruleNodes.values().contains(source->id()) && outboundNodes.values().contains(target->id()))
{
// It's a rule-outbound connection
onNodeClicked(*source);
onNodeClicked(*target);
currentRuleTag = GetFirstNodeData(source->id(), RuleNode)->GetRuleTag();
auto _outboundTag = GetFirstNodeData(target->id(), OutboundNode)->GetOutbound();
if (!CurrentRule.QV2RAY_RULE_USE_BALANCER && CurrentRule.outboundTag == _outboundTag)
{
CurrentRule.outboundTag.clear();
}
LOG(MODULE_GRAPH, "Removing an outbound: " + _outboundTag)
}
else
{
// It's an impossible connection
LOG(MODULE_GRAPH, "Selected an unknown node, RARE.")
}
// if (inboundNodes.values().contains(source->id()) && ruleNodes.values().contains(target->id()))
//{
// // It's a inbound-rule connection
// onNodeClicked(*source);
// onNodeClicked(*target);
// currentRuleTag = GetFirstNodeData(target->id(), RuleNode)->GetRuleTag();
// auto _inboundTag = GetFirstNodeData(source->id(), InboundNode)->GetInbound();
// LOG(MODULE_UI, "Removing inbound: " + _inboundTag + " from rule: " + currentRuleTag)
// CurrentRule.inboundTag.removeAll(_inboundTag);
//}
// else if (ruleNodes.values().contains(source->id()) && outboundNodes.values().contains(target->id()))
//{
// // It's a rule-outbound connection
// onNodeClicked(*source);
// onNodeClicked(*target);
// currentRuleTag = GetFirstNodeData(source->id(), RuleNode)->GetRuleTag();
// auto _outboundTag = GetFirstNodeData(target->id(), OutboundNode)->GetOutbound();
//
// if (!CurrentRule.QV2RAY_RULE_USE_BALANCER && CurrentRule.outboundTag == _outboundTag)
// {
// CurrentRule.outboundTag.clear();
// }
//
// LOG(MODULE_GRAPH, "Removing an outbound: " + _outboundTag)
//}
// else
//{
// // It's an impossible connection
// LOG(MODULE_GRAPH, "Selected an unknown node, RARE.")
//}
}
CONFIGROOT RouteEditor::OpenEditor()
@ -330,7 +317,7 @@ CONFIGROOT RouteEditor::OpenEditor()
// Append rules by order
for (auto i = 0; i < ruleListWidget->count(); i++)
{
auto _rule = rules[ruleListWidget->item(i)->text()];
auto _rule = rules[i];
auto ruleJsonObject = _rule.toJson();
// Process balancer for a rule
@ -339,19 +326,19 @@ CONFIGROOT RouteEditor::OpenEditor()
// Do not use outbound tag.
ruleJsonObject.remove("outboundTag");
// Find balancer list
if (!balancers.contains(_rule.balancerTag))
{
LOG(MODULE_UI, "Cannot find a balancer for tag: " + _rule.balancerTag)
}
else
{
auto _balancerList = balancers[_rule.balancerTag];
QJsonObject balancerEntry;
balancerEntry["tag"] = _rule.balancerTag;
balancerEntry["selector"] = QJsonArray::fromStringList(_balancerList);
_balancers.append(balancerEntry);
}
// // Find balancer list
// if (!balancers.contains(_rule.balancerTag))
// {
// LOG(MODULE_UI, "Cannot find a balancer for tag: " + _rule.balancerTag)
// }
// else
// {
// auto _balancerList = balancers[_rule.balancerTag];
// QJsonObject balancerEntry;
// balancerEntry["tag"] = _rule.balancerTag;
// balancerEntry["selector"] = QJsonArray::fromStringList(_balancerList);
// _balancers.append(balancerEntry);
// }
}
// Remove some empty fields.
@ -425,85 +412,6 @@ void RouteEditor::on_buttonBox_accepted()
{
}
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;
}
// Switch to the detailed page.
ruleEnableCB->setEnabled(true);
ruleEnableCB->setChecked(CurrentRule.QV2RAY_RULE_ENABLED);
routeEditGroupBox->setEnabled(true);
ruleTagLineEdit->setEnabled(true);
ruleRenameBtn->setEnabled(true);
routeRuleGroupBox->setEnabled(true);
LOAD_FLAG_BEGIN
ruleTagLineEdit->setText(CurrentRule.QV2RAY_RULE_TAG);
balancerSelectionCombo->clear();
for (auto out : outbounds)
{
balancerSelectionCombo->addItem(getTag(OUTBOUND(out)));
}
//
// Balancers combo and balancer list.
enableBalancerCB->setChecked(CurrentRule.QV2RAY_RULE_USE_BALANCER);
balancersWidget->setEnabled(CurrentRule.QV2RAY_RULE_USE_BALANCER);
if (!CurrentRule.balancerTag.isEmpty())
{
balancerList->clear();
balancerList->addItems(balancers[CurrentRule.balancerTag]);
}
isLoading = false;
// Networks
auto network = CurrentRule.network.toLower();
bool isBoth = (network.contains("tcp") && network.contains("udp")) || network.isEmpty();
netUDPRB->setChecked(network.contains("udp"));
netTCPRB->setChecked(network.contains("tcp"));
netBothRB->setChecked(isBoth);
//
// Set protocol checkboxes.
auto protocol = CurrentRule.protocol;
routeProtocolHTTPCB->setChecked(protocol.contains("http"));
routeProtocolTLSCB->setChecked(protocol.contains("tls"));
routeProtocolBTCB->setChecked(protocol.contains("bittorrent"));
//
// Port
routePortTxt->setText(CurrentRule.port);
//
// Users
QString users = CurrentRule.user.join(NEWLINE);
routeUserTxt->setPlainText(users);
//
// Incoming Sources
QString sources = CurrentRule.source.join(NEWLINE);
sourceIPList->setPlainText(sources);
//
// Domains
QString domains = CurrentRule.domain.join(NEWLINE);
hostList->setPlainText(domains);
//
// Outcoming IPs
QString ips = CurrentRule.ip.join(NEWLINE);
ipList->setPlainText(ips);
LOAD_FLAG_END
}
void RouteEditor::on_insertDirectBtn_clicked()
{
auto freedom = GenerateFreedomOUT("AsIs", "", 0);
@ -514,172 +422,6 @@ void RouteEditor::on_insertDirectBtn_clicked()
statusLabel->setText(tr("Added DIRECT outbound"));
}
void RouteEditor::on_routeProtocolHTTPCB_stateChanged(int arg1)
{
LOADINGCHECK
QStringList protocols;
if (arg1 == Qt::Checked)
protocols.push_back("http");
if (routeProtocolTLSCB->isChecked())
protocols.push_back("tls");
if (routeProtocolBTCB->isChecked())
protocols.push_back("bittorrent");
CurrentRule.protocol = protocols;
statusLabel->setText(tr("Protocol list changed: ") + protocols.join(";"));
}
void RouteEditor::on_routeProtocolTLSCB_stateChanged(int arg1)
{
LOADINGCHECK
QStringList protocols;
if (arg1 == Qt::Checked)
protocols.push_back("tls");
if (routeProtocolHTTPCB->isChecked())
protocols.push_back("http");
if (routeProtocolBTCB->isChecked())
protocols.push_back("bittorrent");
CurrentRule.protocol = protocols;
statusLabel->setText(tr("Protocol list changed: ") + protocols.join(";"));
}
void RouteEditor::on_routeProtocolBTCB_stateChanged(int arg1)
{
LOADINGCHECK
QStringList protocols;
if (arg1 == Qt::Checked)
protocols.push_back("bittorrent");
if (routeProtocolHTTPCB->isChecked())
protocols.push_back("http");
if (routeProtocolTLSCB->isChecked())
protocols.push_back("tls");
CurrentRule.protocol = protocols;
statusLabel->setText(tr("Protocol list changed: ") + protocols.join(";"));
}
void RouteEditor::on_balancerAddBtn_clicked()
{
LOADINGCHECK
auto balancerTx = balancerSelectionCombo->currentText();
if (!balancerTx.isEmpty())
{
this->balancers[CurrentRule.balancerTag].append(balancerSelectionCombo->currentText());
balancerList->addItem(balancerTx);
balancerSelectionCombo->setEditText("");
statusLabel->setText(tr("OK"));
}
else
{
statusLabel->setText(tr("Balancer is empty, not processing."));
}
}
void RouteEditor::on_balancerDelBtn_clicked()
{
LOADINGCHECK
if (balancerList->currentRow() < 0)
{
return;
}
balancers[CurrentRule.balancerTag].removeAt(balancerList->currentRow());
balancerList->takeItem(balancerList->currentRow());
statusLabel->setText(tr("Removed a balancer entry."));
}
void RouteEditor::on_hostList_textChanged()
{
LOADINGCHECK
CurrentRule.domain = SplitLines(hostList->toPlainText());
}
void RouteEditor::on_ipList_textChanged()
{
LOADINGCHECK
CurrentRule.ip = SplitLines(ipList->toPlainText());
}
void RouteEditor::on_routePortTxt_textEdited(const QString &arg1)
{
LOADINGCHECK
CurrentRule.port = arg1;
}
void RouteEditor::on_routeUserTxt_textEdited(const QString &arg1)
{
LOADINGCHECK
CurrentRule.user = SplitLines(arg1);
}
void RouteEditor::on_addRouteBtn_clicked()
{
auto ruleName = AddNewRule();
Q_UNUSED(ruleName)
}
void RouteEditor::on_netBothRB_clicked()
{
LOADINGCHECK
CurrentRule.network = "tcp,udp";
}
void RouteEditor::on_netUDPRB_clicked()
{
LOADINGCHECK
CurrentRule.network = "udp";
}
void RouteEditor::on_netTCPRB_clicked()
{
LOADINGCHECK
CurrentRule.network = "tcp";
}
void RouteEditor::on_routeUserTxt_textChanged()
{
LOADINGCHECK
CurrentRule.user = SplitLines(routeUserTxt->toPlainText());
}
void RouteEditor::on_sourceIPList_textChanged()
{
LOADINGCHECK
CurrentRule.source = SplitLines(sourceIPList->toPlainText());
}
void RouteEditor::on_enableBalancerCB_stateChanged(int arg1)
{
LOADINGCHECK
auto useBalancer = arg1 == Qt::Checked;
CurrentRule.QV2RAY_RULE_USE_BALANCER = useBalancer;
balancersWidget->setEnabled(useBalancer);
if (CurrentRule.balancerTag.isEmpty())
{
LOG(MODULE_UI, "Creating a new balancer tag.")
CurrentRule.balancerTag = GenerateRandomString(6);
balancers[CurrentRule.balancerTag] = QStringList();
}
DEBUG(MODULE_UI, "Balancer: " + CurrentRule.balancerTag)
if (useBalancer)
{
LOG(MODULE_UI, "A rule has been set to use balancer, disconnect it to any outbound.")
auto ruleNode = ruleNodes[currentRuleTag];
for (auto &&[_, conn] : nodeScene->connections())
{
if (conn->getNode(PortType::Out)->id() == ruleNode)
{
nodeScene->deleteConnection(*conn);
// Since there should be only one connection from this rule node.
break;
}
}
}
else
{
QvMessageBoxWarn(this, tr("Route Editor"), tr("To make this rule ready to use, you need to connect it to an outbound node."));
}
}
void RouteEditor::on_addDefaultBtn_clicked()
{
LOADINGCHECK
@ -809,13 +551,7 @@ void RouteEditor::on_addOutboundBtn_clicked()
CHECKEMPTYRULES
}
void RouteEditor::on_ruleEnableCB_stateChanged(int arg1)
{
bool _isEnabled = arg1 == Qt::Checked;
CurrentRule.QV2RAY_RULE_ENABLED = _isEnabled;
routeEditGroupBox->setEnabled(_isEnabled);
routeRuleGroupBox->setEnabled(_isEnabled);
}
void RouteEditor::on_delBtn_clicked()
{
if (nodeScene->selectedNodes().empty())
@ -834,57 +570,57 @@ void RouteEditor::on_delBtn_clicked()
// the node container.
if (isInbound)
{
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);
// 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);
// 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();
// 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
@ -893,6 +629,11 @@ void RouteEditor::on_delBtn_clicked()
QvMessageBoxWarn(this, tr("Error"), tr("Qv2ray entered an unknown state."));
}
}
void RouteEditor::on_addRouteBtn_clicked()
{
auto ruleName = AddNewRule();
Q_UNUSED(ruleName)
}
void RouteEditor::on_editBtn_clicked()
{
if (nodeScene->selectedNodes().empty())
@ -907,117 +648,117 @@ void RouteEditor::on_editBtn_clicked()
if (isInbound)
{
currentInboundOutboundTag = GetFirstNodeData(firstNode->id(), InboundNode)->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();
int _code;
if (protocol != "http" && protocol != "mtproto" && protocol != "socks" && protocol != "dokodemo-door")
{
QvMessageBoxWarn(this, tr("Cannot Edit"),
tr("Currently, this type of outbound is not supported by the editor.") + "\r\n" +
tr("We will launch Json Editor instead."));
statusLabel->setText(tr("Opening JSON editor"));
JsonEditor w(_in, this);
_result = INBOUND(w.OpenEditor());
_code = w.result();
}
else
{
InboundEditor w(_in, this);
statusLabel->setText(tr("Opening default inbound editor"));
_result = w.OpenEditor();
_code = w.result();
}
statusLabel->setText(tr("OK"));
if (_code == QDialog::Accepted)
{
bool isTagChanged = getTag(_in) != getTag(_result);
if (isTagChanged)
{
auto newTag = getTag(_result);
RenameItemTag(RENAME_INBOUND, getTag(_in), &newTag);
}
DEBUG(MODULE_UI, "Removed old tag: " + getTag(_in))
inbounds.remove(getTag(_in));
DEBUG(MODULE_UI, "Adding new tag: " + getTag(_result))
inbounds.insert(getTag(_result), _result);
}
// currentInboundOutboundTag = GetFirstNodeData(firstNode->id(), InboundNode)->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();
// int _code;
//
// if (protocol != "http" && protocol != "mtproto" && protocol != "socks" && protocol != "dokodemo-door")
// {
// QvMessageBoxWarn(this, tr("Cannot Edit"),
// tr("Currently, this type of outbound is not supported by the editor.") + "\r\n" +
// tr("We will launch Json Editor instead."));
// statusLabel->setText(tr("Opening JSON editor"));
// JsonEditor w(_in, this);
// _result = INBOUND(w.OpenEditor());
// _code = w.result();
// }
// else
// {
// InboundEditor w(_in, this);
// statusLabel->setText(tr("Opening default inbound editor"));
// _result = w.OpenEditor();
// _code = w.result();
// }
//
// statusLabel->setText(tr("OK"));
//
// if (_code == QDialog::Accepted)
// {
// bool isTagChanged = getTag(_in) != getTag(_result);
//
// if (isTagChanged)
// {
// auto newTag = getTag(_result);
// RenameItemTag(RENAME_INBOUND, getTag(_in), &newTag);
// }
//
// DEBUG(MODULE_UI, "Removed old tag: " + getTag(_in))
// inbounds.remove(getTag(_in));
// DEBUG(MODULE_UI, "Adding new tag: " + getTag(_result))
// inbounds.insert(getTag(_result), _result);
// }
}
else if (isOutbound)
{
currentInboundOutboundTag = GetFirstNodeData(firstNode->id(), OutboundNode)->GetOutbound();
if (!outbounds.contains(currentInboundOutboundTag))
{
QvMessageBoxWarn(this, tr("Edit Inbound"), tr("No inbound tag found: ") + currentInboundOutboundTag);
return;
}
OUTBOUND _result;
auto _out = outbounds.value(currentInboundOutboundTag);
auto protocol = _out["protocol"].toString().toLower();
int _code;
bool guisupport = true;
if (protocol != "vmess" && protocol != "shadowsocks" && protocol != "socks" && protocol != "http")
{
guisupport = false;
auto pluginEditorWidgetsInfo = PluginHost->GetOutboundEditorWidgets();
for (const auto &plugin : pluginEditorWidgetsInfo)
{
for (const auto &_d : plugin->OutboundCapabilities())
{
guisupport = guisupport || protocol == _d.protocol;
}
}
}
if (!guisupport)
{
QvMessageBoxWarn(this, tr("Unsupported Outbound Type"),
tr("This outbound entry is not supported by the GUI editor.") + NEWLINE +
tr("We will launch Json Editor instead."));
JsonEditor w(_out, this);
statusLabel->setText(tr("Opening JSON editor"));
_result = OUTBOUND(w.OpenEditor());
_code = w.result();
}
else
{
OutboundEditor w(_out, this);
statusLabel->setText(tr("Opening default outbound editor."));
_result = w.OpenEditor();
_code = w.result();
}
if (_code == QDialog::Accepted)
{
bool isTagChanged = getTag(_out) != getTag(_result);
if (isTagChanged)
{
auto newTag = getTag(_result);
DEBUG(MODULE_UI, "Outbound tag is changed: " + newTag)
RenameItemTag(RENAME_OUTBOUND, getTag(_out), &newTag);
}
DEBUG(MODULE_UI, "Adding new tag: " + getTag(_result))
outbounds.insert(getTag(_result), _result);
statusLabel->setText(tr("OK"));
}
// currentInboundOutboundTag = GetFirstNodeData(firstNode->id(), OutboundNode)->GetOutbound();
//
// if (!outbounds.contains(currentInboundOutboundTag))
//{
// QvMessageBoxWarn(this, tr("Edit Inbound"), tr("No inbound tag found: ") + currentInboundOutboundTag);
// return;
//}
//
// OUTBOUND _result;
// auto _out = outbounds.value(currentInboundOutboundTag);
// auto protocol = _out["protocol"].toString().toLower();
// int _code;
//
// bool guisupport = true;
// if (protocol != "vmess" && protocol != "shadowsocks" && protocol != "socks" && protocol != "http")
//{
// guisupport = false;
// auto pluginEditorWidgetsInfo = PluginHost->GetOutboundEditorWidgets();
// for (const auto &plugin : pluginEditorWidgetsInfo)
// {
// for (const auto &_d : plugin->OutboundCapabilities())
// {
// guisupport = guisupport || protocol == _d.protocol;
// }
// }
//}
//
// if (!guisupport)
//{
// QvMessageBoxWarn(this, tr("Unsupported Outbound Type"),
// tr("This outbound entry is not supported by the GUI editor.") + NEWLINE +
// tr("We will launch Json Editor instead."));
// JsonEditor w(_out, this);
// statusLabel->setText(tr("Opening JSON editor"));
// _result = OUTBOUND(w.OpenEditor());
// _code = w.result();
//}
// else
//{
// OutboundEditor w(_out, this);
// statusLabel->setText(tr("Opening default outbound editor."));
// _result = w.OpenEditor();
// _code = w.result();
//}
//
// if (_code == QDialog::Accepted)
//{
// bool isTagChanged = getTag(_out) != getTag(_result);
//
// if (isTagChanged)
// {
// auto newTag = getTag(_result);
// DEBUG(MODULE_UI, "Outbound tag is changed: " + newTag)
// RenameItemTag(RENAME_OUTBOUND, getTag(_out), &newTag);
// }
//
// DEBUG(MODULE_UI, "Adding new tag: " + getTag(_result))
// outbounds.insert(getTag(_result), _result);
// statusLabel->setText(tr("OK"));
//}
}
else
{
@ -1031,31 +772,6 @@ void RouteEditor::on_domainStrategyCombo_currentIndexChanged(const QString &arg1
domainStrategy = arg1;
}
void RouteEditor::on_ruleRenameBtn_clicked()
{
auto newTag = ruleTagLineEdit->text();
if (newTag.isEmpty())
{
LOG(MODULE_UI, "Tag is empty, this is ILLEGAL!")
QvMessageBoxWarn(this, tr("Renaming a tag"), tr("New tag is empty, please try another."));
}
else if (newTag == CurrentRule.QV2RAY_RULE_TAG)
{
LOG(MODULE_UI, "No tag changed, returning.")
QvMessageBoxInfo(this, tr("Renaming a tag"), tr("New tag is the same as the original one."));
}
else if (rules.contains(newTag))
{
LOG(MODULE_UI, "Tag duplicate detected.")
QvMessageBoxWarn(this, tr("Renaming a tag"), tr("Duplicate rule tag detected, please try another."));
}
else
{
RenameItemTag(RENAME_RULE, CurrentRule.QV2RAY_RULE_TAG, &newTag);
}
}
void RouteEditor::on_defaultOutboundCombo_currentTextChanged(const QString &arg1)
{
LOADINGCHECK

View File

@ -36,68 +36,30 @@ class RouteEditor
void processCommands(QString, QStringList, QMap<QString, QString>) override{};
private:
void updateColorScheme() override{};
void updateColorScheme() override
{
// Setup icons according to the theme settings.
addInboundBtn->setIcon(QICON_R("add.png"));
addOutboundBtn->setIcon(QICON_R("add.png"));
editBtn->setIcon(QICON_R("edit.png"));
addRouteBtn->setIcon(QICON_R("add.png"));
delBtn->setIcon(QICON_R("delete.png"));
};
QvMessageBusSlotDecl;
private slots:
void on_buttonBox_accepted();
void on_insertDirectBtn_clicked();
void on_routeProtocolHTTPCB_stateChanged(int arg1);
void on_routeProtocolTLSCB_stateChanged(int arg1);
void on_routeProtocolBTCB_stateChanged(int arg1);
void on_balancerAddBtn_clicked();
void on_balancerDelBtn_clicked();
void on_hostList_textChanged();
void on_ipList_textChanged();
void on_routePortTxt_textEdited(const QString &arg1);
void on_routeUserTxt_textEdited(const QString &arg1);
void on_addRouteBtn_clicked();
void on_netBothRB_clicked();
void on_netUDPRB_clicked();
void on_netTCPRB_clicked();
void on_routeUserTxt_textChanged();
void on_sourceIPList_textChanged();
void on_enableBalancerCB_stateChanged(int arg1);
void on_addDefaultBtn_clicked();
void on_insertBlackBtn_clicked();
void on_addInboundBtn_clicked();
void on_addOutboundBtn_clicked();
void on_ruleEnableCB_stateChanged(int arg1);
void on_delBtn_clicked();
void on_editBtn_clicked();
void on_domainStrategyCombo_currentIndexChanged(const QString &arg1);
void on_ruleRenameBtn_clicked();
void on_defaultOutboundCombo_currentTextChanged(const QString &arg1);
void on_importExistingBtn_clicked();
void on_importGroupBtn_currentIndexChanged(int index);
public slots:
@ -108,17 +70,16 @@ class RouteEditor
private:
bool isLoading = false;
void RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, QString *newTag);
void ShowCurrentRuleDetail();
//
QString currentRuleTag;
// QString currentRuleTag;
QString currentInboundOutboundTag;
QMap<QString, QStringList> balancers;
// QMap<QString, QStringList> balancers;
QString domainStrategy;
QString defaultOutbound;
//
QMap<QString, INBOUND> inbounds;
QMap<QString, OUTBOUND> outbounds;
QMap<QString, RuleObject> rules;
QList<INBOUND> inbounds;
QList<OUTBOUND> outbounds;
QList<RuleObject> rules;
//
CONFIGROOT root;
CONFIGROOT original;

View File

@ -297,7 +297,7 @@
<item row="1" column="1">
<widget class="QToolBox" name="toolBox">
<property name="currentIndex">
<number>1</number>
<number>0</number>
</property>
<widget class="QWidget" name="page_2">
<property name="geometry">
@ -305,7 +305,7 @@
<x>0</x>
<y>0</y>
<width>359</width>
<height>505</height>
<height>536</height>
</rect>
</property>
<attribute name="label">
@ -401,275 +401,6 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="page">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>347</width>
<height>704</height>
</rect>
</property>
<attribute name="label">
<string>Rule Settings</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Rule Status</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="ruleEnableCB">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Enabled</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Rule Tag</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLineEdit" name="ruleTagLineEdit">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="ruleRenameBtn">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Rename</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="routeEditGroupBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="title">
<string>Route Editor</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string>Network</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QRadioButton" name="netTCPRB">
<property name="text">
<string>TCP</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="netUDPRB">
<property name="text">
<string>UDP</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="netBothRB">
<property name="text">
<string>Both</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Protocol</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QCheckBox" name="routeProtocolHTTPCB">
<property name="text">
<string>HTTP</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="routeProtocolTLSCB">
<property name="text">
<string>TLS</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="routeProtocolBTCB">
<property name="text">
<string>BitTorrent</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_14">
<property name="text">
<string>Port</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="routePortTxt">
<property name="placeholderText">
<string>e.g. 80, 443, 8000-8080</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Balancers</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="enableBalancerCB">
<property name="text">
<string>Use Balancers</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QWidget" name="balancersWidget" native="true">
<layout class="QGridLayout" name="balancerLayout">
<item row="0" column="0">
<widget class="QComboBox" name="balancerSelectionCombo">
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0" rowspan="2">
<widget class="QListWidget" name="balancerList"/>
</item>
<item row="1" column="1">
<widget class="QToolButton" name="balancerDelBtn">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="2" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QToolButton" name="balancerAddBtn">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="routeRuleGroupBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="title">
<string>Route Detail Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_15">
<property name="text">
<string>Users List</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Source IP Matches</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPlainTextEdit" name="routeUserTxt"/>
</item>
<item row="1" column="1">
<widget class="QPlainTextEdit" name="sourceIPList"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Target Domain List</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Target IP List</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QPlainTextEdit" name="hostList"/>
</item>
<item row="3" column="1">
<widget class="QPlainTextEdit" name="ipList"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item row="2" column="0" colspan="2">
@ -715,25 +446,6 @@
<tabstop>domainStrategyCombo</tabstop>
<tabstop>defaultOutboundCombo</tabstop>
<tabstop>ruleListWidget</tabstop>
<tabstop>ruleEnableCB</tabstop>
<tabstop>ruleTagLineEdit</tabstop>
<tabstop>ruleRenameBtn</tabstop>
<tabstop>netTCPRB</tabstop>
<tabstop>netUDPRB</tabstop>
<tabstop>netBothRB</tabstop>
<tabstop>routeProtocolHTTPCB</tabstop>
<tabstop>routeProtocolTLSCB</tabstop>
<tabstop>routeProtocolBTCB</tabstop>
<tabstop>routePortTxt</tabstop>
<tabstop>enableBalancerCB</tabstop>
<tabstop>balancerSelectionCombo</tabstop>
<tabstop>balancerAddBtn</tabstop>
<tabstop>balancerList</tabstop>
<tabstop>balancerDelBtn</tabstop>
<tabstop>routeUserTxt</tabstop>
<tabstop>sourceIPList</tabstop>
<tabstop>ipList</tabstop>
<tabstop>hostList</tabstop>
</tabstops>
<resources/>
<connections>

View File

@ -1,10 +1,11 @@
#include <nodes/internal/FlowScene.hpp>
#include "core/CoreUtils.hpp"
#include "ui/common/UIBase.hpp"
#include "ui/models/InboundNodeModel.hpp"
#include "ui/models/OutboundNodeModel.hpp"
#include "ui/models/RuleNodeModel.hpp"
#include "w_RoutesEditor.hpp"
#include <nodes/internal/FlowScene.hpp>
// Supplementary source file for Routes editor, basically providing
// routes-related operations.
@ -12,40 +13,36 @@ void RouteEditor::AddInbound(INBOUND in)
{
QString tag = getTag(in);
if (inbounds.contains(tag))
{
tag = tag + "_" + GenerateRandomString(5);
}
if (inboundNodes.contains(tag))
tag.append("_" + GenerateRandomString(5));
in["tag"] = tag;
auto _nodeData = std::make_unique<QvInboundNodeModel>(std::make_shared<InboundNodeData>(tag));
inbounds << in;
auto _nodeData = std::make_unique<QvInboundNodeModel>(std::make_shared<InboundNodeData>(std::make_shared<INBOUND>(inbounds.last())));
auto &node = nodeScene->createNode(std::move(_nodeData));
QPointF pos;
pos.setX(0 + GRAPH_GLOBAL_OFFSET_X);
pos.setY(inboundNodes.count() * 130 + GRAPH_GLOBAL_OFFSET_Y);
nodeScene->setNodePosition(node, pos);
inboundNodes.insert(tag, node.id());
inbounds.insert(getTag(in), in);
}
void RouteEditor::AddOutbound(OUTBOUND out)
{
QString tag = getTag(out);
if (outbounds.contains(tag))
{
tag = tag + "_" + GenerateRandomString(5);
}
if (outboundNodes.contains(tag))
tag.append("_" + GenerateRandomString(5));
out["tag"] = tag;
auto _nodeData = std::make_unique<QvOutboundNodeModel>(std::make_shared<OutboundNodeData>(tag));
outbounds << out;
auto _nodeData = std::make_unique<QvOutboundNodeModel>(std::make_shared<OutboundNodeData>(std::make_shared<OUTBOUND>(outbounds.last())));
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.insert(tag, node.id());
outbounds.insert(tag, out);
defaultOutboundCombo->addItem(tag);
}
@ -60,7 +57,7 @@ QString RouteEditor::AddNewRule()
auto bTag = GenerateRandomString();
rule.QV2RAY_RULE_TAG = rules.isEmpty() ? tr("Default rule") : (tr("rule") + "-" + GenerateRandomString(6));
rule.balancerTag = bTag;
balancers[bTag] = QStringList();
// balancers[bTag] = QStringList();
AddRule(rule);
return rule.QV2RAY_RULE_TAG;
}
@ -73,11 +70,11 @@ void RouteEditor::AddRule(RuleObject rule)
rule.QV2RAY_RULE_TAG += "-" + GenerateRandomString(5);
}
rules.insert(rule.QV2RAY_RULE_TAG, rule);
rules << 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 = std::make_unique<QvRuleNodeModel>(std::make_shared<RuleNodeData>(rule.QV2RAY_RULE_TAG));
auto _nodeData = std::make_unique<QvRuleNodeModel>(std::make_shared<RuleNodeData>(std::make_shared<RuleObject>(rules.last())));
auto &node = nodeScene->createNode(std::move(_nodeData));
nodeScene->setNodePosition(node, pos);
@ -121,6 +118,7 @@ void RouteEditor::AddRule(RuleObject rule)
// Do not use reference here, we need deep copy of EVERY QString.
void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, QString *newTag)
{
/*
switch (mode)
{
case RENAME_RULE:
@ -158,11 +156,11 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag,
{
items.first()->setText(*newTag);
}
if (currentRuleTag == originalTag)
{
currentRuleTag = *newTag;
}
abort();
// if (currentRuleTag == originalTag)
// {
// currentRuleTag = *newTag;
// }
}
else
{
@ -261,7 +259,7 @@ void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag,
}
break;
}
}*/
}
// Do not use const reference here.
@ -272,7 +270,9 @@ void RouteEditor::ResolveDefaultOutboundTag(const QString original, const QStrin
//
isLoading = true;
defaultOutboundCombo->clear();
defaultOutboundCombo->addItems(outbounds.keys());
//
for (const auto &out : outbounds) defaultOutboundCombo->addItem(getTag(out));
//
isLoading = false;
//
if (!isDefaultChanged)
@ -293,7 +293,7 @@ void RouteEditor::ResolveDefaultOutboundTag(const QString original, const QStrin
else
{
defaultOutbound = getTag(outbounds.first());
defaultOutboundCombo->addItem(outbounds.firstKey());
defaultOutboundCombo->addItem(getTag(outbounds.first()));
}
}
else

View File

@ -3,13 +3,7 @@
QvInboundNodeModel::QvInboundNodeModel(std::shared_ptr<InboundNodeData> data) : NodeDataModel()
{
_in = data;
_label = new QLabel();
//
QFont font = _label->font();
font.setPointSize(font.pointSize() + GRAPH_NODE_LABEL_FONTSIZE_INCREMENT);
_label->setFont(font);
//
_label->setText(data->GetInbound());
_label->setWindowFlags(Qt::FramelessWindowHint);
_label->setAttribute(Qt::WA_TranslucentBackground);
widget = new InboundOutboundWidget();
widget->setWindowFlags(Qt::FramelessWindowHint);
widget->setAttribute(Qt::WA_TranslucentBackground);
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "NodeModelsBase.hpp"
#include "ui/widgets/node/InboundOutboundWidget.hpp"
#include <QtCore/qglobal.h>
@ -9,12 +10,7 @@ class QvInboundNodeModel : public NodeDataModel
Q_OBJECT
public:
explicit QvInboundNodeModel(std::shared_ptr<InboundNodeData> data);
~QvInboundNodeModel()
{
// if (_label) {
// delete _label;
//}
}
~QvInboundNodeModel(){};
QString caption() const override
{
@ -40,7 +36,7 @@ class QvInboundNodeModel : public NodeDataModel
{
Q_UNUSED(portType)
Q_UNUSED(portIndex)
return inboundType;
return NODE_TYPE_INBOUND;
}
std::shared_ptr<NodeData> outData(PortIndex) override
@ -48,19 +44,17 @@ class QvInboundNodeModel : public NodeDataModel
return _in;
}
void setInData(std::shared_ptr<NodeData>, int) override
{
}
void setData(const QString &data)
void setInData(std::shared_ptr<NodeData>, int) override{};
void setData(std::shared_ptr<INBOUND> data)
{
_in = std::make_shared<InboundNodeData>(data);
_label->setText(data);
_label->adjustSize();
widget->adjustSize();
}
QWidget *embeddedWidget() override
{
return _label;
return widget;
}
std::unique_ptr<NodeDataModel> clone() const override
{
@ -72,5 +66,5 @@ class QvInboundNodeModel : public NodeDataModel
QString modelValidationError = tr("Missing or incorrect inputs");
//
std::shared_ptr<InboundNodeData> _in;
QLabel *_label;
InboundOutboundWidget *widget;
};

View File

@ -1,11 +1,12 @@
#pragma once
#include <nodes/internal/NodeDataModel.hpp>
#include <nodes/internal/PortType.hpp>
#include "base/Qv2rayBase.hpp"
#include "common/QvHelpers.hpp"
#include <QLabel>
#include <memory>
#include <nodes/internal/NodeDataModel.hpp>
#include <nodes/internal/PortType.hpp>
using QtNodes::NodeData;
using QtNodes::NodeDataModel;
@ -17,79 +18,69 @@ using QtNodes::PortType;
using QtNodes::NodeData;
using QtNodes::NodeDataType;
const int GRAPH_NODE_LABEL_FONTSIZE_INCREMENT = 3;
constexpr auto GRAPH_NODE_LABEL_FONTSIZE_INCREMENT = 3;
namespace Qv2ray::ui::nodemodels
{
const std::shared_ptr<NodeDataType> outboundType = std::make_shared<NodeDataType>("outbound", QObject::tr("Outbound"));
const std::shared_ptr<NodeDataType> inboundType = std::make_shared<NodeDataType>("inbound", QObject::tr("Inbound"));
/// The class can potentially incapsulate any user data
/// need to be transferred within the Node Editor graph
const std::shared_ptr<NodeDataType> NODE_TYPE_OUTBOUND = std::make_shared<NodeDataType>("outbound", QObject::tr("Outbound"));
const std::shared_ptr<NodeDataType> NODE_TYPE_INBOUND = std::make_shared<NodeDataType>("inbound", QObject::tr("Inbound"));
class InboundNodeData : public NodeData
{
public:
explicit InboundNodeData(QString in) : _inboundTag(in)
{
}
explicit InboundNodeData(std::shared_ptr<INBOUND> data) : inboundData(data){};
std::shared_ptr<NodeDataType> type() const override
{
return inboundType;
return NODE_TYPE_INBOUND;
}
QString GetInbound()
std::shared_ptr<INBOUND> GetInbound()
{
return _inboundTag;
return inboundData;
}
private:
QString _inboundTag;
std::shared_ptr<INBOUND> inboundData;
};
/// The class can potentially incapsulate any user data
/// need to be transferred within the Node Editor graph
class OutboundNodeData : public NodeData
{
public:
explicit OutboundNodeData(QString out) : _outboundTag(out)
{
}
explicit OutboundNodeData(std::shared_ptr<OUTBOUND> data) : outboundData(data){};
std::shared_ptr<NodeDataType> type() const override
{
return outboundType;
return NODE_TYPE_INBOUND;
}
QString GetOutbound()
std::shared_ptr<OUTBOUND> GetOutbound()
{
return _outboundTag;
return outboundData;
}
private:
QString _outboundTag;
std::shared_ptr<OUTBOUND> outboundData;
};
/// The class can potentially incapsulate any user data
/// need to be transferred within the Node Editor graph
class RuleNodeData : public NodeData
{
public:
explicit RuleNodeData(QString out) : _ruleTag(out)
{
}
explicit RuleNodeData(std::shared_ptr<RuleObject> rule) : _rule(rule){};
std::shared_ptr<NodeDataType> type() const override
{
return outboundType;
return NODE_TYPE_INBOUND;
}
QString GetRuleTag()
std::shared_ptr<RuleObject> GetRule()
{
return _ruleTag;
return _rule;
}
private:
QString _ruleTag;
std::shared_ptr<RuleObject> _rule;
};
} // namespace Qv2ray::ui::nodemodels

View File

@ -3,13 +3,7 @@
QvOutboundNodeModel::QvOutboundNodeModel(std::shared_ptr<OutboundNodeData> data) : NodeDataModel()
{
_out = data;
_label = new QLabel();
//
QFont font = _label->font();
font.setPointSize(font.pointSize() + GRAPH_NODE_LABEL_FONTSIZE_INCREMENT);
_label->setFont(font);
//
_label->setText(data->GetOutbound());
_label->setWindowFlags(Qt::FramelessWindowHint);
_label->setAttribute(Qt::WA_TranslucentBackground);
widget = new InboundOutboundWidget();
widget->setWindowFlags(Qt::FramelessWindowHint);
widget->setAttribute(Qt::WA_TranslucentBackground);
}

View File

@ -1,5 +1,6 @@
#pragma once
#include "ui/models/NodeModelsBase.hpp"
#include "ui/widgets/node/InboundOutboundWidget.hpp"
#include <QtCore/qglobal.h>
@ -8,12 +9,9 @@ class QvOutboundNodeModel : public NodeDataModel
Q_OBJECT
public:
explicit QvOutboundNodeModel(std::shared_ptr<OutboundNodeData> data);
~QvOutboundNodeModel()
{
// if (_label) {
// delete _label;
//}
}
~QvOutboundNodeModel(){};
void setInData(std::shared_ptr<NodeData>, int) override{};
void setInData(std::vector<std::shared_ptr<NodeData>>, int) override{};
QString caption() const override
{
@ -39,7 +37,7 @@ class QvOutboundNodeModel : public NodeDataModel
{
Q_UNUSED(portType)
Q_UNUSED(portIndex)
return outboundType;
return NODE_TYPE_OUTBOUND;
}
std::shared_ptr<NodeData> outData(PortIndex) override
@ -47,23 +45,15 @@ class QvOutboundNodeModel : public NodeDataModel
return _out;
}
void setInData(std::shared_ptr<NodeData>, int) override
{
}
void setInData(std::vector<std::shared_ptr<NodeData>>, int) override
{
}
void setData(const QString &data)
void setData(std::shared_ptr<OUTBOUND> data)
{
_out = std::make_shared<OutboundNodeData>(data);
_label->setText(_out->GetOutbound());
_label->adjustSize();
widget->adjustSize();
}
QWidget *embeddedWidget() override
{
return _label;
return nullptr;
}
ConnectionPolicy portInConnectionPolicy(PortIndex) const override
@ -80,5 +70,5 @@ class QvOutboundNodeModel : public NodeDataModel
QString modelValidationError = tr("Missing or incorrect inputs");
//
std::shared_ptr<OutboundNodeData> _out;
QLabel *_label;
InboundOutboundWidget *widget;
};

View File

@ -3,14 +3,7 @@
QvRuleNodeModel::QvRuleNodeModel(std::shared_ptr<RuleNodeData> data) : NodeDataModel()
{
_ruleTag = data;
_label = new QLabel();
//
QFont font = _label->font();
font.setPointSize(font.pointSize() + GRAPH_NODE_LABEL_FONTSIZE_INCREMENT);
font.setBold(true);
_label->setFont(font);
//
_label->setText(data->GetRuleTag());
_label->setWindowFlags(Qt::FramelessWindowHint);
_label->setAttribute(Qt::WA_TranslucentBackground);
ruleWidget = new QvNodeRuleWidget();
ruleWidget->setWindowFlags(Qt::FramelessWindowHint);
ruleWidget->setAttribute(Qt::WA_TranslucentBackground);
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "ui/models/NodeModelsBase.hpp"
#include "ui/widgets/node/RuleWidget.hpp"
#include <QtCore/qglobal.h>
@ -9,12 +10,7 @@ class QvRuleNodeModel : public NodeDataModel
Q_OBJECT
public:
QvRuleNodeModel(std::shared_ptr<RuleNodeData> data);
~QvRuleNodeModel()
{
// if (_label) {
// delete _label;
//}
}
~QvRuleNodeModel(){};
QString caption() const override
{
@ -28,61 +24,42 @@ class QvRuleNodeModel : public NodeDataModel
unsigned int nPorts(PortType portType) const override
{
if (portType == PortType::In)
{
if (portType == PortType::In || portType == PortType::Out)
return 1;
}
else if (portType == PortType::Out)
{
return 1;
}
else
{
return 0;
}
}
QString name() const override
{
return "RuleNode";
}
std::shared_ptr<NodeDataType> dataType(PortType portType, PortIndex portIndex) const override
std::shared_ptr<NodeDataType> dataType(PortType portType, PortIndex) const override
{
Q_UNUSED(portIndex)
switch (portType)
{
case PortType::In: return inboundType;
case PortType::Out: return outboundType;
case PortType::In: return NODE_TYPE_INBOUND;
case PortType::Out: return NODE_TYPE_OUTBOUND;
default: return {};
}
}
std::shared_ptr<NodeData> outData(PortIndex port) override
std::shared_ptr<NodeData> outData(PortIndex) override
{
Q_UNUSED(port)
return _ruleTag;
}
void setInData(std::shared_ptr<NodeData>, int) override
{
}
void setInData(std::vector<std::shared_ptr<NodeData>>, int) override
{
}
void setData(const QString &data)
void setInData(std::shared_ptr<NodeData>, int) override{};
void setInData(std::vector<std::shared_ptr<NodeData>>, int) override{};
void setData(std::shared_ptr<RuleObject> data)
{
_ruleTag = std::make_shared<RuleNodeData>(data);
_label->setText(_ruleTag->GetRuleTag());
_label->adjustSize();
ruleWidget->adjustSize();
}
QWidget *embeddedWidget() override
{
return _label;
return ruleWidget;
}
ConnectionPolicy portInConnectionPolicy(PortIndex) const override
@ -104,5 +81,5 @@ class QvRuleNodeModel : public NodeDataModel
QString modelValidationError = tr("Missing or incorrect inputs");
//
std::shared_ptr<RuleNodeData> _ruleTag;
QLabel *_label;
QvNodeRuleWidget *ruleWidget;
};

View File

@ -1,8 +1,12 @@
#include "OutboundBalancerWidget.hpp"
#include "base/Qv2rayBase.hpp"
OutboundBalancerWidget::OutboundBalancerWidget(QWidget *parent) : QWidget(parent)
{
setupUi(this);
balancerAddBtn->setIcon(QICON_R("add.png"));
balancerDelBtn->setIcon(QICON_R("delete.png"));
}
void OutboundBalancerWidget::changeEvent(QEvent *e)
@ -14,3 +18,31 @@ void OutboundBalancerWidget::changeEvent(QEvent *e)
default: break;
}
}
void OutboundBalancerWidget::on_balancerAddBtn_clicked()
{
auto balancerTx = balancerSelectionCombo->currentText();
if (!balancerTx.isEmpty())
{
targetList.append(balancerSelectionCombo->currentText());
balancerList->addItem(balancerTx);
balancerSelectionCombo->setEditText("");
// statusLabel->setText(tr("OK"));
}
else
{
// statusLabel->setText(tr("Balancer is empty, not processing."));
}
}
void OutboundBalancerWidget::on_balancerDelBtn_clicked()
{
if (balancerList->currentRow() < 0)
{
return;
}
targetList.removeAt(balancerList->currentRow());
balancerList->takeItem(balancerList->currentRow());
// statusLabel->setText(tr("Removed a balancer entry."));
}

View File

@ -10,7 +10,11 @@ class OutboundBalancerWidget
public:
explicit OutboundBalancerWidget(QWidget *parent = nullptr);
void on_balancerAddBtn_clicked();
void on_balancerDelBtn_clicked();
protected:
void changeEvent(QEvent *e);
QStringList targetList;
};

View File

@ -1,9 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<author/>
<comment/>
<exportmacro/>
<class>OutboundBalancerWidget</class>
<widget name="OutboundBalancerWidget" class="QWidget">
<widget class="QWidget" name="OutboundBalancerWidget">
<property name="geometry">
<rect>
<x>0</x>
@ -15,7 +13,56 @@
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QWidget" name="balancersWidget" native="true">
<property name="geometry">
<rect>
<x>130</x>
<y>100</y>
<width>197</width>
<height>150</height>
</rect>
</property>
<layout class="QGridLayout" name="balancerLayout">
<item row="0" column="0">
<widget class="QComboBox" name="balancerSelectionCombo">
<property name="editable">
<bool>true</bool>
</property>
</widget>
<pixmapfunction/>
</item>
<item row="1" column="0" rowspan="2">
<widget class="QListWidget" name="balancerList"/>
</item>
<item row="1" column="1">
<widget class="QToolButton" name="balancerDelBtn">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="2" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QToolButton" name="balancerAddBtn">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -1,5 +1,15 @@
#include "RuleWidget.hpp"
#include "base/Qv2rayBase.hpp"
#include "common/QvHelpers.hpp"
#define LOAD_FLAG_END isLoading = false;
#define LOAD_FLAG_BEGIN isLoading = true;
#define LOADINGCHECK \
if (isLoading) \
return;
#define rule (*ruleptr)
QvNodeRuleWidget::QvNodeRuleWidget(QWidget *parent) : QWidget(parent)
{
setupUi(this);
@ -14,3 +24,235 @@ void QvNodeRuleWidget::changeEvent(QEvent *e)
default: break;
}
}
void QvNodeRuleWidget::ShowCurrentRuleDetail(std::shared_ptr<RuleObject> _ruleptr)
{
LOADINGCHECK
this->ruleptr = _ruleptr;
// Switch to the detailed page.
ruleEnableCB->setEnabled(true);
ruleEnableCB->setChecked(rule.QV2RAY_RULE_ENABLED);
ruleTagLineEdit->setEnabled(true);
ruleRenameBtn->setEnabled(true);
LOAD_FLAG_BEGIN
ruleTagLineEdit->setText(rule.QV2RAY_RULE_TAG);
// balancerSelectionCombo->clear();
// for (auto out : outbounds)
// {
// balancerSelectionCombo->addItem(getTag(OUTBOUND(out)));
// }
// //
// // Balancers combo and balancer list.
// enableBalancerCB->setChecked(CurrentRule.QV2RAY_RULE_USE_BALANCER);
// balancersWidget->setEnabled(CurrentRule.QV2RAY_RULE_USE_BALANCER);
// if (!CurrentRule.balancerTag.isEmpty())
// {
// balancerList->clear();
// balancerList->addItems(balancers[CurrentRule.balancerTag]);
// }
isLoading = false;
// Networks
auto network = rule.network.toLower();
bool isBoth = (network.contains("tcp") && network.contains("udp")) || network.isEmpty();
netUDPRB->setChecked(network.contains("udp"));
netTCPRB->setChecked(network.contains("tcp"));
netBothRB->setChecked(isBoth);
//
// Set protocol checkboxes.
auto protocol = rule.protocol;
routeProtocolHTTPCB->setChecked(protocol.contains("http"));
routeProtocolTLSCB->setChecked(protocol.contains("tls"));
routeProtocolBTCB->setChecked(protocol.contains("bittorrent"));
//
// Port
routePortTxt->setText(rule.port);
//
// Users
QString users = rule.user.join(NEWLINE);
routeUserTxt->setPlainText(users);
//
// Incoming Sources
QString sources = rule.source.join(NEWLINE);
sourceIPList->setPlainText(sources);
//
// Domains
QString domains = rule.domain.join(NEWLINE);
hostList->setPlainText(domains);
//
// Outcoming IPs
QString ips = rule.ip.join(NEWLINE);
ipList->setPlainText(ips);
LOAD_FLAG_END
}
void QvNodeRuleWidget::on_routeProtocolHTTPCB_stateChanged(int arg1)
{
LOADINGCHECK
QStringList protocols;
if (arg1 == Qt::Checked)
protocols.push_back("http");
if (routeProtocolTLSCB->isChecked())
protocols.push_back("tls");
if (routeProtocolBTCB->isChecked())
protocols.push_back("bittorrent");
rule.protocol = protocols;
}
void QvNodeRuleWidget::on_routeProtocolTLSCB_stateChanged(int arg1)
{
LOADINGCHECK
QStringList protocols;
if (arg1 == Qt::Checked)
protocols.push_back("tls");
if (routeProtocolHTTPCB->isChecked())
protocols.push_back("http");
if (routeProtocolBTCB->isChecked())
protocols.push_back("bittorrent");
rule.protocol = protocols;
}
void QvNodeRuleWidget::on_routeProtocolBTCB_stateChanged(int arg1)
{
LOADINGCHECK
QStringList protocols;
if (arg1 == Qt::Checked)
protocols.push_back("bittorrent");
if (routeProtocolHTTPCB->isChecked())
protocols.push_back("http");
if (routeProtocolTLSCB->isChecked())
protocols.push_back("tls");
rule.protocol = protocols;
}
void QvNodeRuleWidget::on_hostList_textChanged()
{
LOADINGCHECK
rule.domain = SplitLines(hostList->toPlainText());
}
void QvNodeRuleWidget::on_ipList_textChanged()
{
LOADINGCHECK
rule.ip = SplitLines(ipList->toPlainText());
}
void QvNodeRuleWidget::on_routePortTxt_textEdited(const QString &arg1)
{
LOADINGCHECK
rule.port = arg1;
}
void QvNodeRuleWidget::on_routeUserTxt_textEdited(const QString &arg1)
{
LOADINGCHECK
rule.user = SplitLines(arg1);
}
void QvNodeRuleWidget::on_netBothRB_clicked()
{
LOADINGCHECK
rule.network = "tcp,udp";
}
void QvNodeRuleWidget::on_netUDPRB_clicked()
{
LOADINGCHECK
rule.network = "udp";
}
void QvNodeRuleWidget::on_netTCPRB_clicked()
{
LOADINGCHECK
rule.network = "tcp";
}
void QvNodeRuleWidget::on_routeUserTxt_textChanged()
{
LOADINGCHECK
rule.user = SplitLines(routeUserTxt->toPlainText());
}
void QvNodeRuleWidget::on_sourceIPList_textChanged()
{
LOADINGCHECK
rule.source = SplitLines(sourceIPList->toPlainText());
}
void QvNodeRuleWidget::on_enableBalancerCB_stateChanged(int arg1)
{
// LOADINGCHECK
// auto useBalancer = arg1 == Qt::Checked;
// CurrentRule.QV2RAY_RULE_USE_BALANCER = useBalancer;
// // balancersWidget->setEnabled(useBalancer);
// // if (CurrentRule.balancerTag.isEmpty())
// // {
// // LOG(MODULE_UI, "Creating a new balancer tag.")
// // CurrentRule.balancerTag = GenerateRandomString(6);
// // balancers[CurrentRule.balancerTag] = QStringList();
// // }
// DEBUG(MODULE_UI, "Balancer: " + CurrentRule.balancerTag)
// if (useBalancer)
// {
// LOG(MODULE_UI, "A rule has been set to use balancer, disconnect it to any outbound.")
// auto ruleNode = ruleNodes[currentRuleTag];
// for (auto &&[_, conn] : nodeScene->connections())
// {
// if (conn->getNode(PortType::Out)->id() == ruleNode)
// {
// nodeScene->deleteConnection(*conn);
// // Since there should be only one connection from this rule node.
// break;
// }
// }
// }
// else
// {
// QvMessageBoxWarn(this, tr("Route Editor"), tr("To make this rule ready to use, you need to connect it to an outbound node."));
// }
}
void QvNodeRuleWidget::on_ruleRenameBtn_clicked()
{
abort();
// auto newTag = ruleTagLineEdit->text();
//
// if (newTag.isEmpty())
//{
// LOG(MODULE_UI, "Tag is empty, this is ILLEGAL!")
// QvMessageBoxWarn(this, tr("Renaming a tag"), tr("New tag is empty, please try another."));
//}
// else if (newTag == rule.QV2RAY_RULE_TAG)
//{
// LOG(MODULE_UI, "No tag changed, returning.")
// QvMessageBoxInfo(this, tr("Renaming a tag"), tr("New tag is the same as the original one."));
//}
// else if (rules.contains(newTag))
//{
// LOG(MODULE_UI, "Tag duplicate detected.")
// QvMessageBoxWarn(this, tr("Renaming a tag"), tr("Duplicate rule tag detected, please try another."));
//}
// else
//{
// RenameItemTag(RENAME_RULE, rule.QV2RAY_RULE_TAG, &newTag);
//}
}
void QvNodeRuleWidget::on_ruleEnableCB_stateChanged(int arg1)
{
bool _isEnabled = arg1 == Qt::Checked;
rule.QV2RAY_RULE_ENABLED = _isEnabled;
settingsFrame->setEnabled(isEnabled());
}
void QvNodeRuleWidget::on_toolButton_clicked()
{
settingsFrame->setVisible(!settingsFrame->isVisible());
adjustSize();
}

View File

@ -1,5 +1,6 @@
#pragma once
#include "base/Qv2rayBase.hpp"
#include "ui_RuleWidget.h"
class QvNodeRuleWidget
@ -10,7 +11,27 @@ class QvNodeRuleWidget
public:
explicit QvNodeRuleWidget(QWidget *parent = nullptr);
void ShowCurrentRuleDetail(std::shared_ptr<RuleObject> rule);
private slots:
void on_toolButton_clicked();
void on_routeProtocolHTTPCB_stateChanged(int arg1);
void on_routeProtocolTLSCB_stateChanged(int arg1);
void on_routeProtocolBTCB_stateChanged(int arg1);
void on_hostList_textChanged();
void on_ipList_textChanged();
void on_routePortTxt_textEdited(const QString &arg1);
void on_routeUserTxt_textEdited(const QString &arg1);
void on_netBothRB_clicked();
void on_netUDPRB_clicked();
void on_netTCPRB_clicked();
void on_routeUserTxt_textChanged();
void on_sourceIPList_textChanged();
void on_enableBalancerCB_stateChanged(int arg1);
void on_ruleRenameBtn_clicked();
void on_ruleEnableCB_stateChanged(int arg1);
protected:
void changeEvent(QEvent *e);
std::shared_ptr<RuleObject> ruleptr;
bool isLoading;
};

View File

@ -6,54 +6,21 @@
<rect>
<x>0</x>
<y>0</y>
<width>296</width>
<height>704</height>
<width>298</width>
<height>500</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Rule Status</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="ruleEnableCB">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Enabled</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Rule Tag</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="ruleTagLineEdit">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
<widget class="QLineEdit" name="ruleTagLineEdit"/>
</item>
<item>
<widget class="QPushButton" name="ruleRenameBtn">
<widget class="QToolButton" name="ruleRenameBtn">
<property name="enabled">
<bool>false</bool>
</property>
@ -64,19 +31,30 @@
</item>
</layout>
</item>
</layout>
<item>
<widget class="QCheckBox" name="ruleEnableCB">
<property name="text">
<string>Rule Enabled</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="routeEditGroupBox">
<property name="enabled">
<bool>false</bool>
<widget class="QToolButton" name="toolButton">
<property name="text">
<string>Show / Hide</string>
</property>
<property name="title">
<string>Route Editor</string>
</widget>
</item>
<item>
<widget class="QFrame" name="settingsFrame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="flat">
<bool>false</bool>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_17">
@ -156,74 +134,9 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Balancers</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="enableBalancerCB">
<property name="text">
<string>Use Balancers</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QWidget" name="balancersWidget" native="true">
<layout class="QGridLayout" name="balancerLayout">
<item row="0" column="0">
<widget class="QComboBox" name="balancerSelectionCombo">
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0" rowspan="2">
<widget class="QListWidget" name="balancerList"/>
</item>
<item row="1" column="1">
<widget class="QToolButton" name="balancerDelBtn">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="2" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QToolButton" name="balancerAddBtn">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="routeRuleGroupBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="title">
<string>Route Detail Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_15">
@ -266,6 +179,8 @@
<widget class="QPlainTextEdit" name="ipList"/>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>

View File

@ -5,7 +5,7 @@
void MainWindow::MWSetSystemProxy()
{
const auto inboundInfo = KernelInstance->GetInboundInfo();
const auto inboundInfo = KernelInstance->GetCurrentConnectionInboundInfo();
InboundInfoObject httpInboundInfo;
InboundInfoObject socksInboundInfo;