diff --git a/db/Database.cpp b/db/Database.cpp index 2423581..0172daf 100644 --- a/db/Database.cpp +++ b/db/Database.cpp @@ -88,6 +88,10 @@ namespace NekoGui { routes[id] = route; } + // Add default route chains + routes[IranBypassChainID] = RoutingChain::GetIranDefaultChain(); + routes[ChinaBypassChainID] = RoutingChain::GetChinaDefaultChain(); + // First setup if (groups.empty()) { auto defaultGroup = NekoGui::ProfileManager::NewGroup(); diff --git a/db/RouteEntity.cpp b/db/RouteEntity.cpp index 36e36dd..efbcbe4 100644 --- a/db/RouteEntity.cpp +++ b/db/RouteEntity.cpp @@ -297,16 +297,76 @@ namespace NekoGui { return res; } + bool RoutingChain::isViewOnly() const { + return id == IranBypassChainID || + id == ChinaBypassChainID; + } + std::shared_ptr RoutingChain::GetDefaultChain() { auto defaultChain = std::make_shared(); defaultChain->name = "Default"; auto defaultRule = std::make_shared(); + defaultRule->name = "Route DNS"; defaultRule->protocol = "dns"; defaultRule->outboundID = -4; defaultChain->Rules << defaultRule; return defaultChain; } + std::shared_ptr RoutingChain::GetIranDefaultChain() { + auto chain = std::make_shared(); + chain->name = "Bypass Iran"; + chain->id = IranBypassChainID; + chain->save_control_no_save = true; + + auto rule0 = std::make_shared(); + rule0->name = "Route DNS"; + rule0->protocol = "dns"; + rule0->outboundID = -4; + chain->Rules << rule0; + + auto rule1 = std::make_shared(); + rule1->rule_set << QString("ir_IP") << QString("category-ir_SITE"); + rule1->name = "Bypass Iran IPs and Domains"; + rule1->outboundID = -2; + chain->Rules << rule1; + + auto rule2 = std::make_shared(); + rule2->name = "Bypass Private IPs"; + rule2->ip_is_private = true; + rule1->outboundID = -2; + chain->Rules << rule2; + + return chain; + } + + std::shared_ptr RoutingChain::GetChinaDefaultChain() { + auto chain = std::make_shared(); + chain->name = "Bypass China"; + chain->id = ChinaBypassChainID; + chain->save_control_no_save = true; + + auto rule0 = std::make_shared(); + rule0->name = "Route DNS"; + rule0->protocol = "dns"; + rule0->outboundID = -4; + chain->Rules << rule0; + + auto rule1 = std::make_shared(); + rule1->name = "Bypass Chinese IPs and Domains"; + rule1->rule_set << QString("cn_IP") << QString("geolocation-cn_SITE"); + rule1->outboundID = -2; + chain->Rules << rule1; + + auto rule2 = std::make_shared(); + rule2->name = "Bypass Private IPs"; + rule2->ip_is_private = true; + rule1->outboundID = -2; + chain->Rules << rule2; + + return chain; + } + std::shared_ptr> RoutingChain::get_used_outbounds() { auto res = std::make_shared>(); for (const auto& item: Rules) { diff --git a/db/RouteEntity.h b/db/RouteEntity.h index 7e64fe9..2d24dcd 100644 --- a/db/RouteEntity.h +++ b/db/RouteEntity.h @@ -4,6 +4,8 @@ namespace NekoGui { enum inputType {trufalse, select, text}; + const int IranBypassChainID = 111111111; + const int ChinaBypassChainID = 222222222; class RouteRule : public JsonStore { public: @@ -60,8 +62,14 @@ namespace NekoGui { QJsonArray get_route_rules(bool forView = false, std::map outboundMap = {}); + bool isViewOnly() const; + static std::shared_ptr GetDefaultChain(); + static std::shared_ptr GetIranDefaultChain(); + + static std::shared_ptr GetChinaDefaultChain(); + std::shared_ptr> get_used_outbounds(); std::shared_ptr get_used_rule_sets(); diff --git a/ui/dialog_manage_routes.cpp b/ui/dialog_manage_routes.cpp index 8741905..1a55b20 100644 --- a/ui/dialog_manage_routes.cpp +++ b/ui/dialog_manage_routes.cpp @@ -166,6 +166,7 @@ void DialogManageRoutes::on_edit_route_clicked() { routeChainWidget->setWindowModality(Qt::ApplicationModal); routeChainWidget->show(); connect(routeChainWidget, &RouteItem::settingsChanged, this, [=](const std::shared_ptr& chain) { + if (chain->isViewOnly()) return; chainList[idx] = chain; reloadProfileItems(); }); @@ -181,6 +182,7 @@ void DialogManageRoutes::on_delete_route_clicked() { } auto profileToDel = chainList[idx]; + if (profileToDel->isViewOnly()) return; chainList.removeAt(idx); if (profileToDel->id == currentRouteProfileID) { currentRouteProfileID = chainList[0]->id; diff --git a/ui/widget/RouteItem.cpp b/ui/widget/RouteItem.cpp index cb277cb..d90730c 100644 --- a/ui/widget/RouteItem.cpp +++ b/ui/widget/RouteItem.cpp @@ -185,6 +185,16 @@ RouteItem::RouteItem(QWidget *parent, const std::shared_ptrisViewOnly()) { + ui->route_name->setText(chain->name + " (View only)"); + ui->route_name->setEnabled(false); + ui->rule_attr_box->setEnabled(false); + ui->new_route_item->setEnabled(false); + ui->moveup_route_item->setEnabled(false); + ui->movedown_route_item->setEnabled(false); + ui->delete_route_item->setEnabled(false); + } } RouteItem::~RouteItem() { @@ -255,7 +265,7 @@ void RouteItem::updateRuleSection() { } } ui->rule_name->setText(ruleItem->name); - ui->rule_attr_box->setEnabled(true); + ui->rule_attr_box->setDisabled(chain->isViewOnly()); ui->rule_out->setCurrentText(get_outbound_name(ruleItem->outboundID)); if (currentAttr == "rule_set") ui->rule_set_helper->show(); else ui->rule_set_helper->hide(); @@ -311,6 +321,7 @@ void RouteItem::applyRuleHelperSelect(const QModelIndex& index) { } void RouteItem::on_new_route_item_clicked() { + if (chain->isViewOnly()) return; auto routeItem = std::make_shared(); routeItem->name = "rule_" + Int2String(++lastNum); chain->Rules << routeItem; @@ -323,6 +334,7 @@ void RouteItem::on_new_route_item_clicked() { } void RouteItem::on_moveup_route_item_clicked() { + if (chain->isViewOnly()) return; if (currentIndex == -1 || currentIndex == 0) return; auto curr = chain->Rules[currentIndex]; chain->Rules[currentIndex] = chain->Rules[currentIndex-1]; @@ -332,6 +344,7 @@ void RouteItem::on_moveup_route_item_clicked() { } void RouteItem::on_movedown_route_item_clicked() { + if (chain->isViewOnly()) return; if (currentIndex == -1 || currentIndex == chain->Rules.size() - 1) return; auto curr = chain->Rules[currentIndex]; chain->Rules[currentIndex] = chain->Rules[currentIndex+1]; @@ -341,6 +354,7 @@ void RouteItem::on_movedown_route_item_clicked() { } void RouteItem::on_delete_route_item_clicked() { + if (chain->isViewOnly()) return; if (currentIndex == -1) return; chain->Rules.removeAt(currentIndex); if (chain->Rules.empty()) currentIndex = -1;