mirror of
https://github.com/Mahdi-zarei/nekoray.git
synced 2026-01-06 05:09:15 +08:00
feat: Continue implementing new route GUI
This commit is contained in:
parent
37f7bc55de
commit
215f0a17b0
@ -13,7 +13,7 @@ namespace NekoGui {
|
||||
return res;
|
||||
}
|
||||
|
||||
QJsonObject RouteRule::get_rule_json() const {
|
||||
QJsonObject RouteRule::get_rule_json(bool forView) const {
|
||||
QJsonObject obj;
|
||||
|
||||
if (ip_version != "") obj["ip_version"] = ip_version.toInt();
|
||||
@ -36,20 +36,24 @@ namespace NekoGui {
|
||||
if (!rule_set.empty()) obj["rule_set"] = get_as_array(rule_set);
|
||||
if (invert) obj["invert"] = invert;
|
||||
|
||||
switch (outboundID) { // TODO use constants
|
||||
case -2:
|
||||
obj["outbound"] = "direct";
|
||||
case -3:
|
||||
obj["outbound"] = "block";
|
||||
case -4:
|
||||
obj["outbound"] = "dns_out";
|
||||
default:
|
||||
auto prof = NekoGui::profileManager->GetProfile(outboundID);
|
||||
if (prof == nullptr) {
|
||||
MW_show_log("The outbound described in the rule chain is missing, maybe your data is corrupted");
|
||||
return {};
|
||||
}
|
||||
obj["outbound"] = prof->bean->DisplayName();
|
||||
if (forView) {
|
||||
switch (outboundID) { // TODO use constants
|
||||
case -2:
|
||||
obj["outbound"] = "direct";
|
||||
case -3:
|
||||
obj["outbound"] = "block";
|
||||
case -4:
|
||||
obj["outbound"] = "dns_out";
|
||||
default:
|
||||
auto prof = NekoGui::profileManager->GetProfile(outboundID);
|
||||
if (prof == nullptr) {
|
||||
MW_show_log("The outbound described in the rule chain is missing, maybe your data is corrupted");
|
||||
return {};
|
||||
}
|
||||
obj["outbound"] = prof->bean->DisplayName();
|
||||
}
|
||||
} else {
|
||||
obj["outbound"] = outboundID;
|
||||
}
|
||||
|
||||
return obj;
|
||||
@ -95,13 +99,13 @@ namespace NekoGui {
|
||||
|
||||
QStringList RouteRule::get_values_for_field(const QString& fieldName) {
|
||||
if (fieldName == "ip_version") {
|
||||
return {"4", "6"};
|
||||
return {"", "4", "6"};
|
||||
}
|
||||
if (fieldName == "network") {
|
||||
return {"tcp", "udp"};
|
||||
return {"", "tcp", "udp"};
|
||||
}
|
||||
if (fieldName == "protocol") {
|
||||
return {"http", "tls", "quic", "stun", "dns", "bittorrent"};
|
||||
return {"", "http", "tls", "quic", "stun", "dns", "bittorrent"};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@ -226,10 +230,10 @@ namespace NekoGui {
|
||||
}
|
||||
}
|
||||
|
||||
QJsonArray RoutingChain::get_route_rules() {
|
||||
QJsonArray RoutingChain::get_route_rules(bool forView) {
|
||||
QJsonArray res;
|
||||
for (const auto &item: Rules) {
|
||||
auto rule_json = item->get_rule_json();
|
||||
auto rule_json = item->get_rule_json(forView);
|
||||
if (rule_json.empty()) {
|
||||
MW_show_log("Aborted generating routing section, an error has occurred");
|
||||
return {};
|
||||
|
||||
@ -27,9 +27,9 @@ namespace NekoGui {
|
||||
QList<QString> process_path;
|
||||
QList<QString> rule_set;
|
||||
bool invert = false;
|
||||
int outboundID = -1; // -2 is direct -3 is block -4 is dns_out
|
||||
int outboundID = -1; // -1 is invalid -2 is direct -3 is block -4 is dns_out
|
||||
|
||||
[[nodiscard]] QJsonObject get_rule_json() const;
|
||||
[[nodiscard]] QJsonObject get_rule_json(bool forView = false) const;
|
||||
static QStringList get_attributes();
|
||||
static inputType get_input_type(const QString& fieldName);
|
||||
static QStringList get_values_for_field(const QString& fieldName);
|
||||
@ -44,7 +44,7 @@ namespace NekoGui {
|
||||
QString name = "";
|
||||
QList<std::shared_ptr<RouteRule>> Rules;
|
||||
|
||||
QJsonArray get_route_rules();
|
||||
QJsonArray get_route_rules(bool forView = false);
|
||||
|
||||
static std::shared_ptr<RoutingChain> GetDefaultChain();
|
||||
};
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
#include "db/RouteEntity.h"
|
||||
#include "db/Database.hpp"
|
||||
|
||||
#define ADJUST_SIZE runOnUiThread([=] { adjustSize(); adjustPosition(mainwindow); }, this);
|
||||
|
||||
int RouteItem::getIndexOf(const QString& name) const {
|
||||
for (int i=0;i<chain->Rules.size();i++) {
|
||||
@ -23,6 +22,18 @@ QString get_outbound_name(int id) {
|
||||
return "INVALID OUTBOUND";
|
||||
}
|
||||
|
||||
int get_outbound_id(const QString& name) {
|
||||
if (name == "direct") return -2;
|
||||
if (name == "block") return -3;
|
||||
if (name == "dns_out") return -4;
|
||||
auto profiles = NekoGui::profileManager->profiles;
|
||||
for (const auto& item: profiles) {
|
||||
if (item.second->bean->name == name) return item.first;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
QStringList get_all_outbounds() {
|
||||
QStringList res;
|
||||
auto profiles = NekoGui::profileManager->profiles;
|
||||
@ -40,7 +51,27 @@ RouteItem::RouteItem(QWidget *parent, const std::shared_ptr<NekoGui::RoutingChai
|
||||
// make a copy
|
||||
chain = routeChain;
|
||||
|
||||
for (const auto &item: chain->Rules) {
|
||||
std::map<QString, int> valueMap;
|
||||
for (auto &item: chain->Rules) {
|
||||
auto baseName = item->name;
|
||||
int randPart;
|
||||
if (baseName == "") {
|
||||
randPart = GetRandomUint64()%1000;
|
||||
baseName = "rule_" + Int2String(randPart);
|
||||
lastNum = std::max(lastNum, randPart);
|
||||
}
|
||||
while (true) {
|
||||
valueMap[baseName]++;
|
||||
if (valueMap[baseName] > 1) {
|
||||
valueMap[baseName]--;
|
||||
randPart = GetRandomUint64()%1000;
|
||||
baseName = "rule_" + Int2String(randPart);
|
||||
lastNum = std::max(lastNum, randPart);
|
||||
continue;
|
||||
}
|
||||
item->name = baseName;
|
||||
break;
|
||||
}
|
||||
ui->route_items->addItem(item->name);
|
||||
}
|
||||
|
||||
@ -52,6 +83,26 @@ RouteItem::RouteItem(QWidget *parent, const std::shared_ptr<NekoGui::RoutingChai
|
||||
ui->rule_attr_text->hide();
|
||||
ui->rule_attr_data->setTitle("");
|
||||
|
||||
connect(ui->route_name, &QLineEdit::textChanged, this, [=](const QString& text) {
|
||||
chain->name = text;
|
||||
});
|
||||
|
||||
connect(ui->route_view_json, &QPushButton::clicked, this, [=] {
|
||||
QString res;
|
||||
auto rules = chain->get_route_rules(true);
|
||||
for (int i=0;i<rules.size();i++) {
|
||||
auto item = rules[i];
|
||||
res += QJsonObject2QString(item.toObject(), false);
|
||||
if (i != rules.size()-1) res+=",\n";
|
||||
}
|
||||
MessageBoxInfo("JSON object", res);
|
||||
});
|
||||
|
||||
connect(ui->rule_name, &QLineEdit::textChanged, this, [=](const QString& text) {
|
||||
if (currentIndex == -1) return;
|
||||
chain->Rules[currentIndex]->name = text;
|
||||
});
|
||||
|
||||
connect(ui->rule_attr_selector, &QComboBox::currentTextChanged, this, [=](const QString& text){
|
||||
if (currentIndex == -1) return;
|
||||
chain->Rules[currentIndex]->set_field_value(ui->rule_attr->currentText(), {text});
|
||||
@ -63,12 +114,23 @@ RouteItem::RouteItem(QWidget *parent, const std::shared_ptr<NekoGui::RoutingChai
|
||||
chain->Rules[currentIndex]->set_field_value(ui->rule_attr->currentText(), currentVal);
|
||||
});
|
||||
|
||||
connect(ui->rule_out, &QComboBox::currentTextChanged, this, [=](const QString& text) {
|
||||
if (currentIndex == -1) return;
|
||||
auto id = get_outbound_id(text);
|
||||
if (id == -1) {
|
||||
MessageBoxWarning("Invalid state", "selected outbound does not exists in the database, try restarting the app.");
|
||||
return;
|
||||
}
|
||||
chain->Rules[currentIndex]->outboundID = id;
|
||||
});
|
||||
|
||||
connect(ui->route_items, &QListWidget::itemClicked, this, [=](const QListWidgetItem *item) {
|
||||
auto idx = getIndexOf(item->text());
|
||||
if (idx == -1) return;
|
||||
currentIndex = idx;
|
||||
auto ruleItem = chain->Rules[idx];
|
||||
ui->rule_out->setCurrentText(get_outbound_name(ruleItem->outboundID));
|
||||
setDefaultRuleData(ruleItem->ip_version);
|
||||
});
|
||||
|
||||
connect(ui->rule_attr, &QComboBox::currentTextChanged, this, [=](const QString& text){
|
||||
@ -96,12 +158,33 @@ RouteItem::RouteItem(QWidget *parent, const std::shared_ptr<NekoGui::RoutingChai
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
connect(ui->new_route_item, &QPushButton::clicked, this, &RouteItem::on_new_route_item_clicked);
|
||||
connect(ui->moveup_route_item, &QPushButton::clicked, this, &RouteItem::on_moveup_route_item_clicked);
|
||||
connect(ui->movedown_route_item, &QPushButton::clicked, this, &RouteItem::on_movedown_route_item_clicked);
|
||||
connect(ui->delete_route_item, &QPushButton::clicked, this, &RouteItem::on_delete_route_item_clicked);
|
||||
}
|
||||
|
||||
RouteItem::~RouteItem() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void RouteItem::updateRouteItemsView() {
|
||||
ui->route_items->clear();
|
||||
if (chain->Rules.empty()) return;
|
||||
|
||||
for (const auto& item: chain->Rules) {
|
||||
ui->route_items->addItem(item->name);
|
||||
}
|
||||
ui->route_items->setCurrentRow(currentIndex);
|
||||
}
|
||||
|
||||
void RouteItem::setDefaultRuleData(const QString& currentData) {
|
||||
ui->rule_attr->setCurrentText("ip_version");
|
||||
ui->rule_attr_data->setTitle("ip_version");
|
||||
showSelectItem(NekoGui::RouteRule::get_values_for_field("ip_version"), currentData);
|
||||
}
|
||||
|
||||
void RouteItem::showSelectItem(const QStringList& items, const QString& currentItem) {
|
||||
ui->rule_attr_text->hide();
|
||||
ui->rule_attr_selector->clear();
|
||||
@ -120,3 +203,38 @@ void RouteItem::showTextEnterItem(const QStringList& items) {
|
||||
ui->rule_attr_text->setText(items.join('\n'));
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
void RouteItem::on_new_route_item_clicked() {
|
||||
auto routeItem = std::make_shared<NekoGui::RouteRule>(NekoGui::RouteRule());
|
||||
routeItem->name = "rule_" + Int2String(++lastNum);
|
||||
chain->Rules << routeItem;
|
||||
currentIndex = chain->Rules.size() - 1;
|
||||
updateRouteItemsView();
|
||||
setDefaultRuleData("");
|
||||
}
|
||||
|
||||
void RouteItem::on_moveup_route_item_clicked() {
|
||||
if (currentIndex == -1 || currentIndex == 0) return;
|
||||
chain->Rules.swapItemsAt(currentIndex, currentIndex-1);
|
||||
currentIndex--;
|
||||
updateRouteItemsView();
|
||||
}
|
||||
|
||||
void RouteItem::on_movedown_route_item_clicked() {
|
||||
if (currentIndex == -1 || currentIndex == chain->Rules.size() - 1) return;
|
||||
chain->Rules.swapItemsAt(currentIndex, currentIndex+1);
|
||||
currentIndex++;
|
||||
updateRouteItemsView();
|
||||
}
|
||||
|
||||
void RouteItem::on_delete_route_item_clicked() {
|
||||
if (currentIndex == -1) return;
|
||||
chain->Rules.removeAt(currentIndex);
|
||||
if (chain->Rules.empty()) currentIndex = -1;
|
||||
else {
|
||||
currentIndex--;
|
||||
if (currentIndex == -1) currentIndex = 0;
|
||||
setDefaultRuleData(chain->Rules[currentIndex]->ip_version);
|
||||
}
|
||||
updateRouteItemsView();
|
||||
}
|
||||
@ -27,17 +27,23 @@ private:
|
||||
Ui::RouteItem *ui;
|
||||
int currentIndex = -1;
|
||||
|
||||
int lastNum;
|
||||
|
||||
[[nodiscard]] int getIndexOf(const QString& name) const;
|
||||
|
||||
void showSelectItem(const QStringList& items, const QString& currentItem);
|
||||
|
||||
void showTextEnterItem(const QStringList& items);
|
||||
|
||||
void setDefaultRuleData(const QString& currentData);
|
||||
|
||||
void updateRouteItemsView();
|
||||
|
||||
private slots:
|
||||
void on_ok_button_clicked();
|
||||
void on_cancel_button_clicked();
|
||||
void on_new_route_item_clicked();
|
||||
void on_moveup_route_item_clicked();
|
||||
void on_movedown_route_item_clicked();
|
||||
void on_route_view_json_clicked();
|
||||
void on_delete_route_item_clicked();
|
||||
};
|
||||
|
||||
@ -70,6 +70,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="delete_route_item">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -82,6 +89,16 @@
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_3" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="rule_name_l">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="rule_name"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="rule_attr_l">
|
||||
<property name="text">
|
||||
|
||||
Loading…
Reference in New Issue
Block a user